mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-23 04:08:36 -05:00
commit
7fb66b6998
@ -6,7 +6,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
SET(CUBICSDR_VERSION_MAJOR "0")
|
||||
SET(CUBICSDR_VERSION_MINOR "2")
|
||||
SET(CUBICSDR_VERSION_PATCH "2")
|
||||
SET(CUBICSDR_VERSION_PATCH "3")
|
||||
SET(CUBICSDR_VERSION_SUFFIX "")
|
||||
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}${CUBICSDR_VERSION_SUFFIX}")
|
||||
|
||||
@ -347,6 +347,10 @@ SET (cubicsdr_sources
|
||||
src/modules/modem/analog/ModemLSB.cpp
|
||||
src/modules/modem/analog/ModemUSB.cpp
|
||||
src/audio/AudioThread.cpp
|
||||
src/audio/AudioSinkThread.cpp
|
||||
src/audio/AudioSinkFileThread.cpp
|
||||
src/audio/AudioFile.cpp
|
||||
src/audio/AudioFileWAV.cpp
|
||||
src/util/Gradient.cpp
|
||||
src/util/Timer.cpp
|
||||
src/util/MouseTracker.cpp
|
||||
@ -451,6 +455,10 @@ SET (cubicsdr_headers
|
||||
src/modules/modem/analog/ModemLSB.h
|
||||
src/modules/modem/analog/ModemUSB.h
|
||||
src/audio/AudioThread.h
|
||||
src/audio/AudioSinkThread.h
|
||||
src/audio/AudioSinkFileThread.h
|
||||
src/audio/AudioFile.h
|
||||
src/audio/AudioFileWAV.h
|
||||
src/util/Gradient.h
|
||||
src/util/Timer.h
|
||||
src/util/ThreadBlockingQueue.h
|
||||
@ -995,7 +1003,7 @@ IF (WIN32 AND BUILD_INSTALLER)
|
||||
|
||||
IF (MSVC)
|
||||
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/external/msvc/${EX_PLATFORM_NAME}/vc_redist.${EX_PLATFORM_NAME}.exe DESTINATION vc_redist)
|
||||
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\vc_redist\\\\vc_redist.${EX_PLATFORM_NAME}.exe\\\" /q:a'")
|
||||
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\vc_redist\\\\vc_redist.${EX_PLATFORM_NAME}.exe\\\" /passive /norestart'")
|
||||
ENDIF (MSVC)
|
||||
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "AppConfig.h"
|
||||
#include "CubicSDR.h"
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
DeviceConfig::DeviceConfig() : deviceId("") {
|
||||
ppm.store(0);
|
||||
offset.store(0);
|
||||
@ -505,6 +507,51 @@ bool AppConfig::getBookmarksVisible() {
|
||||
return bookmarksVisible.load();
|
||||
}
|
||||
|
||||
void AppConfig::setRecordingPath(std::string recPath) {
|
||||
recordingPath = recPath;
|
||||
}
|
||||
|
||||
std::string AppConfig::getRecordingPath() {
|
||||
return recordingPath;
|
||||
}
|
||||
|
||||
bool AppConfig::verifyRecordingPath() {
|
||||
string recPathStr = wxGetApp().getConfig()->getRecordingPath();
|
||||
|
||||
if (recPathStr.empty()) {
|
||||
wxMessageBox( wxT("Recording path is not set. Please use 'Set Recording Path' from the 'File' Menu."), wxT("Recording Path Error"), wxICON_INFORMATION);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxFileName recPath(recPathStr);
|
||||
|
||||
if (!recPath.Exists() || !recPath.IsDirWritable()) {
|
||||
wxMessageBox( wxT("Recording path does not exist or is not writable. Please use 'Set Recording Path' from the 'File' Menu."), wxT("Recording Path Error"), wxICON_INFORMATION);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void AppConfig::setRecordingSquelchOption(int enumChoice) {
|
||||
recordingSquelchOption = enumChoice;
|
||||
}
|
||||
|
||||
int AppConfig::getRecordingSquelchOption() {
|
||||
return recordingSquelchOption;
|
||||
}
|
||||
|
||||
void AppConfig::setRecordingFileTimeLimit(int nbSeconds) {
|
||||
recordingFileTimeLimitSeconds = nbSeconds;
|
||||
}
|
||||
|
||||
int AppConfig::getRecordingFileTimeLimit() {
|
||||
return recordingFileTimeLimitSeconds;
|
||||
}
|
||||
|
||||
|
||||
void AppConfig::setConfigName(std::string configName) {
|
||||
this->configName = configName;
|
||||
@ -559,6 +606,12 @@ bool AppConfig::save() {
|
||||
*window_node->newChild("bookmark_visible") = bookmarksVisible.load();
|
||||
}
|
||||
|
||||
//Recording settings:
|
||||
DataNode *rec_node = cfg.rootNode()->newChild("recording");
|
||||
*rec_node->newChild("path") = recordingPath;
|
||||
*rec_node->newChild("squelch") = recordingSquelchOption;
|
||||
*rec_node->newChild("file_time_limit") = recordingFileTimeLimitSeconds;
|
||||
|
||||
DataNode *devices_node = cfg.rootNode()->newChild("devices");
|
||||
|
||||
std::map<std::string, DeviceConfig *>::iterator device_config_i;
|
||||
@ -741,6 +794,26 @@ bool AppConfig::load() {
|
||||
}
|
||||
}
|
||||
|
||||
//Recording settings:
|
||||
if (cfg.rootNode()->hasAnother("recording")) {
|
||||
DataNode *rec_node = cfg.rootNode()->getNext("recording");
|
||||
|
||||
if (rec_node->hasAnother("path")) {
|
||||
DataNode *rec_path = rec_node->getNext("path");
|
||||
recordingPath = rec_path->element()->toString();
|
||||
}
|
||||
|
||||
if (rec_node->hasAnother("squelch")) {
|
||||
DataNode *rec_squelch = rec_node->getNext("squelch");
|
||||
rec_squelch->element()->get(recordingSquelchOption);
|
||||
}
|
||||
|
||||
if (rec_node->hasAnother("file_time_limit")) {
|
||||
DataNode *rec_file_time_limit = rec_node->getNext("file_time_limit");
|
||||
rec_file_time_limit->element()->get(recordingFileTimeLimitSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.rootNode()->hasAnother("devices")) {
|
||||
DataNode *devices_node = cfg.rootNode()->getNext("devices");
|
||||
|
||||
|
@ -138,6 +138,16 @@ public:
|
||||
void setBookmarksVisible(bool state);
|
||||
bool getBookmarksVisible();
|
||||
|
||||
//Recording settings:
|
||||
void setRecordingPath(std::string recPath);
|
||||
std::string getRecordingPath();
|
||||
bool verifyRecordingPath();
|
||||
|
||||
void setRecordingSquelchOption(int enumChoice);
|
||||
int getRecordingSquelchOption();
|
||||
|
||||
void setRecordingFileTimeLimit(int nbSeconds);
|
||||
int getRecordingFileTimeLimit();
|
||||
|
||||
#if USE_HAMLIB
|
||||
int getRigModel();
|
||||
@ -185,6 +195,10 @@ private:
|
||||
std::atomic_int dbOffset;
|
||||
std::vector<SDRManualDef> manualDevices;
|
||||
std::atomic_bool bookmarksVisible;
|
||||
|
||||
std::string recordingPath = "";
|
||||
int recordingSquelchOption = 0;
|
||||
int recordingFileTimeLimitSeconds = 0;
|
||||
#if USE_HAMLIB
|
||||
std::atomic_int rigModel, rigRate;
|
||||
std::string rigPort;
|
||||
|
326
src/AppFrame.cpp
326
src/AppFrame.cpp
@ -18,12 +18,13 @@
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "AudioThread.h"
|
||||
#include "AudioSinkFileThread.h"
|
||||
#include "CubicSDR.h"
|
||||
#include "DataTree.h"
|
||||
#include "ColorTheme.h"
|
||||
#include "DemodulatorMgr.h"
|
||||
#include "ImagePanel.h"
|
||||
#include "ActionDialog.h"
|
||||
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
@ -53,6 +54,22 @@ wxEND_EVENT_TABLE()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
class ActionDialogBookmarkReset : public ActionDialog {
|
||||
public:
|
||||
ActionDialogBookmarkReset() : ActionDialog(wxGetApp().getAppFrame(), wxID_ANY, wxT("Reset Bookmarks?")) {
|
||||
m_questionText->SetLabelText(wxT("Resetting bookmarks will erase all current bookmarks; are you sure?"));
|
||||
}
|
||||
|
||||
void doClickOK() {
|
||||
wxGetApp().getBookmarkMgr().resetBookmarks();
|
||||
wxGetApp().getBookmarkMgr().updateBookmarks();
|
||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* split a string by 'seperator' into a vector of string */
|
||||
std::vector<std::string> str_explode(const std::string &seperator, const std::string &in_str);
|
||||
|
||||
@ -402,49 +419,13 @@ AppFrame::AppFrame() :
|
||||
|
||||
// Make a menubar
|
||||
menuBar = new wxMenuBar;
|
||||
wxMenu *menu = new wxMenu;
|
||||
#ifndef __APPLE__
|
||||
#ifdef CUBICSDR_ENABLE_ABOUT_DIALOG
|
||||
menu->Append(wxID_ABOUT_CUBICSDR, "About " CUBICSDR_INSTALL_NAME);
|
||||
#endif
|
||||
#endif
|
||||
menu->Append(wxID_SDR_DEVICES, "SDR Devices");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_SDR_START_STOP, "Stop / Start Device");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_OPEN, "&Open Session");
|
||||
menu->Append(wxID_SAVE, "&Save Session");
|
||||
menu->Append(wxID_SAVEAS, "Save Session &As..");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_RESET, "&Reset Session");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_OPEN_BOOKMARKS, "Open Bookmarks");
|
||||
menu->Append(wxID_SAVE_BOOKMARKS, "Save Bookmarks");
|
||||
menu->Append(wxID_SAVEAS_BOOKMARKS, "Save Bookmarks As..");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_RESET_BOOKMARKS, "Reset Bookmarks");
|
||||
|
||||
#ifndef __APPLE__
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_CLOSE);
|
||||
#else
|
||||
#ifdef CUBICSDR_ENABLE_ABOUT_DIALOG
|
||||
if ( wxApp::s_macAboutMenuItemId != wxID_NONE ) {
|
||||
wxString aboutLabel;
|
||||
aboutLabel.Printf(_("About %s"), CUBICSDR_INSTALL_NAME);
|
||||
menu->Append( wxApp::s_macAboutMenuItemId, aboutLabel);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
menuBar->Append(menu, wxT("&File"));
|
||||
|
||||
menuBar->Append(makeFileMenu(), wxT("&File"));
|
||||
|
||||
settingsMenu = new wxMenu;
|
||||
|
||||
menuBar->Append(settingsMenu, wxT("&Settings"));
|
||||
|
||||
menu = new wxMenu;
|
||||
|
||||
std::vector<RtAudio::DeviceInfo>::iterator devices_i;
|
||||
std::map<int, RtAudio::DeviceInfo>::iterator mdevices_i;
|
||||
AudioThread::enumerateDevices(devices);
|
||||
@ -478,7 +459,7 @@ AppFrame::AppFrame() :
|
||||
menuBar->Append(sampleRateMenu, wxT("Sample &Rate"));
|
||||
|
||||
// Audio Sample Rates
|
||||
menu = new wxMenu;
|
||||
wxMenu *audioSampleRateMenu = new wxMenu;
|
||||
|
||||
#define NUM_RATES_DEFAULT 4
|
||||
unsigned int desired_rates[NUM_RATES_DEFAULT] = { 48000, 44100, 96000, 192000 };
|
||||
@ -508,7 +489,7 @@ AppFrame::AppFrame() :
|
||||
for (mdevices_i = outputDevices.begin(); mdevices_i != outputDevices.end(); mdevices_i++) {
|
||||
int menu_id = wxID_AUDIO_BANDWIDTH_BASE + wxID_AUDIO_DEVICE_MULTIPLIER * mdevices_i->first;
|
||||
wxMenu *subMenu = new wxMenu;
|
||||
menu->AppendSubMenu(subMenu, mdevices_i->second.name, wxT("Description?"));
|
||||
audioSampleRateMenu->AppendSubMenu(subMenu, mdevices_i->second.name, wxT("Description?"));
|
||||
|
||||
int j = 0;
|
||||
for (std::vector<unsigned int>::iterator srate = mdevices_i->second.sampleRates.begin(); srate != mdevices_i->second.sampleRates.end();
|
||||
@ -526,7 +507,12 @@ AppFrame::AppFrame() :
|
||||
}
|
||||
}
|
||||
|
||||
menuBar->Append(menu, wxT("Audio &Sample Rate"));
|
||||
menuBar->Append(audioSampleRateMenu, wxT("Audio &Sample Rate"));
|
||||
|
||||
//Add a Recording menu
|
||||
menuBar->Append(makeRecordingMenu(), wxT("Recordin&g"));
|
||||
//
|
||||
updateRecordingMenu();
|
||||
|
||||
//Add Display menu
|
||||
displayMenu = new wxMenu;
|
||||
@ -535,7 +521,7 @@ AppFrame::AppFrame() :
|
||||
|
||||
int fontScale = wxGetApp().getConfig()->getFontScale();
|
||||
|
||||
fontMenu->AppendRadioItem(wxID_DISPLAY_BASE, "Normal")->Check(GLFont::GLFONT_SCALE_NORMAL == fontScale);
|
||||
fontMenu->AppendRadioItem(wxID_DISPLAY_BASE, "Default")->Check(GLFont::GLFONT_SCALE_NORMAL == fontScale);
|
||||
fontMenu->AppendRadioItem(wxID_DISPLAY_BASE + 1, "1.5x")->Check(GLFont::GLFONT_SCALE_MEDIUM == fontScale);
|
||||
fontMenu->AppendRadioItem(wxID_DISPLAY_BASE + 2, "2.0x")->Check(GLFont::GLFONT_SCALE_LARGE == fontScale);
|
||||
|
||||
@ -729,6 +715,137 @@ AppFrame::~AppFrame() {
|
||||
t_FFTData->join();
|
||||
}
|
||||
|
||||
wxMenu *AppFrame::makeFileMenu() {
|
||||
|
||||
wxMenu *menu = new wxMenu;
|
||||
#ifndef __APPLE__
|
||||
#ifdef CUBICSDR_ENABLE_ABOUT_DIALOG
|
||||
menu->Append(wxID_ABOUT_CUBICSDR, "About " CUBICSDR_INSTALL_NAME);
|
||||
#endif
|
||||
#endif
|
||||
menu->Append(wxID_SDR_DEVICES, "SDR Devices");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_SDR_START_STOP, "Stop / Start Device");
|
||||
menu->AppendSeparator();
|
||||
|
||||
wxMenu *sessionMenu = new wxMenu;
|
||||
|
||||
sessionMenu->Append(wxID_OPEN, "&Open Session");
|
||||
sessionMenu->Append(wxID_SAVE, "&Save Session");
|
||||
sessionMenu->Append(wxID_SAVEAS, "Save Session &As..");
|
||||
sessionMenu->AppendSeparator();
|
||||
sessionMenu->Append(wxID_RESET, "&Reset Session");
|
||||
|
||||
menu->AppendSubMenu(sessionMenu, "Session");
|
||||
|
||||
menu->AppendSeparator();
|
||||
|
||||
wxMenu *bookmarkMenu = new wxMenu;
|
||||
|
||||
bookmarkMenu->Append(wxID_OPEN_BOOKMARKS, "Open Bookmarks");
|
||||
bookmarkMenu->Append(wxID_SAVE_BOOKMARKS, "Save Bookmarks");
|
||||
bookmarkMenu->Append(wxID_SAVEAS_BOOKMARKS, "Save Bookmarks As..");
|
||||
bookmarkMenu->AppendSeparator();
|
||||
bookmarkMenu->Append(wxID_RESET_BOOKMARKS, "Reset Bookmarks");
|
||||
|
||||
menu->AppendSubMenu(bookmarkMenu, "Bookmarks");
|
||||
|
||||
#ifndef __APPLE__
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_CLOSE);
|
||||
#else
|
||||
#ifdef CUBICSDR_ENABLE_ABOUT_DIALOG
|
||||
if (wxApp::s_macAboutMenuItemId != wxID_NONE) {
|
||||
wxString aboutLabel;
|
||||
aboutLabel.Printf(_("About %s"), CUBICSDR_INSTALL_NAME);
|
||||
menu->Append(wxApp::s_macAboutMenuItemId, aboutLabel);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
fileMenu = menu;
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
wxMenu *AppFrame::makeRecordingMenu() {
|
||||
|
||||
recordingMenuItems.clear();
|
||||
|
||||
wxMenu *menu = new wxMenu;
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_PATH] = menu->Append(wxID_RECORDING_PATH, getSettingsLabel("Set Recording Path", "<Not Set>"));
|
||||
|
||||
menu->AppendSeparator();
|
||||
|
||||
//Squelch options as sub-menu:
|
||||
wxMenu *subMenu = new wxMenu;
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_BASE] = menu->AppendSubMenu(subMenu, "Squelch");
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_SILENCE] = subMenu->AppendRadioItem(wxID_RECORDING_SQUELCH_SILENCE, "Record Silence",
|
||||
"Record below squelch-break audio as silence, i.e records as the user may hear.");
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_SKIP] = subMenu->AppendRadioItem(wxID_RECORDING_SQUELCH_SKIP, "Skip Silence",
|
||||
"Do not record below squelch-break audio, i.e squelch-break audio parts are packed together.");
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_ALWAYS] = subMenu->AppendRadioItem(wxID_RECORDING_SQUELCH_ALWAYS, "Record Always",
|
||||
"Record everything irrespective of the squelch level.");
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_FILE_TIME_LIMIT] = menu->Append(wxID_RECORDING_FILE_TIME_LIMIT, getSettingsLabel("File time limit", "<Not Set>"),
|
||||
"Creates a new file automatically, each time the recording lasts longer than the limit, named according to the current time.");
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_SILENCE]->Check(true);
|
||||
|
||||
recordingMenu = menu;
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void AppFrame::updateRecordingMenu() {
|
||||
|
||||
// Recording path:
|
||||
std::string recPath = wxGetApp().getConfig()->getRecordingPath();
|
||||
if (recPath.length() > 32) {
|
||||
recPath = "..." + recPath.substr(recPath.length() - 32, 32);
|
||||
}
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_PATH]->SetItemLabel(getSettingsLabel("Set Recording Path", recPath.empty() ? "<Not Set>" : recPath));
|
||||
|
||||
//Squelch options:
|
||||
int squelchEnumValue = wxGetApp().getConfig()->getRecordingSquelchOption();
|
||||
|
||||
if (squelchEnumValue == AudioSinkFileThread::SQUELCH_RECORD_SILENCE) {
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_SILENCE]->Check(true);
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_BASE]->SetItemLabel(getSettingsLabel("Squelch", "Record Silence"));
|
||||
|
||||
} else if (squelchEnumValue == AudioSinkFileThread::SQUELCH_SKIP_SILENCE) {
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_SKIP]->Check(true);
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_BASE]->SetItemLabel(getSettingsLabel("Squelch", "Skip Silence"));
|
||||
|
||||
} else if (squelchEnumValue == AudioSinkFileThread::SQUELCH_RECORD_ALWAYS) {
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_ALWAYS]->Check(true);
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_BASE]->SetItemLabel(getSettingsLabel("Squelch", "Record Always"));
|
||||
}
|
||||
else {
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_SILENCE]->Check(true);
|
||||
recordingMenuItems[wxID_RECORDING_SQUELCH_BASE]->SetItemLabel(getSettingsLabel("Squelch", "Record Silence"));
|
||||
|
||||
}
|
||||
|
||||
//File time limit:
|
||||
int fileTimeLimitSeconds = wxGetApp().getConfig()->getRecordingFileTimeLimit();
|
||||
|
||||
if (fileTimeLimitSeconds <= 0) {
|
||||
|
||||
recordingMenuItems[wxID_RECORDING_FILE_TIME_LIMIT]->SetItemLabel(getSettingsLabel("File time limit","<Not Set>"));
|
||||
}
|
||||
else {
|
||||
recordingMenuItems[wxID_RECORDING_FILE_TIME_LIMIT]->SetItemLabel(getSettingsLabel("File time limit",
|
||||
std::to_string(fileTimeLimitSeconds), "s"));
|
||||
}
|
||||
}
|
||||
|
||||
void AppFrame::initDeviceParams(SDRDeviceInfo *devInfo) {
|
||||
this->devInfo = devInfo;
|
||||
deviceChanged.store(true);
|
||||
@ -1480,16 +1597,81 @@ bool AppFrame::actionOnMenuLoadSave(wxCommandEvent& event) {
|
||||
}
|
||||
else if (event.GetId() == wxID_RESET_BOOKMARKS) {
|
||||
|
||||
wxGetApp().getBookmarkMgr().resetBookmarks();
|
||||
wxGetApp().getBookmarkMgr().updateBookmarks();
|
||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||
|
||||
ActionDialog::showDialog(new ActionDialogBookmarkReset());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AppFrame::actionOnMenuRecording(wxCommandEvent& event) {
|
||||
|
||||
if (event.GetId() == wxID_RECORDING_PATH) {
|
||||
|
||||
std::string recPath = wxGetApp().getConfig()->getRecordingPath();
|
||||
|
||||
wxDirDialog recPathDialog(this, _("File Path for Recordings"), recPath, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
|
||||
if (recPathDialog.ShowModal() == wxID_CANCEL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
wxGetApp().getConfig()->setRecordingPath(recPathDialog.GetPath().ToStdString());
|
||||
|
||||
updateRecordingMenu();
|
||||
return true;
|
||||
|
||||
}
|
||||
else if (event.GetId() == wxID_RECORDING_SQUELCH_SILENCE) {
|
||||
|
||||
wxGetApp().getConfig()->setRecordingSquelchOption(AudioSinkFileThread::SQUELCH_RECORD_SILENCE);
|
||||
|
||||
updateRecordingMenu();
|
||||
return true;
|
||||
}
|
||||
else if (event.GetId() == wxID_RECORDING_SQUELCH_SKIP) {
|
||||
|
||||
wxGetApp().getConfig()->setRecordingSquelchOption(AudioSinkFileThread::SQUELCH_SKIP_SILENCE);
|
||||
|
||||
updateRecordingMenu();
|
||||
return true;
|
||||
}
|
||||
else if (event.GetId() == wxID_RECORDING_SQUELCH_ALWAYS) {
|
||||
|
||||
wxGetApp().getConfig()->setRecordingSquelchOption(AudioSinkFileThread::SQUELCH_RECORD_ALWAYS);
|
||||
|
||||
updateRecordingMenu();
|
||||
return true;
|
||||
}
|
||||
else if (event.GetId() == wxID_RECORDING_FILE_TIME_LIMIT) {
|
||||
|
||||
int currentFileLimitSeconds = wxGetApp().getConfig()->getRecordingFileTimeLimit();
|
||||
|
||||
long newFileLimit = wxGetNumberFromUser(wxString("\nFile time limit:\n") +
|
||||
"\nCreates a new file automatically, each time the recording lasts longer than the limit, named according to the current time.\n\n " +
|
||||
+ "min: 0 s (no limit)"
|
||||
+ ", max: 36000 s (10 hours)\n",
|
||||
"Time in seconds",
|
||||
"File Time Limit",
|
||||
//If a manual sample rate has already been input, recall this one.
|
||||
currentFileLimitSeconds > 0 ? currentFileLimitSeconds : 0,
|
||||
0,
|
||||
36000,
|
||||
this);
|
||||
|
||||
if (newFileLimit != -1) {
|
||||
|
||||
wxGetApp().getConfig()->setRecordingFileTimeLimit((int)newFileLimit);
|
||||
|
||||
updateRecordingMenu();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AppFrame::actionOnMenuRig(wxCommandEvent& event) {
|
||||
|
||||
bool bManaged = false;
|
||||
@ -1709,9 +1891,12 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||
else if (actionOnMenuAudioSampleRate(event)) {
|
||||
return;
|
||||
}
|
||||
else if (actionOnMenuDisplay(event)) {
|
||||
else if (actionOnMenuRecording(event)) {
|
||||
return;
|
||||
}
|
||||
else if (actionOnMenuDisplay(event)) {
|
||||
return;
|
||||
}
|
||||
//Optional : Rig
|
||||
else if (actionOnMenuRig(event)) {
|
||||
return;
|
||||
@ -2576,6 +2761,7 @@ int AppFrame::OnGlobalKeyDown(wxKeyEvent &event) {
|
||||
case 'S':
|
||||
case 'P':
|
||||
case 'M':
|
||||
case 'R':
|
||||
return 1;
|
||||
case '0':
|
||||
case '1':
|
||||
@ -2716,6 +2902,13 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) {
|
||||
wxGetApp().setSoloMode(!wxGetApp().getSoloMode());
|
||||
return 1;
|
||||
break;
|
||||
case 'R':
|
||||
if (event.ShiftDown()) {
|
||||
toggleAllActiveDemodRecording();
|
||||
} else {
|
||||
toggleActiveDemodRecording();
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
wxGetApp().getSpectrumProcessor()->setPeakHold(!wxGetApp().getSpectrumProcessor()->getPeakHold());
|
||||
if (wxGetApp().getDemodSpectrumProcessor()) {
|
||||
@ -2760,6 +2953,43 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void AppFrame::toggleActiveDemodRecording() {
|
||||
if (!wxGetApp().getConfig()->verifyRecordingPath()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||
|
||||
if (activeDemod) {
|
||||
activeDemod->setRecording(!activeDemod->isRecording());
|
||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||
}
|
||||
}
|
||||
|
||||
void AppFrame::toggleAllActiveDemodRecording() {
|
||||
if (!wxGetApp().getConfig()->verifyRecordingPath()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto activeDemods = wxGetApp().getDemodMgr().getDemodulators();
|
||||
|
||||
bool stateToSet = true;
|
||||
|
||||
for (auto i : activeDemods) {
|
||||
if (i->isActive() && i->isRecording()) {
|
||||
stateToSet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i : activeDemods) {
|
||||
if (i->isActive() && i->isRecording() != stateToSet) {
|
||||
i->setRecording(stateToSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AppFrame::setWaterfallLinesPerSecond(int lps) {
|
||||
waterfallSpeedMeter->setUserInputValue(sqrt(lps));
|
||||
|
@ -76,6 +76,13 @@
|
||||
|
||||
#define wxID_DEVICE_ID 3500
|
||||
|
||||
#define wxID_RECORDING_PATH 8500
|
||||
#define wxID_RECORDING_SQUELCH_BASE 8501
|
||||
#define wxID_RECORDING_SQUELCH_SILENCE 8502
|
||||
#define wxID_RECORDING_SQUELCH_SKIP 8503
|
||||
#define wxID_RECORDING_SQUELCH_ALWAYS 8504
|
||||
#define wxID_RECORDING_FILE_TIME_LIMIT 8505
|
||||
|
||||
#define wxID_AUDIO_BANDWIDTH_BASE 9000
|
||||
#define wxID_AUDIO_DEVICE_MULTIPLIER 50
|
||||
|
||||
@ -101,6 +108,11 @@ public:
|
||||
AppFrame();
|
||||
~AppFrame();
|
||||
|
||||
wxMenu *makeFileMenu();
|
||||
|
||||
wxMenu *makeRecordingMenu();
|
||||
void updateRecordingMenu();
|
||||
|
||||
void initDeviceParams(SDRDeviceInfo *devInfo);
|
||||
void updateDeviceParams();
|
||||
|
||||
@ -119,6 +131,9 @@ public:
|
||||
int OnGlobalKeyDown(wxKeyEvent &event);
|
||||
int OnGlobalKeyUp(wxKeyEvent &event);
|
||||
|
||||
void toggleActiveDemodRecording();
|
||||
void toggleAllActiveDemodRecording();
|
||||
|
||||
void setWaterfallLinesPerSecond(int lps);
|
||||
void setSpectrumAvgSpeed(double avg);
|
||||
|
||||
@ -171,6 +186,7 @@ private:
|
||||
bool actionOnMenuAudioSampleRate(wxCommandEvent& event);
|
||||
bool actionOnMenuDisplay(wxCommandEvent& event);
|
||||
bool actionOnMenuLoadSave(wxCommandEvent& event);
|
||||
bool actionOnMenuRecording(wxCommandEvent& event);
|
||||
bool actionOnMenuRig(wxCommandEvent& event);
|
||||
|
||||
wxString getSettingsLabel(const std::string& settingsName,
|
||||
@ -205,6 +221,7 @@ private:
|
||||
std::vector<RtAudio::DeviceInfo> devices;
|
||||
std::map<int,RtAudio::DeviceInfo> inputDevices;
|
||||
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
||||
|
||||
std::map<int, wxMenuItem *> outputDeviceMenuItems;
|
||||
std::map<int, wxMenuItem *> sampleRateMenuItems;
|
||||
std::map<int, wxMenuItem *> antennaMenuItems;
|
||||
@ -214,6 +231,10 @@ private:
|
||||
std::map<int, wxMenuItem *> settingsMenuItems;
|
||||
|
||||
std::map<int, wxMenuItem *> audioSampleRateMenuItems;
|
||||
|
||||
//
|
||||
std::map<int, wxMenuItem *> recordingMenuItems;
|
||||
|
||||
std::map<int, wxMenuItem *> directSamplingMenuItems;
|
||||
wxMenuBar *menuBar;
|
||||
|
||||
@ -222,7 +243,9 @@ private:
|
||||
wxMenuItem *agcMenuItem = nullptr;
|
||||
wxMenuItem *iqSwapMenuItem = nullptr;
|
||||
wxMenuItem *lowPerfMenuItem = nullptr;
|
||||
wxMenu *fileMenu = nullptr;
|
||||
wxMenu *settingsMenu = nullptr;
|
||||
wxMenu *recordingMenu = nullptr;
|
||||
|
||||
SoapySDR::ArgInfoList settingArgs;
|
||||
int settingsIdMax;
|
||||
|
@ -415,7 +415,11 @@ bool BookmarkMgr::getExpandState(std::string groupName) {
|
||||
|
||||
void BookmarkMgr::updateActiveList() {
|
||||
|
||||
std::lock_guard < std::recursive_mutex > lockData(busy_lock);
|
||||
std::lock_guard < std::recursive_mutex > lockData(busy_lock);
|
||||
|
||||
if (wxGetApp().isShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BookmarkView *bmv = wxGetApp().getAppFrame()->getBookmarkView();
|
||||
|
||||
|
@ -203,6 +203,7 @@ CubicSDR::CubicSDR() : frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFA
|
||||
sampleRateInitialized.store(false);
|
||||
agcMode.store(true);
|
||||
soloMode.store(false);
|
||||
shuttingDown.store(false);
|
||||
fdlgTarget = FrequencyDialog::FDIALOG_TARGET_DEFAULT;
|
||||
stoppedDev = nullptr;
|
||||
}
|
||||
@ -384,6 +385,8 @@ bool CubicSDR::OnInit() {
|
||||
}
|
||||
|
||||
int CubicSDR::OnExit() {
|
||||
shuttingDown.store(true);
|
||||
|
||||
#if USE_HAMLIB
|
||||
if (rigIsActive()) {
|
||||
std::cout << "Terminating Rig thread.." << std::endl << std::flush;
|
||||
@ -1029,6 +1032,11 @@ bool CubicSDR::getSoloMode() {
|
||||
return soloMode.load();
|
||||
}
|
||||
|
||||
bool CubicSDR::isShuttingDown()
|
||||
{
|
||||
return shuttingDown.load();
|
||||
}
|
||||
|
||||
int CubicSDR::FilterEvent(wxEvent& event) {
|
||||
if (!appframe) {
|
||||
return -1;
|
||||
|
@ -170,6 +170,8 @@ public:
|
||||
|
||||
void setSoloMode(bool solo);
|
||||
bool getSoloMode();
|
||||
|
||||
bool isShuttingDown();
|
||||
|
||||
#ifdef USE_HAMLIB
|
||||
RigThread *getRigThread();
|
||||
@ -195,6 +197,7 @@ private:
|
||||
std::atomic_llong sampleRate;
|
||||
std::string antennaName;
|
||||
std::atomic_bool agcMode;
|
||||
std::atomic_bool shuttingDown;
|
||||
|
||||
SDRThread *sdrThread = nullptr;
|
||||
SDREnumerator *sdrEnum = nullptr;
|
||||
|
50
src/audio/AudioFile.cpp
Normal file
50
src/audio/AudioFile.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "AudioFile.h"
|
||||
#include "CubicSDR.h"
|
||||
#include <sstream>
|
||||
|
||||
AudioFile::AudioFile() {
|
||||
|
||||
}
|
||||
|
||||
AudioFile::~AudioFile() {
|
||||
|
||||
}
|
||||
|
||||
void AudioFile::setOutputFileName(std::string filename) {
|
||||
filenameBase = filename;
|
||||
}
|
||||
|
||||
std::string AudioFile::getOutputFileName() {
|
||||
|
||||
std::string recPath = wxGetApp().getConfig()->getRecordingPath();
|
||||
|
||||
// Strip any invalid characters from the name
|
||||
std::string stripChars("<>:\"/\\|?*");
|
||||
std::string filenameBaseSafe = filenameBase;
|
||||
|
||||
for (size_t i = 0, iMax = filenameBaseSafe.length(); i < iMax; i++) {
|
||||
if (stripChars.find(filenameBaseSafe[i]) != std::string::npos) {
|
||||
filenameBaseSafe.replace(i,1,"_");
|
||||
}
|
||||
}
|
||||
|
||||
// Create output file name
|
||||
std::stringstream outputFileName;
|
||||
outputFileName << recPath << filePathSeparator << filenameBaseSafe;
|
||||
|
||||
int idx = 0;
|
||||
|
||||
// If the file exists; then find the next non-existing file in sequence.
|
||||
std::string fileNameCandidate = outputFileName.str();
|
||||
|
||||
while (FILE *file = fopen((fileNameCandidate + "." + getExtension()).c_str(), "r")) {
|
||||
fclose(file);
|
||||
fileNameCandidate = outputFileName.str() + "-" + std::to_string(++idx);
|
||||
}
|
||||
|
||||
return fileNameCandidate + "." + getExtension();
|
||||
}
|
||||
|
25
src/audio/AudioFile.h
Normal file
25
src/audio/AudioFile.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AudioThread.h"
|
||||
|
||||
class AudioFile
|
||||
{
|
||||
|
||||
public:
|
||||
AudioFile();
|
||||
virtual ~AudioFile();
|
||||
|
||||
virtual void setOutputFileName(std::string filename);
|
||||
virtual std::string getExtension() = 0;
|
||||
virtual std::string getOutputFileName();
|
||||
|
||||
virtual bool writeToFile(AudioThreadInputPtr input) = 0;
|
||||
virtual bool closeFile() = 0;
|
||||
|
||||
protected:
|
||||
std::string filenameBase;
|
||||
|
||||
};
|
219
src/audio/AudioFileWAV.cpp
Normal file
219
src/audio/AudioFileWAV.cpp
Normal file
@ -0,0 +1,219 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "AudioFileWAV.h"
|
||||
#include "CubicSDR.h"
|
||||
#include <iomanip>
|
||||
|
||||
//limit file size to 2GB (- margin) for maximum compatibility.
|
||||
#define MAX_WAV_FILE_SIZE (0x7FFFFFFF - 1024)
|
||||
|
||||
// Simple endian io read/write handling from
|
||||
// http://www.cplusplus.com/forum/beginner/31584/#msg171056
|
||||
namespace little_endian_io
|
||||
{
|
||||
template <typename Word>
|
||||
std::ostream& write_word(std::ostream& outs, Word value, unsigned size = sizeof(Word)) {
|
||||
for (; size; --size, value >>= 8) {
|
||||
outs.put(static_cast <char> (value & 0xFF));
|
||||
}
|
||||
return outs;
|
||||
}
|
||||
|
||||
template <typename Word>
|
||||
std::istream& read_word(std::istream& ins, Word& value, unsigned size = sizeof(Word)) {
|
||||
for (unsigned n = 0, value = 0; n < size; ++n) {
|
||||
value |= ins.get() << (8 * n);
|
||||
}
|
||||
return ins;
|
||||
}
|
||||
}
|
||||
|
||||
namespace big_endian_io
|
||||
{
|
||||
template <typename Word>
|
||||
std::ostream& write_word(std::ostream& outs, Word value, unsigned size = sizeof(Word)) {
|
||||
while (size) {
|
||||
outs.put(static_cast <char> ((value >> (8 * --size)) & 0xFF));
|
||||
}
|
||||
return outs;
|
||||
}
|
||||
|
||||
template <typename Word>
|
||||
std::istream& read_word(std::istream& ins, Word& value, unsigned size = sizeof(Word)) {
|
||||
for (value = 0; size; --size) {
|
||||
value = (value << 8) | ins.get();
|
||||
}
|
||||
return ins;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace little_endian_io;
|
||||
|
||||
AudioFileWAV::AudioFileWAV() : AudioFile() {
|
||||
}
|
||||
|
||||
AudioFileWAV::~AudioFileWAV() {
|
||||
}
|
||||
|
||||
|
||||
std::string AudioFileWAV::getExtension()
|
||||
{
|
||||
return "wav";
|
||||
}
|
||||
|
||||
bool AudioFileWAV::writeToFile(AudioThreadInputPtr input)
|
||||
{
|
||||
if (!outputFileStream.is_open()) {
|
||||
|
||||
std::string ofName = getOutputFileName();
|
||||
|
||||
outputFileStream.open(ofName.c_str(), std::ios::binary);
|
||||
currentFileSize = 0;
|
||||
|
||||
writeHeaderToFileStream(input);
|
||||
}
|
||||
|
||||
size_t maxRoomInCurrentFileInSamples = getMaxWritableNumberOfSamples(input);
|
||||
|
||||
if (maxRoomInCurrentFileInSamples >= input->data.size()) {
|
||||
writePayloadToFileStream(input, 0, input->data.size());
|
||||
}
|
||||
else {
|
||||
//we complete the current file and open another:
|
||||
writePayloadToFileStream(input, 0, maxRoomInCurrentFileInSamples);
|
||||
|
||||
closeFile();
|
||||
|
||||
// Open a new file with the next sequence number, and dump the rest of samples in it.
|
||||
currentSequenceNumber++;
|
||||
currentFileSize = 0;
|
||||
|
||||
std::string ofName = getOutputFileName();
|
||||
outputFileStream.open(ofName.c_str(), std::ios::binary);
|
||||
|
||||
writeHeaderToFileStream(input);
|
||||
writePayloadToFileStream(input, maxRoomInCurrentFileInSamples, input->data.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioFileWAV::closeFile()
|
||||
{
|
||||
if (outputFileStream.is_open()) {
|
||||
size_t file_length = outputFileStream.tellp();
|
||||
|
||||
// Fix the data chunk header to contain the data size
|
||||
outputFileStream.seekp(dataChunkPos + 4);
|
||||
write_word(outputFileStream, file_length - dataChunkPos + 8);
|
||||
|
||||
// Fix the file header to contain the proper RIFF chunk size, which is (file size - 8) bytes
|
||||
outputFileStream.seekp(0 + 4);
|
||||
write_word(outputFileStream, file_length - 8, 4);
|
||||
|
||||
outputFileStream.close();
|
||||
currentFileSize = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioFileWAV::writeHeaderToFileStream(AudioThreadInputPtr input) {
|
||||
|
||||
// Based on simple wav file output code from
|
||||
// http://www.cplusplus.com/forum/beginner/166954/
|
||||
|
||||
// Write the wav file headers
|
||||
outputFileStream << "RIFF----WAVEfmt "; // (chunk size to be filled in later)
|
||||
write_word(outputFileStream, 16, 4); // no extension data
|
||||
write_word(outputFileStream, 1, 2); // PCM - integer samples
|
||||
write_word(outputFileStream, input->channels, 2); // channels
|
||||
write_word(outputFileStream, input->sampleRate, 4); // samples per second (Hz)
|
||||
write_word(outputFileStream, (input->sampleRate * 16 * input->channels) / 8, 4); // (Sample Rate * BitsPerSample * Channels) / 8
|
||||
write_word(outputFileStream, input->channels * 2, 2); // data block size (size of integer samples, one for each channel, in bytes)
|
||||
write_word(outputFileStream, 16, 2); // number of bits per sample (use a multiple of 8)
|
||||
|
||||
// Write the data chunk header
|
||||
dataChunkPos = outputFileStream.tellp();
|
||||
currentFileSize = dataChunkPos;
|
||||
outputFileStream << "data----"; // (chunk size to be filled in later)
|
||||
}
|
||||
|
||||
void AudioFileWAV::writePayloadToFileStream(AudioThreadInputPtr input, size_t startInputPosition, size_t endInputPosition) {
|
||||
|
||||
// Prevent clipping
|
||||
float intScale = (input->peak < 1.0) ? 32767.0f : (32767.0f / input->peak);
|
||||
|
||||
if (input->channels == 1) {
|
||||
for (size_t i = startInputPosition, iMax = endInputPosition; i < iMax; i++) {
|
||||
|
||||
write_word(outputFileStream, int(input->data[i] * intScale), 2);
|
||||
|
||||
currentFileSize += 2;
|
||||
}
|
||||
}
|
||||
else if (input->channels == 2) {
|
||||
for (size_t i = startInputPosition, iMax = endInputPosition / 2; i < iMax; i++) {
|
||||
|
||||
write_word(outputFileStream, int(input->data[i * 2] * intScale), 2);
|
||||
write_word(outputFileStream, int(input->data[i * 2 + 1] * intScale), 2);
|
||||
|
||||
currentFileSize += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioFileWAV::getMaxWritableNumberOfSamples(AudioThreadInputPtr input) {
|
||||
|
||||
long long remainingBytesInFile = (long long)(MAX_WAV_FILE_SIZE) - currentFileSize;
|
||||
|
||||
return (size_t)(remainingBytesInFile / (input->channels * 2));
|
||||
|
||||
}
|
||||
|
||||
void AudioFileWAV::setOutputFileName(std::string filename) {
|
||||
|
||||
if (filename != filenameBase) {
|
||||
|
||||
currentSequenceNumber = 0;
|
||||
}
|
||||
|
||||
AudioFile::setOutputFileName(filename);
|
||||
}
|
||||
|
||||
std::string AudioFileWAV::getOutputFileName() {
|
||||
|
||||
std::string recPath = wxGetApp().getConfig()->getRecordingPath();
|
||||
|
||||
// Strip any invalid characters from the name
|
||||
std::string stripChars("<>:\"/\\|?*");
|
||||
std::string filenameBaseSafe = filenameBase;
|
||||
|
||||
for (size_t i = 0, iMax = filenameBaseSafe.length(); i < iMax; i++) {
|
||||
if (stripChars.find(filenameBaseSafe[i]) != std::string::npos) {
|
||||
filenameBaseSafe.replace(i, 1, "_");
|
||||
}
|
||||
}
|
||||
|
||||
// Create output file name
|
||||
std::stringstream outputFileName;
|
||||
outputFileName << recPath << filePathSeparator << filenameBaseSafe;
|
||||
|
||||
//customized part: append a sequence number.
|
||||
if (currentSequenceNumber > 0) {
|
||||
outputFileName << "_" << std::setfill('0') << std::setw(3) << currentSequenceNumber;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
|
||||
// If the file exists; then find the next non-existing file in sequence.
|
||||
std::string fileNameCandidate = outputFileName.str();
|
||||
|
||||
while (FILE *file = fopen((fileNameCandidate + "." + getExtension()).c_str(), "r")) {
|
||||
fclose(file);
|
||||
fileNameCandidate = outputFileName.str() + "-" + std::to_string(++idx);
|
||||
}
|
||||
|
||||
return fileNameCandidate + "." + getExtension();
|
||||
}
|
42
src/audio/AudioFileWAV.h
Normal file
42
src/audio/AudioFileWAV.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AudioFile.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
class AudioFileWAV : public AudioFile {
|
||||
|
||||
public:
|
||||
AudioFileWAV();
|
||||
~AudioFileWAV();
|
||||
|
||||
//override to manage name change with multi-part WAV.
|
||||
virtual void setOutputFileName(std::string filename);
|
||||
|
||||
//override of the base method to generate multi-part
|
||||
//WAV to overcome the WAV format size limit.
|
||||
virtual std::string getOutputFileName();
|
||||
|
||||
virtual std::string getExtension();
|
||||
|
||||
virtual bool writeToFile(AudioThreadInputPtr input);
|
||||
virtual bool closeFile();
|
||||
|
||||
protected:
|
||||
std::ofstream outputFileStream;
|
||||
size_t dataChunkPos;
|
||||
long long currentFileSize = 0;
|
||||
int currentSequenceNumber = 0;
|
||||
|
||||
private:
|
||||
|
||||
size_t getMaxWritableNumberOfSamples(AudioThreadInputPtr input);
|
||||
|
||||
void writeHeaderToFileStream(AudioThreadInputPtr input);
|
||||
|
||||
//write [startInputPosition; endInputPosition[ samples from input into the file.
|
||||
void writePayloadToFileStream(AudioThreadInputPtr input, size_t startInputPosition, size_t endInputPosition);
|
||||
};
|
140
src/audio/AudioSinkFileThread.cpp
Normal file
140
src/audio/AudioSinkFileThread.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "AudioSinkFileThread.h"
|
||||
#include <ctime>
|
||||
|
||||
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
|
||||
|
||||
AudioSinkFileThread::AudioSinkFileThread() : AudioSinkThread() {
|
||||
|
||||
}
|
||||
|
||||
AudioSinkFileThread::~AudioSinkFileThread() {
|
||||
if (audioFileHandler != nullptr) {
|
||||
audioFileHandler->closeFile();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSinkFileThread::sink(AudioThreadInputPtr input) {
|
||||
if (!audioFileHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
//by default, always write something
|
||||
bool isSomethingToWrite = true;
|
||||
|
||||
if (input->is_squelch_active) {
|
||||
|
||||
if (squelchOption == SQUELCH_RECORD_SILENCE) {
|
||||
|
||||
//patch with "silence"
|
||||
input->data.assign(input->data.size(), 0.0f);
|
||||
input->peak = 0.0f;
|
||||
}
|
||||
else if (squelchOption == SQUELCH_SKIP_SILENCE) {
|
||||
isSomethingToWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
//else, nothing to do record as if squelch was not enabled.
|
||||
|
||||
if (!isSomethingToWrite) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileTimeLimit > 0) {
|
||||
durationMeasurement.update();
|
||||
|
||||
//duration exeeded, close this file and create another
|
||||
//with "now" as timestamp.
|
||||
if (durationMeasurement.getSeconds() > fileTimeLimit) {
|
||||
|
||||
audioFileHandler->closeFile();
|
||||
|
||||
//initialize the filename of the AudioFile with the current time
|
||||
time_t t = std::time(nullptr);
|
||||
tm ltm = *std::localtime(&t);
|
||||
|
||||
// GCC 5+
|
||||
// fileName << "_" << std::put_time(<m, "%d-%m-%Y_%H-%M-%S");
|
||||
|
||||
char timeStr[512];
|
||||
//International format: Year.Month.Day, also lexicographically sortable
|
||||
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d_%H-%M-%S", <m);
|
||||
|
||||
audioFileHandler->setOutputFileName(fileNameBase + std::string("_") + timeStr);
|
||||
|
||||
//reset duration counter
|
||||
durationMeasurement.start();
|
||||
//the following writeToFile will take care of creating another file.
|
||||
}
|
||||
}
|
||||
|
||||
// forward to output file handler
|
||||
audioFileHandler->writeToFile(input);
|
||||
}
|
||||
|
||||
void AudioSinkFileThread::inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps) {
|
||||
// close, set new parameters, adjust file name sequence and re-open?
|
||||
if (!audioFileHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
audioFileHandler->closeFile();
|
||||
|
||||
//reset duration counter
|
||||
durationMeasurement.start();
|
||||
}
|
||||
|
||||
void AudioSinkFileThread::setAudioFileNameBase(const std::string& baseName) {
|
||||
|
||||
fileNameBase = baseName;
|
||||
}
|
||||
|
||||
void AudioSinkFileThread::setAudioFileHandler(AudioFile * output) {
|
||||
audioFileHandler = output;
|
||||
|
||||
//initialize the filename of the AudioFile with the current time
|
||||
time_t t = std::time(nullptr);
|
||||
tm ltm = *std::localtime(&t);
|
||||
|
||||
// GCC 5+
|
||||
// fileName << "_" << std::put_time(<m, "%d-%m-%Y_%H-%M-%S");
|
||||
|
||||
char timeStr[512];
|
||||
//International format: Year.Month.Day, also lexicographically sortable
|
||||
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d_%H-%M-%S", <m);
|
||||
|
||||
audioFileHandler->setOutputFileName(fileNameBase + std::string("_") + timeStr);
|
||||
|
||||
// reset Timer
|
||||
durationMeasurement.start();
|
||||
}
|
||||
|
||||
void AudioSinkFileThread::setSquelchOption(int squelchOptEnumValue) {
|
||||
|
||||
if (squelchOptEnumValue == AudioSinkFileThread::SQUELCH_RECORD_SILENCE) {
|
||||
squelchOption = AudioSinkFileThread::SQUELCH_RECORD_SILENCE;
|
||||
}
|
||||
else if (squelchOptEnumValue == AudioSinkFileThread::SQUELCH_SKIP_SILENCE) {
|
||||
squelchOption = AudioSinkFileThread::SQUELCH_SKIP_SILENCE;
|
||||
}
|
||||
else if (squelchOptEnumValue == AudioSinkFileThread::SQUELCH_RECORD_ALWAYS) {
|
||||
squelchOption = AudioSinkFileThread::SQUELCH_RECORD_ALWAYS;
|
||||
}
|
||||
else {
|
||||
squelchOption = AudioSinkFileThread::SQUELCH_RECORD_SILENCE;
|
||||
}
|
||||
}
|
||||
|
||||
// Time limit
|
||||
void AudioSinkFileThread::setFileTimeLimit(int nbSeconds) {
|
||||
|
||||
if (nbSeconds > 0) {
|
||||
fileTimeLimit = nbSeconds;
|
||||
}
|
||||
else {
|
||||
fileTimeLimit = 0;
|
||||
}
|
||||
}
|
50
src/audio/AudioSinkFileThread.h
Normal file
50
src/audio/AudioSinkFileThread.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AudioSinkThread.h"
|
||||
#include "AudioFile.h"
|
||||
#include "Timer.h"
|
||||
|
||||
class AudioSinkFileThread : public AudioSinkThread {
|
||||
|
||||
public:
|
||||
AudioSinkFileThread();
|
||||
~AudioSinkFileThread();
|
||||
|
||||
enum SquelchOption {
|
||||
SQUELCH_RECORD_SILENCE = 0, // default value, record as a user would hear it.
|
||||
SQUELCH_SKIP_SILENCE = 1, // skip below-squelch level.
|
||||
SQUELCH_RECORD_ALWAYS = 2, // record irrespective of the squelch level.
|
||||
SQUELCH_RECORD_MAX
|
||||
};
|
||||
|
||||
virtual void sink(AudioThreadInputPtr input);
|
||||
virtual void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps);
|
||||
|
||||
void setAudioFileHandler(AudioFile *output);
|
||||
|
||||
void setAudioFileNameBase(const std::string& baseName);
|
||||
|
||||
//Squelch
|
||||
void setSquelchOption(int squelchOptEnumValue);
|
||||
|
||||
// Time limit
|
||||
void setFileTimeLimit(int nbSeconds);
|
||||
|
||||
protected:
|
||||
|
||||
std::string fileNameBase;
|
||||
|
||||
AudioFile *audioFileHandler = nullptr;
|
||||
|
||||
SquelchOption squelchOption = SQUELCH_RECORD_SILENCE;
|
||||
int fileTimeLimit = 0;
|
||||
|
||||
int fileTimeDurationSeconds = -1;
|
||||
|
||||
Timer durationMeasurement;
|
||||
|
||||
};
|
||||
|
54
src/audio/AudioSinkThread.cpp
Normal file
54
src/audio/AudioSinkThread.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "AudioSinkThread.h"
|
||||
|
||||
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
|
||||
|
||||
AudioSinkThread::AudioSinkThread() {
|
||||
inputQueuePtr = std::make_shared<AudioThreadInputQueue>();
|
||||
inputQueuePtr->set_max_num_items(1000);
|
||||
setInputQueue("input", inputQueuePtr);
|
||||
}
|
||||
|
||||
AudioSinkThread::~AudioSinkThread() {
|
||||
|
||||
}
|
||||
|
||||
void AudioSinkThread::run() {
|
||||
#ifdef __APPLE__
|
||||
pthread_t tID = pthread_self(); // ID of this thread
|
||||
int priority = sched_get_priority_max(SCHED_RR) - 1;
|
||||
sched_param prio = { priority }; // scheduling priority of thread
|
||||
pthread_setschedparam(tID, SCHED_RR, &prio);
|
||||
#endif
|
||||
|
||||
AudioThreadInputPtr inp;
|
||||
AudioThreadInput inputRef;
|
||||
|
||||
while (!stopping) {
|
||||
if (!inputQueuePtr->pop(inp, HEARTBEAT_CHECK_PERIOD_MICROS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inputRef.channels != inp->channels ||
|
||||
inputRef.frequency != inp->frequency ||
|
||||
inputRef.inputRate != inp->inputRate ||
|
||||
inputRef.sampleRate != inp->sampleRate) {
|
||||
|
||||
inputChanged(inputRef, inp);
|
||||
|
||||
inputRef.channels = inp->channels;
|
||||
inputRef.frequency = inp->frequency;
|
||||
inputRef.inputRate = inp->inputRate;
|
||||
inputRef.sampleRate = inp->sampleRate;
|
||||
}
|
||||
|
||||
sink(inp);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSinkThread::terminate() {
|
||||
IOThread::terminate();
|
||||
inputQueuePtr->flush();
|
||||
}
|
25
src/audio/AudioSinkThread.h
Normal file
25
src/audio/AudioSinkThread.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) Charles J. Cliffe
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AudioThread.h"
|
||||
|
||||
class AudioSinkThread : public IOThread {
|
||||
|
||||
public:
|
||||
|
||||
AudioSinkThread();
|
||||
virtual ~AudioSinkThread();
|
||||
|
||||
virtual void run();
|
||||
virtual void terminate();
|
||||
|
||||
virtual void sink(AudioThreadInputPtr input) = 0;
|
||||
virtual void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps) = 0;
|
||||
|
||||
protected:
|
||||
std::recursive_mutex m_mutex;
|
||||
AudioThreadInputQueuePtr inputQueuePtr;
|
||||
|
||||
};
|
@ -21,13 +21,32 @@ public:
|
||||
int channels;
|
||||
float peak;
|
||||
int type;
|
||||
bool is_squelch_active;
|
||||
|
||||
std::vector<float> data;
|
||||
|
||||
AudioThreadInput() :
|
||||
frequency(0), sampleRate(0), channels(0), peak(0) {
|
||||
frequency(0), inputRate(0), sampleRate(0), channels(0), peak(0), type(0), is_squelch_active(false) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
AudioThreadInput(AudioThreadInput *copyFrom) {
|
||||
copy(copyFrom);
|
||||
}
|
||||
|
||||
void copy(AudioThreadInput *copyFrom) {
|
||||
frequency = copyFrom->frequency;
|
||||
inputRate = copyFrom->inputRate;
|
||||
sampleRate = copyFrom->sampleRate;
|
||||
channels = copyFrom->channels;
|
||||
peak = copyFrom->peak;
|
||||
type = copyFrom->type;
|
||||
is_squelch_active = copyFrom->is_squelch_active;
|
||||
data.assign(copyFrom->data.begin(), copyFrom->data.end());
|
||||
}
|
||||
|
||||
|
||||
virtual ~AudioThreadInput() {
|
||||
|
||||
}
|
||||
|
@ -2,12 +2,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <memory>
|
||||
#include <iomanip>
|
||||
|
||||
#include "DemodulatorInstance.h"
|
||||
#include "CubicSDR.h"
|
||||
|
||||
#include "DemodulatorThread.h"
|
||||
#include "DemodulatorPreThread.h"
|
||||
|
||||
#include "AudioSinkFileThread.h"
|
||||
#include "AudioFileWAV.h"
|
||||
|
||||
#if USE_HAMLIB
|
||||
#include "RigThread.h"
|
||||
@ -47,6 +50,7 @@ DemodulatorInstance::DemodulatorInstance() {
|
||||
active.store(false);
|
||||
squelch.store(false);
|
||||
muted.store(false);
|
||||
recording.store(false);
|
||||
deltaLock.store(false);
|
||||
deltaLockOfs.store(0);
|
||||
currentOutputDevice.store(-1);
|
||||
@ -106,6 +110,7 @@ DemodulatorInstance::~DemodulatorInstance() {
|
||||
delete demodulatorPreThread;
|
||||
delete demodulatorThread;
|
||||
delete audioThread;
|
||||
delete audioSinkThread;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -181,6 +186,10 @@ void DemodulatorInstance::terminate() {
|
||||
// std::cout << "Terminating demodulator preprocessor thread.." << std::endl;
|
||||
demodulatorPreThread->terminate();
|
||||
|
||||
if (audioSinkThread != nullptr) {
|
||||
stopRecording();
|
||||
}
|
||||
|
||||
//that will actually unblock the currently blocked push().
|
||||
pipeIQInputData->flush();
|
||||
pipeAudioData->flush();
|
||||
@ -204,6 +213,7 @@ bool DemodulatorInstance::isTerminated() {
|
||||
bool audioTerminated = audioThread->isTerminated();
|
||||
bool demodTerminated = demodulatorThread->isTerminated();
|
||||
bool preDemodTerminated = demodulatorPreThread->isTerminated();
|
||||
bool audioSinkTerminated = (audioSinkThread == nullptr) || audioSinkThread->isTerminated();
|
||||
|
||||
//Cleanup the worker threads, if the threads are indeed terminated.
|
||||
// threads are linked as t_PreDemod ==> t_Demod ==> t_Audio
|
||||
@ -240,14 +250,27 @@ bool DemodulatorInstance::isTerminated() {
|
||||
if (audioTerminated) {
|
||||
|
||||
if (t_Audio) {
|
||||
#ifdef __APPLE__
|
||||
pthread_join(t_PreDemod, NULL);
|
||||
#else
|
||||
t_Audio->join();
|
||||
|
||||
delete t_Audio;
|
||||
#endif
|
||||
t_Audio = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool terminated = audioTerminated && demodTerminated && preDemodTerminated;
|
||||
if (audioSinkTerminated) {
|
||||
|
||||
if (t_AudioSink != nullptr) {
|
||||
t_AudioSink->join();
|
||||
|
||||
delete t_AudioSink;
|
||||
t_AudioSink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool terminated = audioTerminated && demodTerminated && preDemodTerminated && audioSinkTerminated;
|
||||
|
||||
return terminated;
|
||||
}
|
||||
@ -523,6 +546,21 @@ void DemodulatorInstance::setMuted(bool muted) {
|
||||
wxGetApp().getDemodMgr().setLastMuted(muted);
|
||||
}
|
||||
|
||||
bool DemodulatorInstance::isRecording()
|
||||
{
|
||||
return recording.load();
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setRecording(bool recording_in)
|
||||
{
|
||||
if (!recording.load() && recording_in) {
|
||||
startRecording();
|
||||
}
|
||||
else if (recording.load() && !recording_in) {
|
||||
stopRecording();
|
||||
}
|
||||
}
|
||||
|
||||
DemodVisualCue *DemodulatorInstance::getVisualCue() {
|
||||
return &visualCue;
|
||||
}
|
||||
@ -580,6 +618,65 @@ ModemSettings DemodulatorInstance::getLastModemSettings(std::string demodType) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DemodulatorInstance::startRecording() {
|
||||
if (recording.load()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AudioSinkFileThread *newSinkThread = new AudioSinkFileThread();
|
||||
AudioFileWAV *afHandler = new AudioFileWAV();
|
||||
|
||||
std::stringstream fileName;
|
||||
|
||||
std::wstring userLabel = getDemodulatorUserLabel();
|
||||
|
||||
wxString userLabelForFileName(userLabel);
|
||||
std::string userLabelStr = userLabelForFileName.ToStdString();
|
||||
|
||||
if (!userLabelStr.empty()) {
|
||||
fileName << userLabelStr;
|
||||
} else {
|
||||
fileName << getLabel();
|
||||
}
|
||||
|
||||
newSinkThread->setAudioFileNameBase(fileName.str());
|
||||
|
||||
//attach options:
|
||||
newSinkThread->setSquelchOption(wxGetApp().getConfig()->getRecordingSquelchOption());
|
||||
newSinkThread->setFileTimeLimit(wxGetApp().getConfig()->getRecordingFileTimeLimit());
|
||||
|
||||
newSinkThread->setAudioFileHandler(afHandler);
|
||||
|
||||
audioSinkThread = newSinkThread;
|
||||
t_AudioSink = new std::thread(&AudioSinkThread::threadMain, audioSinkThread);
|
||||
|
||||
demodulatorThread->setOutputQueue("AudioSink", audioSinkThread->getInputQueue("input"));
|
||||
|
||||
recording.store(true);
|
||||
}
|
||||
|
||||
|
||||
void DemodulatorInstance::stopRecording() {
|
||||
if (!recording.load()) {
|
||||
return;
|
||||
}
|
||||
|
||||
demodulatorThread->setOutputQueue("AudioSink", nullptr);
|
||||
audioSinkThread->terminate();
|
||||
|
||||
t_AudioSink->join();
|
||||
|
||||
delete t_AudioSink;
|
||||
delete audioSinkThread;
|
||||
|
||||
t_AudioSink = nullptr;
|
||||
audioSinkThread = nullptr;
|
||||
|
||||
recording.store(false);
|
||||
}
|
||||
|
||||
|
||||
#if ENABLE_DIGITAL_LAB
|
||||
ModemDigitalOutput *DemodulatorInstance::getOutput() {
|
||||
if (activeOutput == nullptr) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "ModemDigital.h"
|
||||
#include "ModemAnalog.h"
|
||||
#include "AudioThread.h"
|
||||
#include "AudioSinkThread.h"
|
||||
|
||||
#if ENABLE_DIGITAL_LAB
|
||||
#include "DigitalConsole.h"
|
||||
@ -110,6 +111,9 @@ public:
|
||||
bool isMuted();
|
||||
void setMuted(bool muted);
|
||||
|
||||
bool isRecording();
|
||||
void setRecording(bool recording);
|
||||
|
||||
DemodVisualCue *getVisualCue();
|
||||
|
||||
DemodulatorThreadInputQueuePtr getIQInputDataPipe();
|
||||
@ -131,6 +135,10 @@ public:
|
||||
void closeOutput();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void startRecording();
|
||||
void stopRecording();
|
||||
|
||||
private:
|
||||
DemodulatorThreadInputQueuePtr pipeIQInputData;
|
||||
DemodulatorThreadPostInputQueuePtr pipeIQDemodData;
|
||||
@ -139,6 +147,10 @@ private:
|
||||
DemodulatorThread *demodulatorThread;
|
||||
DemodulatorThreadControlCommandQueuePtr threadQueueControl;
|
||||
|
||||
AudioSinkThread *audioSinkThread = nullptr;
|
||||
std::thread *t_AudioSink = nullptr;
|
||||
AudioThreadInputQueuePtr audioSinkInputQueue;
|
||||
|
||||
//protects child thread creation and termination
|
||||
std::recursive_mutex m_thread_control_mutex;
|
||||
|
||||
@ -150,6 +162,8 @@ private:
|
||||
std::atomic_bool squelch;
|
||||
std::atomic_bool muted;
|
||||
std::atomic_bool deltaLock;
|
||||
std::atomic_bool recording;
|
||||
|
||||
std::atomic_int deltaLockOfs;
|
||||
|
||||
std::atomic_int currentOutputDevice;
|
||||
|
@ -58,7 +58,6 @@ void DemodulatorMgr::terminateAll() {
|
||||
|
||||
DemodulatorInstancePtr d = demods.back();
|
||||
demods.pop_back();
|
||||
wxGetApp().removeDemodulator(d);
|
||||
deleteThread(d);
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,12 @@ void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBasePtr thread
|
||||
|
||||
audioVisOutputQueue = std::static_pointer_cast<DemodulatorThreadOutputQueue>(threadQueue);
|
||||
}
|
||||
|
||||
if (name == "AudioSink") {
|
||||
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
|
||||
|
||||
audioSinkOutputQueue = std::static_pointer_cast<AudioThreadInputQueue>(threadQueue);
|
||||
}
|
||||
}
|
||||
|
||||
double DemodulatorThread::abMagnitude(float inphase, float quadrature) {
|
||||
@ -195,7 +201,7 @@ void DemodulatorThread::run() {
|
||||
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05 * sampleTime * 30.0;
|
||||
}
|
||||
|
||||
bool squelched = (muted.load() || (squelchEnabled && (signalLevel < squelchLevel)));
|
||||
bool squelched = squelchEnabled && (signalLevel < squelchLevel);
|
||||
|
||||
if (squelchEnabled) {
|
||||
if (!squelched && !squelchBreak) {
|
||||
@ -218,20 +224,25 @@ void DemodulatorThread::run() {
|
||||
squelchBreak = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (audioOutputQueue != nullptr && ati && ati->data.size() && !squelched) {
|
||||
std::vector<float>::iterator data_i;
|
||||
ati->peak = 0;
|
||||
for (auto data_i : ati->data) {
|
||||
float p = fabs(data_i);
|
||||
if (p > ati->peak) {
|
||||
ati->peak = p;
|
||||
}
|
||||
}
|
||||
} else if (ati) {
|
||||
ati = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//compute audio peak:
|
||||
if (audioOutputQueue != nullptr && ati) {
|
||||
|
||||
ati->peak = 0;
|
||||
|
||||
for (auto data_i : ati->data) {
|
||||
float p = fabs(data_i);
|
||||
if (p > ati->peak) {
|
||||
ati->peak = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//attach squelch flag to samples, to be used by audio sink.
|
||||
if (ati) {
|
||||
ati->is_squelch_active = squelched;
|
||||
}
|
||||
|
||||
//At that point, capture the current state of audioVisOutputQueue in a local
|
||||
//variable, and works with it with now on until the next while-turn.
|
||||
DemodulatorThreadOutputQueuePtr localAudioVisOutputQueue = nullptr;
|
||||
@ -240,7 +251,7 @@ void DemodulatorThread::run() {
|
||||
localAudioVisOutputQueue = audioVisOutputQueue;
|
||||
}
|
||||
|
||||
if ((ati || modemDigital) && localAudioVisOutputQueue != nullptr && localAudioVisOutputQueue->empty()) {
|
||||
if (!squelched && (ati || modemDigital) && localAudioVisOutputQueue != nullptr && localAudioVisOutputQueue->empty()) {
|
||||
|
||||
AudioThreadInputPtr ati_vis = std::make_shared<AudioThreadInput>();
|
||||
|
||||
@ -310,7 +321,7 @@ void DemodulatorThread::run() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ati != nullptr) {
|
||||
if (!squelched && ati != nullptr) {
|
||||
if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator().get()))) {
|
||||
//non-blocking push needed for audio out
|
||||
if (!audioOutputQueue->try_push(ati)) {
|
||||
@ -321,6 +332,23 @@ void DemodulatorThread::run() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Capture audioSinkOutputQueue state in a local variable
|
||||
DemodulatorThreadOutputQueuePtr localAudioSinkOutputQueue = nullptr;
|
||||
{
|
||||
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
|
||||
localAudioSinkOutputQueue = audioSinkOutputQueue;
|
||||
}
|
||||
|
||||
//Push to audio sink, if any:
|
||||
if (ati && localAudioSinkOutputQueue != nullptr) {
|
||||
|
||||
if (!localAudioSinkOutputQueue->try_push(ati)) {
|
||||
std::cout << "DemodulatorThread::run() cannot push ati into audioSinkOutputQueue, is full !" << std::endl;
|
||||
std::this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
DemodulatorThreadControlCommand command;
|
||||
|
||||
//empty command queue, execute commands
|
||||
@ -398,4 +426,4 @@ void DemodulatorThread::releaseSquelchLock(DemodulatorInstance* inst) {
|
||||
if (inst == nullptr || squelchLock == inst) {
|
||||
squelchLock = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +67,8 @@ protected:
|
||||
DemodulatorThreadOutputQueuePtr audioVisOutputQueue;
|
||||
DemodulatorThreadControlCommandQueuePtr threadQueueControl;
|
||||
|
||||
DemodulatorThreadOutputQueuePtr audioSinkOutputQueue = nullptr;
|
||||
|
||||
//protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
|
||||
std::mutex m_mutexAudioVisOutputQueue;
|
||||
};
|
||||
|
@ -821,8 +821,16 @@ void BookmarkView::activeSelection(DemodulatorInstancePtr dsel) {
|
||||
clearButtons();
|
||||
|
||||
addBookmarkChoice(m_buttonPanel);
|
||||
addButton(m_buttonPanel, "Remove Active", wxCommandEventHandler( BookmarkView::onRemoveActive ));
|
||||
|
||||
if (dsel->isActive() && !(dsel->isRecording())) {
|
||||
addButton(m_buttonPanel, "Start Recording", wxCommandEventHandler( BookmarkView::onStartRecording ));
|
||||
} else {
|
||||
addButton(m_buttonPanel, "Stop Recording", wxCommandEventHandler( BookmarkView::onStopRecording ));
|
||||
}
|
||||
|
||||
addButton(m_buttonPanel, "Remove Active", wxCommandEventHandler( BookmarkView::onRemoveActive ));
|
||||
|
||||
|
||||
showProps();
|
||||
showButtons();
|
||||
refreshLayout();
|
||||
@ -1158,6 +1166,30 @@ void BookmarkView::onRemoveActive( wxCommandEvent& /* event */ ) {
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkView::onStartRecording( wxCommandEvent& /* event */ ) {
|
||||
TreeViewItem *curSel = itemToTVI(m_treeView->GetSelection());
|
||||
|
||||
if (curSel && curSel->type == TreeViewItem::TREEVIEW_ITEM_TYPE_ACTIVE) {
|
||||
if (!curSel->demod->isRecording() && wxGetApp().getConfig()->verifyRecordingPath()) {
|
||||
curSel->demod->setRecording(true);
|
||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BookmarkView::onStopRecording( wxCommandEvent& /* event */ ) {
|
||||
TreeViewItem *curSel = itemToTVI(m_treeView->GetSelection());
|
||||
|
||||
if (curSel && curSel->type == TreeViewItem::TREEVIEW_ITEM_TYPE_ACTIVE) {
|
||||
if (curSel->demod->isRecording()) {
|
||||
curSel->demod->setRecording(false);
|
||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BookmarkView::onRemoveBookmark( wxCommandEvent& /* event */ ) {
|
||||
if (editingLabel) {
|
||||
|
@ -145,6 +145,8 @@ protected:
|
||||
void onBookmarkChoice( wxCommandEvent &event );
|
||||
|
||||
void onRemoveActive( wxCommandEvent& event );
|
||||
void onStartRecording( wxCommandEvent& event );
|
||||
void onStopRecording( wxCommandEvent& event );
|
||||
void onRemoveBookmark( wxCommandEvent& event );
|
||||
|
||||
void onActivateBookmark( wxCommandEvent& event );
|
||||
|
@ -6534,6 +6534,421 @@
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Chad Myslinsky</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_dChadMyslinsky</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Charlie Bruckner</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_dCharlieBruckner</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Jordan Parker</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_dJordanParker</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Robert Chave</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_dRobertChave</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Marvin Calvert</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_dMarvinCalvert</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 27 2017)
|
||||
// C++ code generated with wxFormBuilder (version Nov 6 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -9,475 +9,495 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AboutDialogBase::AboutDialogBase(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
|
||||
AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
|
||||
|
||||
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
|
||||
|
||||
wxBoxSizer* dlgSizer;
|
||||
dlgSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_hPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
dlgSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_hPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* m_hSizer;
|
||||
m_hSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_appName = new wxStaticText(m_hPanel, wxID_ANY, wxT("CubicSDR"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_appName->Wrap(-1);
|
||||
m_appName->SetFont(wxFont(20, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_hSizer->Add(m_appName, 0, wxALL, 6);
|
||||
|
||||
|
||||
m_hPanel->SetSizer(m_hSizer);
|
||||
m_hSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_appName = new wxStaticText( m_hPanel, wxID_ANY, wxT("CubicSDR"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_appName->Wrap( -1 );
|
||||
m_appName->SetFont( wxFont( 20, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_hSizer->Add( m_appName, 0, wxALL, 6 );
|
||||
|
||||
|
||||
m_hPanel->SetSizer( m_hSizer );
|
||||
m_hPanel->Layout();
|
||||
m_hSizer->Fit(m_hPanel);
|
||||
dlgSizer->Add(m_hPanel, 0, wxALL | wxEXPAND, 5);
|
||||
|
||||
m_aboutNotebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbScroll = new wxScrolledWindow(m_aboutNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL);
|
||||
m_dbScroll->SetScrollRate(5, 5);
|
||||
m_hSizer->Fit( m_hPanel );
|
||||
dlgSizer->Add( m_hPanel, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_aboutNotebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbScroll = new wxScrolledWindow( m_aboutNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
|
||||
m_dbScroll->SetScrollRate( 5, 5 );
|
||||
wxBoxSizer* m_dbPane;
|
||||
m_dbPane = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_dbPane = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* m_dbSizer;
|
||||
m_dbSizer = new wxFlexGridSizer(0, 3, 2, 20);
|
||||
m_dbSizer->SetFlexibleDirection(wxBOTH);
|
||||
m_dbSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
|
||||
|
||||
m_dbHeader = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Developed By"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_dbHeader->Wrap(-1);
|
||||
m_dbHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_dbSizer->Add(m_dbHeader, 0, wxALL, 5);
|
||||
|
||||
m_dbGHHeader = new wxStaticText(m_dbScroll, wxID_ANY, wxT("GitHub"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbGHHeader->Wrap(-1);
|
||||
m_dbGHHeader->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_dbSizer->Add(m_dbGHHeader, 0, wxALL, 5);
|
||||
|
||||
m_dbTwitter = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Twitter"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbTwitter->Wrap(-1);
|
||||
m_dbTwitter->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_dbSizer->Add(m_dbTwitter, 0, wxALL, 5);
|
||||
|
||||
m_dbCharlesCliffe = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Charles J. Cliffe"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbCharlesCliffe->Wrap(-1);
|
||||
m_dbSizer->Add(m_dbCharlesCliffe, 0, wxALL, 5);
|
||||
|
||||
m_dbghCC = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@cjcliffe"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbghCC->Wrap(-1);
|
||||
m_dbSizer->Add(m_dbghCC, 0, wxALL, 5);
|
||||
|
||||
m_dbtCC = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@ccliffe"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbtCC->Wrap(-1);
|
||||
m_dbSizer->Add(m_dbtCC, 0, wxALL, 5);
|
||||
|
||||
m_dbVincentSonnier = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Vincent Sonnier"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbVincentSonnier->Wrap(-1);
|
||||
m_dbSizer->Add(m_dbVincentSonnier, 0, wxALL, 5);
|
||||
|
||||
m_dbghVS = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@vsonnier"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbghVS->Wrap(-1);
|
||||
m_dbSizer->Add(m_dbghVS, 0, wxALL, 5);
|
||||
|
||||
m_dbtVS = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@VincentSonnier"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dbtVS->Wrap(-1);
|
||||
m_dbSizer->Add(m_dbtVS, 0, wxALL, 5);
|
||||
|
||||
|
||||
m_dbPane->Add(m_dbSizer, 0, wxALL | wxEXPAND, 5);
|
||||
|
||||
m_dbDivider1 = new wxStaticLine(m_dbScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||
m_dbPane->Add(m_dbDivider1, 0, wxALL | wxEXPAND, 10);
|
||||
|
||||
m_dbSizer = new wxFlexGridSizer( 0, 3, 2, 20 );
|
||||
m_dbSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_dbSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL );
|
||||
|
||||
m_dbHeader = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Developed By"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_dbHeader->Wrap( -1 );
|
||||
m_dbHeader->SetFont( wxFont( 15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_dbSizer->Add( m_dbHeader, 0, wxALL, 5 );
|
||||
|
||||
m_dbGHHeader = new wxStaticText( m_dbScroll, wxID_ANY, wxT("GitHub"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbGHHeader->Wrap( -1 );
|
||||
m_dbGHHeader->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_dbSizer->Add( m_dbGHHeader, 0, wxALL, 5 );
|
||||
|
||||
m_dbTwitter = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Twitter"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbTwitter->Wrap( -1 );
|
||||
m_dbTwitter->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_dbSizer->Add( m_dbTwitter, 0, wxALL, 5 );
|
||||
|
||||
m_dbCharlesCliffe = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Charles J. Cliffe"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbCharlesCliffe->Wrap( -1 );
|
||||
m_dbSizer->Add( m_dbCharlesCliffe, 0, wxALL, 5 );
|
||||
|
||||
m_dbghCC = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@cjcliffe"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbghCC->Wrap( -1 );
|
||||
m_dbSizer->Add( m_dbghCC, 0, wxALL, 5 );
|
||||
|
||||
m_dbtCC = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@ccliffe"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbtCC->Wrap( -1 );
|
||||
m_dbSizer->Add( m_dbtCC, 0, wxALL, 5 );
|
||||
|
||||
m_dbVincentSonnier = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Vincent Sonnier"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbVincentSonnier->Wrap( -1 );
|
||||
m_dbSizer->Add( m_dbVincentSonnier, 0, wxALL, 5 );
|
||||
|
||||
m_dbghVS = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@vsonnier"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbghVS->Wrap( -1 );
|
||||
m_dbSizer->Add( m_dbghVS, 0, wxALL, 5 );
|
||||
|
||||
m_dbtVS = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@VincentSonnier"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dbtVS->Wrap( -1 );
|
||||
m_dbSizer->Add( m_dbtVS, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_dbPane->Add( m_dbSizer, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_dbDivider1 = new wxStaticLine( m_dbScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
m_dbPane->Add( m_dbDivider1, 0, wxALL|wxEXPAND, 10 );
|
||||
|
||||
wxFlexGridSizer* m_cSizer;
|
||||
m_cSizer = new wxFlexGridSizer(0, 2, 2, 20);
|
||||
m_cSizer->SetFlexibleDirection(wxBOTH);
|
||||
m_cSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
|
||||
|
||||
m_cContributorsHeader = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Contributors"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_cContributorsHeader->Wrap(-1);
|
||||
m_cContributorsHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_cSizer->Add(m_cContributorsHeader, 0, wxALL, 5);
|
||||
|
||||
m_cGitHub = new wxStaticText(m_dbScroll, wxID_ANY, wxT("GitHub"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cGitHub->Wrap(-1);
|
||||
m_cGitHub->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_cSizer->Add(m_cGitHub, 0, wxALL, 5);
|
||||
|
||||
m_cCorneLukken = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Corne Lukken"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cCorneLukken->Wrap(-1);
|
||||
m_cSizer->Add(m_cCorneLukken, 0, wxALL, 5);
|
||||
|
||||
m_cghCL = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@Dantali0n"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghCL->Wrap(-1);
|
||||
m_cSizer->Add(m_cghCL, 0, wxALL, 5);
|
||||
|
||||
m_cStainislawPitucha = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Stanisław Pitucha"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cStainislawPitucha->Wrap(-1);
|
||||
m_cSizer->Add(m_cStainislawPitucha, 0, wxALL, 5);
|
||||
|
||||
m_cghSP = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@viraptor"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghSP->Wrap(-1);
|
||||
m_cSizer->Add(m_cghSP, 0, wxALL, 5);
|
||||
|
||||
m_cghStefanTalpalaru = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Ștefan Talpalaru"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghStefanTalpalaru->Wrap(-1);
|
||||
m_cSizer->Add(m_cghStefanTalpalaru, 0, wxALL, 5);
|
||||
|
||||
m_cghST = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@stefantalpalaru"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghST->Wrap(-1);
|
||||
m_cSizer->Add(m_cghST, 0, wxALL, 5);
|
||||
|
||||
m_cCrisMotch = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Chris Motch"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cCrisMotch->Wrap(-1);
|
||||
m_cSizer->Add(m_cCrisMotch, 0, wxALL, 5);
|
||||
|
||||
m_cghCM = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@bodrick"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghCM->Wrap(-1);
|
||||
m_cSizer->Add(m_cghCM, 0, wxALL, 5);
|
||||
|
||||
m_cMariuszRyndzionek = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Mariusz Ryndzionek"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cMariuszRyndzionek->Wrap(-1);
|
||||
m_cSizer->Add(m_cMariuszRyndzionek, 0, wxALL, 5);
|
||||
|
||||
m_cghMR = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@mryndzionek"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghMR->Wrap(-1);
|
||||
m_cSizer->Add(m_cghMR, 0, wxALL, 5);
|
||||
|
||||
m_cJiangWei = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Jiang Wei"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cJiangWei->Wrap(-1);
|
||||
m_cSizer->Add(m_cJiangWei, 0, wxALL, 5);
|
||||
|
||||
m_cghJW = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@jocover"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghJW->Wrap(-1);
|
||||
m_cSizer->Add(m_cghJW, 0, wxALL, 5);
|
||||
|
||||
m_cTomSwartz = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Tom Swartz"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cTomSwartz->Wrap(-1);
|
||||
m_cSizer->Add(m_cTomSwartz, 0, wxALL, 5);
|
||||
|
||||
m_cghTS = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@tomswartz07"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghTS->Wrap(-1);
|
||||
m_cSizer->Add(m_cghTS, 0, wxALL, 5);
|
||||
|
||||
m_cInfinityCyberworks = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Infinity Cyberworks"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cInfinityCyberworks->Wrap(-1);
|
||||
m_cSizer->Add(m_cInfinityCyberworks, 0, wxALL, 5);
|
||||
|
||||
m_cghIC = new wxStaticText(m_dbScroll, wxID_ANY, wxT("@infinitycyberworks"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_cghIC->Wrap(-1);
|
||||
m_cSizer->Add(m_cghIC, 0, wxALL, 5);
|
||||
|
||||
|
||||
m_dbPane->Add(m_cSizer, 0, wxALL | wxEXPAND, 5);
|
||||
|
||||
|
||||
m_dbScroll->SetSizer(m_dbPane);
|
||||
m_cSizer = new wxFlexGridSizer( 0, 2, 2, 20 );
|
||||
m_cSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_cSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL );
|
||||
|
||||
m_cContributorsHeader = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Contributors"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_cContributorsHeader->Wrap( -1 );
|
||||
m_cContributorsHeader->SetFont( wxFont( 15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_cSizer->Add( m_cContributorsHeader, 0, wxALL, 5 );
|
||||
|
||||
m_cGitHub = new wxStaticText( m_dbScroll, wxID_ANY, wxT("GitHub"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cGitHub->Wrap( -1 );
|
||||
m_cGitHub->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_cSizer->Add( m_cGitHub, 0, wxALL, 5 );
|
||||
|
||||
m_cCorneLukken = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Corne Lukken"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cCorneLukken->Wrap( -1 );
|
||||
m_cSizer->Add( m_cCorneLukken, 0, wxALL, 5 );
|
||||
|
||||
m_cghCL = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@Dantali0n"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghCL->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghCL, 0, wxALL, 5 );
|
||||
|
||||
m_cStainislawPitucha = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Stanisław Pitucha"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cStainislawPitucha->Wrap( -1 );
|
||||
m_cSizer->Add( m_cStainislawPitucha, 0, wxALL, 5 );
|
||||
|
||||
m_cghSP = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@viraptor"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghSP->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghSP, 0, wxALL, 5 );
|
||||
|
||||
m_cghStefanTalpalaru = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Ștefan Talpalaru"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghStefanTalpalaru->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghStefanTalpalaru, 0, wxALL, 5 );
|
||||
|
||||
m_cghST = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@stefantalpalaru"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghST->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghST, 0, wxALL, 5 );
|
||||
|
||||
m_cCrisMotch = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Chris Motch"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cCrisMotch->Wrap( -1 );
|
||||
m_cSizer->Add( m_cCrisMotch, 0, wxALL, 5 );
|
||||
|
||||
m_cghCM = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@bodrick"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghCM->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghCM, 0, wxALL, 5 );
|
||||
|
||||
m_cMariuszRyndzionek = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Mariusz Ryndzionek"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cMariuszRyndzionek->Wrap( -1 );
|
||||
m_cSizer->Add( m_cMariuszRyndzionek, 0, wxALL, 5 );
|
||||
|
||||
m_cghMR = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@mryndzionek"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghMR->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghMR, 0, wxALL, 5 );
|
||||
|
||||
m_cJiangWei = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Jiang Wei"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cJiangWei->Wrap( -1 );
|
||||
m_cSizer->Add( m_cJiangWei, 0, wxALL, 5 );
|
||||
|
||||
m_cghJW = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@jocover"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghJW->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghJW, 0, wxALL, 5 );
|
||||
|
||||
m_cTomSwartz = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Tom Swartz"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cTomSwartz->Wrap( -1 );
|
||||
m_cSizer->Add( m_cTomSwartz, 0, wxALL, 5 );
|
||||
|
||||
m_cghTS = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@tomswartz07"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghTS->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghTS, 0, wxALL, 5 );
|
||||
|
||||
m_cInfinityCyberworks = new wxStaticText( m_dbScroll, wxID_ANY, wxT("Infinity Cyberworks"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cInfinityCyberworks->Wrap( -1 );
|
||||
m_cSizer->Add( m_cInfinityCyberworks, 0, wxALL, 5 );
|
||||
|
||||
m_cghIC = new wxStaticText( m_dbScroll, wxID_ANY, wxT("@infinitycyberworks"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cghIC->Wrap( -1 );
|
||||
m_cSizer->Add( m_cghIC, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_dbPane->Add( m_cSizer, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_dbScroll->SetSizer( m_dbPane );
|
||||
m_dbScroll->Layout();
|
||||
m_dbPane->Fit(m_dbScroll);
|
||||
m_aboutNotebook->AddPage(m_dbScroll, wxT("Developers"), false);
|
||||
m_dScroll = new wxScrolledWindow(m_aboutNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL);
|
||||
m_dScroll->SetScrollRate(5, 5);
|
||||
m_dbPane->Fit( m_dbScroll );
|
||||
m_aboutNotebook->AddPage( m_dbScroll, wxT("Developers"), false );
|
||||
m_dScroll = new wxScrolledWindow( m_aboutNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
|
||||
m_dScroll->SetScrollRate( 5, 5 );
|
||||
wxBoxSizer* m_dBSizer;
|
||||
m_dBSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_dBSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* m_dSizer;
|
||||
m_dSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_dHeader = new wxStaticText(m_dScroll, wxID_ANY, wxT("Thanks to everyone who donated at cubicsdr.com!"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_dHeader->Wrap(-1);
|
||||
m_dHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_dSizer->Add(m_dHeader, 0, wxALL, 5);
|
||||
|
||||
m_dDivider1 = new wxStaticLine(m_dScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||
m_dSizer->Add(m_dDivider1, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_dSDRplay = new wxStaticText(m_dScroll, wxID_ANY, wxT("SDRplay / sdrplay.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dSDRplay->Wrap(-1);
|
||||
m_dSizer->Add(m_dSDRplay, 0, wxALL, 5);
|
||||
|
||||
m_dMichaelLadd = new wxStaticText(m_dScroll, wxID_ANY, wxT("Michael Ladd"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dMichaelLadd->Wrap(-1);
|
||||
m_dSizer->Add(m_dMichaelLadd, 0, wxALL, 5);
|
||||
|
||||
m_dAutoMotiveTemplates = new wxStaticText(m_dScroll, wxID_ANY, wxT("Automotive Templates"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dAutoMotiveTemplates->Wrap(-1);
|
||||
m_dSizer->Add(m_dAutoMotiveTemplates, 0, wxALL, 5);
|
||||
|
||||
m_dJorgeMorales = new wxStaticText(m_dScroll, wxID_ANY, wxT("Jorge Morales"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dJorgeMorales->Wrap(-1);
|
||||
m_dSizer->Add(m_dJorgeMorales, 0, wxALL, 5);
|
||||
|
||||
m_dMichaelRooke = new wxStaticText(m_dScroll, wxID_ANY, wxT("Michael Rooke"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dMichaelRooke->Wrap(-1);
|
||||
m_dSizer->Add(m_dMichaelRooke, 0, wxALL, 5);
|
||||
|
||||
m_dTNCOM = new wxStaticText(m_dScroll, wxID_ANY, wxT("TNCOM"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dTNCOM->Wrap(-1);
|
||||
m_dSizer->Add(m_dTNCOM, 0, wxALL, 5);
|
||||
|
||||
m_dErikWied = new wxStaticText(m_dScroll, wxID_ANY, wxT("Erik Mikkel Wied"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dErikWied->Wrap(-1);
|
||||
m_dSizer->Add(m_dErikWied, 0, wxALL, 5);
|
||||
|
||||
m_dRobertDuering = new wxStaticText(m_dScroll, wxID_ANY, wxT("Robert Duering"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dRobertDuering->Wrap(-1);
|
||||
m_dSizer->Add(m_dRobertDuering, 0, wxALL, 5);
|
||||
|
||||
m_dJimDeitch = new wxStaticText(m_dScroll, wxID_ANY, wxT("Jim Deitch"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dJimDeitch->Wrap(-1);
|
||||
m_dSizer->Add(m_dJimDeitch, 0, wxALL, 5);
|
||||
|
||||
m_dNooElec = new wxStaticText(m_dScroll, wxID_ANY, wxT("NooElec Inc. / nooelec.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dNooElec->Wrap(-1);
|
||||
m_dSizer->Add(m_dNooElec, 0, wxALL, 5);
|
||||
|
||||
m_dDavidAhlgren = new wxStaticText(m_dScroll, wxID_ANY, wxT("David Ahlgren"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dDavidAhlgren->Wrap(-1);
|
||||
m_dSizer->Add(m_dDavidAhlgren, 0, wxALL, 5);
|
||||
|
||||
m_dRonaldCook = new wxStaticText(m_dScroll, wxID_ANY, wxT("Ronald Cook"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dRonaldCook->Wrap(-1);
|
||||
m_dSizer->Add(m_dRonaldCook, 0, wxALL, 5);
|
||||
|
||||
m_dEricPeterson = new wxStaticText(m_dScroll, wxID_ANY, wxT("Eric Peterson"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dEricPeterson->Wrap(-1);
|
||||
m_dSizer->Add(m_dEricPeterson, 0, wxALL, 5);
|
||||
|
||||
m_dGeoDistributing = new wxStaticText(m_dScroll, wxID_ANY, wxT("Geo Distributing"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dGeoDistributing->Wrap(-1);
|
||||
m_dSizer->Add(m_dGeoDistributing, 0, wxALL, 5);
|
||||
|
||||
m_dJamesCarson = new wxStaticText(m_dScroll, wxID_ANY, wxT("James Carson"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dJamesCarson->Wrap(-1);
|
||||
m_dSizer->Add(m_dJamesCarson, 0, wxALL, 5);
|
||||
|
||||
m_dCraigWilliams = new wxStaticText(m_dScroll, wxID_ANY, wxT("Craig Williams"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dCraigWilliams->Wrap(-1);
|
||||
m_dSizer->Add(m_dCraigWilliams, 0, wxALL, 5);
|
||||
|
||||
m_dRudolfShaffer = new wxStaticText(m_dScroll, wxID_ANY, wxT("Rudolf Schaffer"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dRudolfShaffer->Wrap(-1);
|
||||
m_dSizer->Add(m_dRudolfShaffer, 0, wxALL, 5);
|
||||
|
||||
m_dJohnKaton = new wxStaticText(m_dScroll, wxID_ANY, wxT("John Katon"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dJohnKaton->Wrap(-1);
|
||||
m_dSizer->Add(m_dJohnKaton, 0, wxALL, 5);
|
||||
|
||||
m_dVincentSonnier = new wxStaticText(m_dScroll, wxID_ANY, wxT("Vincent Sonnier"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dVincentSonnier->Wrap(-1);
|
||||
m_dSizer->Add(m_dVincentSonnier, 0, wxALL, 5);
|
||||
|
||||
m_dCorq = new wxStaticText(m_dScroll, wxID_ANY, wxT("corq's auctions/L. Easterly LTD (x 4)"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dCorq->Wrap(-1);
|
||||
m_dSizer->Add(m_dCorq, 0, wxALL, 5);
|
||||
|
||||
m_dIvanAlekseev = new wxStaticText(m_dScroll, wxID_ANY, wxT("Ivan Alekseev"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dIvanAlekseev->Wrap(-1);
|
||||
m_dSizer->Add(m_dIvanAlekseev, 0, wxALL, 5);
|
||||
|
||||
m_dOleJorgenKolsrud = new wxStaticText(m_dScroll, wxID_ANY, wxT("Ole-Jørgen Næss Kolsrud"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dOleJorgenKolsrud->Wrap(-1);
|
||||
m_dSizer->Add(m_dOleJorgenKolsrud, 0, wxALL, 5);
|
||||
|
||||
m_dHenrikJagemyr = new wxStaticText(m_dScroll, wxID_ANY, wxT("Henrik Jagemyr"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dHenrikJagemyr->Wrap(-1);
|
||||
m_dSizer->Add(m_dHenrikJagemyr, 0, wxALL, 5);
|
||||
|
||||
m_dPeterHaines = new wxStaticText(m_dScroll, wxID_ANY, wxT("Peter Haines"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dPeterHaines->Wrap(-1);
|
||||
m_dSizer->Add(m_dPeterHaines, 0, wxALL, 5);
|
||||
|
||||
m_dLeonAbrassart = new wxStaticText(m_dScroll, wxID_ANY, wxT("Leon Abrassart"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dLeonAbrassart->Wrap(-1);
|
||||
m_dSizer->Add(m_dLeonAbrassart, 0, wxALL, 5);
|
||||
|
||||
m_dGeorgeTalbot = new wxStaticText(m_dScroll, wxID_ANY, wxT("George Alan Talbot"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dGeorgeTalbot->Wrap(-1);
|
||||
m_dSizer->Add(m_dGeorgeTalbot, 0, wxALL, 5);
|
||||
|
||||
m_dFranciscoPuerta = new wxStaticText(m_dScroll, wxID_ANY, wxT("Francisco Borja Marcos de la Puerta"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dFranciscoPuerta->Wrap(-1);
|
||||
m_dSizer->Add(m_dFranciscoPuerta, 0, wxALL, 5);
|
||||
|
||||
m_dRonaldLundeen = new wxStaticText(m_dScroll, wxID_ANY, wxT("Ronald A. Lundeen"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dRonaldLundeen->Wrap(-1);
|
||||
m_dSizer->Add(m_dRonaldLundeen, 0, wxALL, 5);
|
||||
|
||||
m_dWalterHorbert = new wxStaticText(m_dScroll, wxID_ANY, wxT("Walter Horbert"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dWalterHorbert->Wrap(-1);
|
||||
m_dSizer->Add(m_dWalterHorbert, 0, wxALL, 5);
|
||||
|
||||
m_dWilliamLD = new wxStaticText(m_dScroll, wxID_ANY, wxT("William Lloyd-Davies"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dWilliamLD->Wrap(-1);
|
||||
m_dSizer->Add(m_dWilliamLD, 0, wxALL, 5);
|
||||
|
||||
m_dBratislavArandjelovic = new wxStaticText(m_dScroll, wxID_ANY, wxT("Bratislav Arandjelovic"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dBratislavArandjelovic->Wrap(-1);
|
||||
m_dSizer->Add(m_dBratislavArandjelovic, 0, wxALL, 5);
|
||||
|
||||
m_dGaryMartin = new wxStaticText(m_dScroll, wxID_ANY, wxT("Gary Martin"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dGaryMartin->Wrap(-1);
|
||||
m_dSizer->Add(m_dGaryMartin, 0, wxALL, 5);
|
||||
|
||||
m_dEinarsRepse = new wxStaticText(m_dScroll, wxID_ANY, wxT("Einars Repse"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dEinarsRepse->Wrap(-1);
|
||||
m_dSizer->Add(m_dEinarsRepse, 0, wxALL, 5);
|
||||
|
||||
m_dTimothyGatton = new wxStaticText(m_dScroll, wxID_ANY, wxT("Timothy Gatton"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dTimothyGatton->Wrap(-1);
|
||||
m_dSizer->Add(m_dTimothyGatton, 0, wxALL, 5);
|
||||
|
||||
m_dStephenCuccio = new wxStaticText(m_dScroll, wxID_ANY, wxT("Stephen Cuccio"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dStephenCuccio->Wrap(-1);
|
||||
m_dSizer->Add(m_dStephenCuccio, 0, wxALL, 5);
|
||||
|
||||
m_dKeshavlalPatel = new wxStaticText(m_dScroll, wxID_ANY, wxT("Keshavlal Patel"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dKeshavlalPatel->Wrap(-1);
|
||||
m_dSizer->Add(m_dKeshavlalPatel, 0, wxALL, 5);
|
||||
|
||||
m_dBobSchatzman = new wxStaticText(m_dScroll, wxID_ANY, wxT("Bob Schatzman"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dBobSchatzman->Wrap(-1);
|
||||
m_dSizer->Add(m_dBobSchatzman, 0, wxALL, 5);
|
||||
|
||||
m_dRobertRoss = new wxStaticText(m_dScroll, wxID_ANY, wxT("Robert Ross"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dRobertRoss->Wrap(-1);
|
||||
m_dSizer->Add(m_dRobertRoss, 0, wxALL, 5);
|
||||
|
||||
m_dRobertoBellotti = new wxStaticText(m_dScroll, wxID_ANY, wxT("Roberto Bellotti"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dRobertoBellotti->Wrap(-1);
|
||||
m_dSizer->Add(m_dRobertoBellotti, 0, wxALL, 5);
|
||||
|
||||
m_dSergeVanderTorre = new wxStaticText(m_dScroll, wxID_ANY, wxT("Serge Van der Torre"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dSergeVanderTorre->Wrap(-1);
|
||||
m_dSizer->Add(m_dSergeVanderTorre, 0, wxALL, 5);
|
||||
|
||||
m_dDieterSchneider = new wxStaticText(m_dScroll, wxID_ANY, wxT("Dieter Schneider"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dDieterSchneider->Wrap(-1);
|
||||
m_dSizer->Add(m_dDieterSchneider, 0, wxALL, 5);
|
||||
|
||||
m_dPetrikaJaneku = new wxStaticText(m_dScroll, wxID_ANY, wxT("Petrika Janeku"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dPetrikaJaneku->Wrap(-1);
|
||||
m_dSizer->Add(m_dPetrikaJaneku, 0, wxALL, 5);
|
||||
|
||||
|
||||
m_dBSizer->Add(m_dSizer, 1, wxALL | wxEXPAND, 5);
|
||||
|
||||
|
||||
m_dScroll->SetSizer(m_dBSizer);
|
||||
m_dSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_dHeader = new wxStaticText( m_dScroll, wxID_ANY, wxT("Thanks to everyone who donated at cubicsdr.com!"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_dHeader->Wrap( -1 );
|
||||
m_dHeader->SetFont( wxFont( 15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_dSizer->Add( m_dHeader, 0, wxALL, 5 );
|
||||
|
||||
m_dDivider1 = new wxStaticLine( m_dScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
m_dSizer->Add( m_dDivider1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_dSDRplay = new wxStaticText( m_dScroll, wxID_ANY, wxT("SDRplay / sdrplay.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dSDRplay->Wrap( -1 );
|
||||
m_dSizer->Add( m_dSDRplay, 0, wxALL, 5 );
|
||||
|
||||
m_dMichaelLadd = new wxStaticText( m_dScroll, wxID_ANY, wxT("Michael Ladd"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dMichaelLadd->Wrap( -1 );
|
||||
m_dSizer->Add( m_dMichaelLadd, 0, wxALL, 5 );
|
||||
|
||||
m_dAutoMotiveTemplates = new wxStaticText( m_dScroll, wxID_ANY, wxT("Automotive Templates"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dAutoMotiveTemplates->Wrap( -1 );
|
||||
m_dSizer->Add( m_dAutoMotiveTemplates, 0, wxALL, 5 );
|
||||
|
||||
m_dJorgeMorales = new wxStaticText( m_dScroll, wxID_ANY, wxT("Jorge Morales"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dJorgeMorales->Wrap( -1 );
|
||||
m_dSizer->Add( m_dJorgeMorales, 0, wxALL, 5 );
|
||||
|
||||
m_dMichaelRooke = new wxStaticText( m_dScroll, wxID_ANY, wxT("Michael Rooke"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dMichaelRooke->Wrap( -1 );
|
||||
m_dSizer->Add( m_dMichaelRooke, 0, wxALL, 5 );
|
||||
|
||||
m_dTNCOM = new wxStaticText( m_dScroll, wxID_ANY, wxT("TNCOM"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dTNCOM->Wrap( -1 );
|
||||
m_dSizer->Add( m_dTNCOM, 0, wxALL, 5 );
|
||||
|
||||
m_dErikWied = new wxStaticText( m_dScroll, wxID_ANY, wxT("Erik Mikkel Wied"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dErikWied->Wrap( -1 );
|
||||
m_dSizer->Add( m_dErikWied, 0, wxALL, 5 );
|
||||
|
||||
m_dRobertDuering = new wxStaticText( m_dScroll, wxID_ANY, wxT("Robert Duering"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRobertDuering->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRobertDuering, 0, wxALL, 5 );
|
||||
|
||||
m_dJimDeitch = new wxStaticText( m_dScroll, wxID_ANY, wxT("Jim Deitch"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dJimDeitch->Wrap( -1 );
|
||||
m_dSizer->Add( m_dJimDeitch, 0, wxALL, 5 );
|
||||
|
||||
m_dNooElec = new wxStaticText( m_dScroll, wxID_ANY, wxT("NooElec Inc. / nooelec.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dNooElec->Wrap( -1 );
|
||||
m_dSizer->Add( m_dNooElec, 0, wxALL, 5 );
|
||||
|
||||
m_dDavidAhlgren = new wxStaticText( m_dScroll, wxID_ANY, wxT("David Ahlgren"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dDavidAhlgren->Wrap( -1 );
|
||||
m_dSizer->Add( m_dDavidAhlgren, 0, wxALL, 5 );
|
||||
|
||||
m_dRonaldCook = new wxStaticText( m_dScroll, wxID_ANY, wxT("Ronald Cook"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRonaldCook->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRonaldCook, 0, wxALL, 5 );
|
||||
|
||||
m_dEricPeterson = new wxStaticText( m_dScroll, wxID_ANY, wxT("Eric Peterson"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dEricPeterson->Wrap( -1 );
|
||||
m_dSizer->Add( m_dEricPeterson, 0, wxALL, 5 );
|
||||
|
||||
m_dGeoDistributing = new wxStaticText( m_dScroll, wxID_ANY, wxT("Geo Distributing"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dGeoDistributing->Wrap( -1 );
|
||||
m_dSizer->Add( m_dGeoDistributing, 0, wxALL, 5 );
|
||||
|
||||
m_dJamesCarson = new wxStaticText( m_dScroll, wxID_ANY, wxT("James Carson"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dJamesCarson->Wrap( -1 );
|
||||
m_dSizer->Add( m_dJamesCarson, 0, wxALL, 5 );
|
||||
|
||||
m_dCraigWilliams = new wxStaticText( m_dScroll, wxID_ANY, wxT("Craig Williams"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dCraigWilliams->Wrap( -1 );
|
||||
m_dSizer->Add( m_dCraigWilliams, 0, wxALL, 5 );
|
||||
|
||||
m_dRudolfShaffer = new wxStaticText( m_dScroll, wxID_ANY, wxT("Rudolf Schaffer"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRudolfShaffer->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRudolfShaffer, 0, wxALL, 5 );
|
||||
|
||||
m_dJohnKaton = new wxStaticText( m_dScroll, wxID_ANY, wxT("John Katon"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dJohnKaton->Wrap( -1 );
|
||||
m_dSizer->Add( m_dJohnKaton, 0, wxALL, 5 );
|
||||
|
||||
m_dVincentSonnier = new wxStaticText( m_dScroll, wxID_ANY, wxT("Vincent Sonnier"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dVincentSonnier->Wrap( -1 );
|
||||
m_dSizer->Add( m_dVincentSonnier, 0, wxALL, 5 );
|
||||
|
||||
m_dCorq = new wxStaticText( m_dScroll, wxID_ANY, wxT("corq's auctions/L. Easterly LTD (x 4)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dCorq->Wrap( -1 );
|
||||
m_dSizer->Add( m_dCorq, 0, wxALL, 5 );
|
||||
|
||||
m_dIvanAlekseev = new wxStaticText( m_dScroll, wxID_ANY, wxT("Ivan Alekseev"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dIvanAlekseev->Wrap( -1 );
|
||||
m_dSizer->Add( m_dIvanAlekseev, 0, wxALL, 5 );
|
||||
|
||||
m_dOleJorgenKolsrud = new wxStaticText( m_dScroll, wxID_ANY, wxT("Ole-Jørgen Næss Kolsrud"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dOleJorgenKolsrud->Wrap( -1 );
|
||||
m_dSizer->Add( m_dOleJorgenKolsrud, 0, wxALL, 5 );
|
||||
|
||||
m_dHenrikJagemyr = new wxStaticText( m_dScroll, wxID_ANY, wxT("Henrik Jagemyr"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dHenrikJagemyr->Wrap( -1 );
|
||||
m_dSizer->Add( m_dHenrikJagemyr, 0, wxALL, 5 );
|
||||
|
||||
m_dPeterHaines = new wxStaticText( m_dScroll, wxID_ANY, wxT("Peter Haines"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dPeterHaines->Wrap( -1 );
|
||||
m_dSizer->Add( m_dPeterHaines, 0, wxALL, 5 );
|
||||
|
||||
m_dLeonAbrassart = new wxStaticText( m_dScroll, wxID_ANY, wxT("Leon Abrassart"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dLeonAbrassart->Wrap( -1 );
|
||||
m_dSizer->Add( m_dLeonAbrassart, 0, wxALL, 5 );
|
||||
|
||||
m_dGeorgeTalbot = new wxStaticText( m_dScroll, wxID_ANY, wxT("George Alan Talbot"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dGeorgeTalbot->Wrap( -1 );
|
||||
m_dSizer->Add( m_dGeorgeTalbot, 0, wxALL, 5 );
|
||||
|
||||
m_dFranciscoPuerta = new wxStaticText( m_dScroll, wxID_ANY, wxT("Francisco Borja Marcos de la Puerta"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dFranciscoPuerta->Wrap( -1 );
|
||||
m_dSizer->Add( m_dFranciscoPuerta, 0, wxALL, 5 );
|
||||
|
||||
m_dRonaldLundeen = new wxStaticText( m_dScroll, wxID_ANY, wxT("Ronald A. Lundeen"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRonaldLundeen->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRonaldLundeen, 0, wxALL, 5 );
|
||||
|
||||
m_dWalterHorbert = new wxStaticText( m_dScroll, wxID_ANY, wxT("Walter Horbert"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dWalterHorbert->Wrap( -1 );
|
||||
m_dSizer->Add( m_dWalterHorbert, 0, wxALL, 5 );
|
||||
|
||||
m_dWilliamLD = new wxStaticText( m_dScroll, wxID_ANY, wxT("William Lloyd-Davies"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dWilliamLD->Wrap( -1 );
|
||||
m_dSizer->Add( m_dWilliamLD, 0, wxALL, 5 );
|
||||
|
||||
m_dBratislavArandjelovic = new wxStaticText( m_dScroll, wxID_ANY, wxT("Bratislav Arandjelovic"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dBratislavArandjelovic->Wrap( -1 );
|
||||
m_dSizer->Add( m_dBratislavArandjelovic, 0, wxALL, 5 );
|
||||
|
||||
m_dGaryMartin = new wxStaticText( m_dScroll, wxID_ANY, wxT("Gary Martin"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dGaryMartin->Wrap( -1 );
|
||||
m_dSizer->Add( m_dGaryMartin, 0, wxALL, 5 );
|
||||
|
||||
m_dEinarsRepse = new wxStaticText( m_dScroll, wxID_ANY, wxT("Einars Repse"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dEinarsRepse->Wrap( -1 );
|
||||
m_dSizer->Add( m_dEinarsRepse, 0, wxALL, 5 );
|
||||
|
||||
m_dTimothyGatton = new wxStaticText( m_dScroll, wxID_ANY, wxT("Timothy Gatton"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dTimothyGatton->Wrap( -1 );
|
||||
m_dSizer->Add( m_dTimothyGatton, 0, wxALL, 5 );
|
||||
|
||||
m_dStephenCuccio = new wxStaticText( m_dScroll, wxID_ANY, wxT("Stephen Cuccio"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dStephenCuccio->Wrap( -1 );
|
||||
m_dSizer->Add( m_dStephenCuccio, 0, wxALL, 5 );
|
||||
|
||||
m_dKeshavlalPatel = new wxStaticText( m_dScroll, wxID_ANY, wxT("Keshavlal Patel"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dKeshavlalPatel->Wrap( -1 );
|
||||
m_dSizer->Add( m_dKeshavlalPatel, 0, wxALL, 5 );
|
||||
|
||||
m_dBobSchatzman = new wxStaticText( m_dScroll, wxID_ANY, wxT("Bob Schatzman"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dBobSchatzman->Wrap( -1 );
|
||||
m_dSizer->Add( m_dBobSchatzman, 0, wxALL, 5 );
|
||||
|
||||
m_dRobertRoss = new wxStaticText( m_dScroll, wxID_ANY, wxT("Robert Ross"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRobertRoss->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRobertRoss, 0, wxALL, 5 );
|
||||
|
||||
m_dRobertoBellotti = new wxStaticText( m_dScroll, wxID_ANY, wxT("Roberto Bellotti"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRobertoBellotti->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRobertoBellotti, 0, wxALL, 5 );
|
||||
|
||||
m_dSergeVanderTorre = new wxStaticText( m_dScroll, wxID_ANY, wxT("Serge Van der Torre"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dSergeVanderTorre->Wrap( -1 );
|
||||
m_dSizer->Add( m_dSergeVanderTorre, 0, wxALL, 5 );
|
||||
|
||||
m_dDieterSchneider = new wxStaticText( m_dScroll, wxID_ANY, wxT("Dieter Schneider"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dDieterSchneider->Wrap( -1 );
|
||||
m_dSizer->Add( m_dDieterSchneider, 0, wxALL, 5 );
|
||||
|
||||
m_dPetrikaJaneku = new wxStaticText( m_dScroll, wxID_ANY, wxT("Petrika Janeku"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dPetrikaJaneku->Wrap( -1 );
|
||||
m_dSizer->Add( m_dPetrikaJaneku, 0, wxALL, 5 );
|
||||
|
||||
m_dChadMyslinsky = new wxStaticText( m_dScroll, wxID_ANY, wxT("Chad Myslinsky"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dChadMyslinsky->Wrap( -1 );
|
||||
m_dSizer->Add( m_dChadMyslinsky, 0, wxALL, 5 );
|
||||
|
||||
m_dCharlieBruckner = new wxStaticText( m_dScroll, wxID_ANY, wxT("Charlie Bruckner"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dCharlieBruckner->Wrap( -1 );
|
||||
m_dSizer->Add( m_dCharlieBruckner, 0, wxALL, 5 );
|
||||
|
||||
m_dJordanParker = new wxStaticText( m_dScroll, wxID_ANY, wxT("Jordan Parker"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dJordanParker->Wrap( -1 );
|
||||
m_dSizer->Add( m_dJordanParker, 0, wxALL, 5 );
|
||||
|
||||
m_dRobertChave = new wxStaticText( m_dScroll, wxID_ANY, wxT("Robert Chave"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dRobertChave->Wrap( -1 );
|
||||
m_dSizer->Add( m_dRobertChave, 0, wxALL, 5 );
|
||||
|
||||
m_dMarvinCalvert = new wxStaticText( m_dScroll, wxID_ANY, wxT("Marvin Calvert"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_dMarvinCalvert->Wrap( -1 );
|
||||
m_dSizer->Add( m_dMarvinCalvert, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_dBSizer->Add( m_dSizer, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_dScroll->SetSizer( m_dBSizer );
|
||||
m_dScroll->Layout();
|
||||
m_dBSizer->Fit(m_dScroll);
|
||||
m_aboutNotebook->AddPage(m_dScroll, wxT("Donations"), false);
|
||||
m_stScroll = new wxScrolledWindow(m_aboutNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL);
|
||||
m_stScroll->SetScrollRate(5, 5);
|
||||
m_dBSizer->Fit( m_dScroll );
|
||||
m_aboutNotebook->AddPage( m_dScroll, wxT("Donations"), false );
|
||||
m_stScroll = new wxScrolledWindow( m_aboutNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
|
||||
m_stScroll->SetScrollRate( 5, 5 );
|
||||
wxBoxSizer* m_stBSizer;
|
||||
m_stBSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_stBSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* m_stSizer;
|
||||
m_stSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_stHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("Special Thanks To"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_stHeader->Wrap(-1);
|
||||
m_stHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
|
||||
|
||||
m_stSizer->Add(m_stHeader, 0, wxALL, 5);
|
||||
|
||||
m_stDivider1 = new wxStaticLine(m_stScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||
m_stSizer->Add(m_stDivider1, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_stSoapyDevAssistHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("SoapySDR Development and Assistance:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_stSoapyDevAssistHeader->Wrap(-1);
|
||||
m_stSoapyDevAssistHeader->SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString));
|
||||
|
||||
m_stSizer->Add(m_stSoapyDevAssistHeader, 0, wxALL, 5);
|
||||
|
||||
m_stJoshBlum = new wxStaticText(m_stScroll, wxID_ANY, wxT("Josh Blum / @guruofquality / pothosware.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stJoshBlum->Wrap(-1);
|
||||
m_stSizer->Add(m_stJoshBlum, 0, wxALL, 5);
|
||||
|
||||
m_stDivider2 = new wxStaticLine(m_stScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||
m_stSizer->Add(m_stDivider2, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_stLiquidDSPHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("Liquid-DSP Development and Assistance:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_stLiquidDSPHeader->Wrap(-1);
|
||||
m_stLiquidDSPHeader->SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString));
|
||||
|
||||
m_stSizer->Add(m_stLiquidDSPHeader, 0, wxALL, 5);
|
||||
|
||||
m_stJosephGaeddert = new wxStaticText(m_stScroll, wxID_ANY, wxT("Joseph D. Gaeddert / @jgaeddert / liquidsdr.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stJosephGaeddert->Wrap(-1);
|
||||
m_stSizer->Add(m_stJosephGaeddert, 0, wxALL, 5);
|
||||
|
||||
m_stDivider3 = new wxStaticLine(m_stScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||
m_stSizer->Add(m_stDivider3, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_stIdeasDirectionsHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("Ideas, Direction && Encouragement:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_stIdeasDirectionsHeader->Wrap(-1);
|
||||
m_stIdeasDirectionsHeader->SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString));
|
||||
|
||||
m_stSizer->Add(m_stIdeasDirectionsHeader, 0, wxALL, 5);
|
||||
|
||||
m_stTonMachielsen = new wxStaticText(m_stScroll, wxID_ANY, wxT("Ton Machielsen / @Toontje / @EA3HOE "), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stTonMachielsen->Wrap(-1);
|
||||
m_stSizer->Add(m_stTonMachielsen, 0, wxALL, 5);
|
||||
|
||||
m_stMikeLadd = new wxStaticText(m_stScroll, wxID_ANY, wxT("Mike Ladd / KD2KOG.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stMikeLadd->Wrap(-1);
|
||||
m_stSizer->Add(m_stMikeLadd, 0, wxALL, 5);
|
||||
|
||||
m_stSDRplay = new wxStaticText(m_stScroll, wxID_ANY, wxT("SDRplay team / @SDRplay / SDRplay.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stSDRplay->Wrap(-1);
|
||||
m_stSizer->Add(m_stSDRplay, 0, wxALL, 5);
|
||||
|
||||
m_stSDRplayFB = new wxStaticText(m_stScroll, wxID_ANY, wxT("SDRplay Facebook group"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stSDRplayFB->Wrap(-1);
|
||||
m_stSizer->Add(m_stSDRplayFB, 0, wxALL, 5);
|
||||
|
||||
m_stPaulWarren = new wxStaticText(m_stScroll, wxID_ANY, wxT("Paul Warren / @pwarren"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stPaulWarren->Wrap(-1);
|
||||
m_stSizer->Add(m_stPaulWarren, 0, wxALL, 5);
|
||||
|
||||
m_stSegesdiKaroly = new wxStaticText(m_stScroll, wxID_ANY, wxT("Segesdi Károly / @jazzkutya"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stSegesdiKaroly->Wrap(-1);
|
||||
m_stSizer->Add(m_stSegesdiKaroly, 0, wxALL, 5);
|
||||
|
||||
m_stRedditRTLSDR = new wxStaticText(m_stScroll, wxID_ANY, wxT("Reddit RTL-SDR group /r/rtlsdr"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stRedditRTLSDR->Wrap(-1);
|
||||
m_stSizer->Add(m_stRedditRTLSDR, 0, wxALL, 5);
|
||||
|
||||
m_stNooElec = new wxStaticText(m_stScroll, wxID_ANY, wxT("NooElec team / NooElec.com"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stNooElec->Wrap(-1);
|
||||
m_stSizer->Add(m_stNooElec, 0, wxALL, 5);
|
||||
|
||||
m_stGHIssues = new wxStaticText(m_stScroll, wxID_ANY, wxT("Everyone who's contributed to the GitHub issues; thanks!"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stGHIssues->Wrap(-1);
|
||||
m_stSizer->Add(m_stGHIssues, 0, wxALL, 5);
|
||||
|
||||
m_stNominate = new wxStaticText(m_stScroll, wxID_ANY, wxT("Please feel free to nominate anyone we might have missed."), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_stNominate->Wrap(-1);
|
||||
m_stSizer->Add(m_stNominate, 0, wxALL, 5);
|
||||
|
||||
|
||||
m_stBSizer->Add(m_stSizer, 1, wxALL | wxEXPAND, 5);
|
||||
|
||||
|
||||
m_stScroll->SetSizer(m_stBSizer);
|
||||
m_stSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_stHeader = new wxStaticText( m_stScroll, wxID_ANY, wxT("Special Thanks To"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_stHeader->Wrap( -1 );
|
||||
m_stHeader->SetFont( wxFont( 15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
m_stSizer->Add( m_stHeader, 0, wxALL, 5 );
|
||||
|
||||
m_stDivider1 = new wxStaticLine( m_stScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
m_stSizer->Add( m_stDivider1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_stSoapyDevAssistHeader = new wxStaticText( m_stScroll, wxID_ANY, wxT("SoapySDR Development and Assistance:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_stSoapyDevAssistHeader->Wrap( -1 );
|
||||
m_stSoapyDevAssistHeader->SetFont( wxFont( 10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
|
||||
|
||||
m_stSizer->Add( m_stSoapyDevAssistHeader, 0, wxALL, 5 );
|
||||
|
||||
m_stJoshBlum = new wxStaticText( m_stScroll, wxID_ANY, wxT("Josh Blum / @guruofquality / pothosware.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stJoshBlum->Wrap( -1 );
|
||||
m_stSizer->Add( m_stJoshBlum, 0, wxALL, 5 );
|
||||
|
||||
m_stDivider2 = new wxStaticLine( m_stScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
m_stSizer->Add( m_stDivider2, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_stLiquidDSPHeader = new wxStaticText( m_stScroll, wxID_ANY, wxT("Liquid-DSP Development and Assistance:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_stLiquidDSPHeader->Wrap( -1 );
|
||||
m_stLiquidDSPHeader->SetFont( wxFont( 10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
|
||||
|
||||
m_stSizer->Add( m_stLiquidDSPHeader, 0, wxALL, 5 );
|
||||
|
||||
m_stJosephGaeddert = new wxStaticText( m_stScroll, wxID_ANY, wxT("Joseph D. Gaeddert / @jgaeddert / liquidsdr.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stJosephGaeddert->Wrap( -1 );
|
||||
m_stSizer->Add( m_stJosephGaeddert, 0, wxALL, 5 );
|
||||
|
||||
m_stDivider3 = new wxStaticLine( m_stScroll, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
m_stSizer->Add( m_stDivider3, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_stIdeasDirectionsHeader = new wxStaticText( m_stScroll, wxID_ANY, wxT("Ideas, Direction && Encouragement:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
|
||||
m_stIdeasDirectionsHeader->Wrap( -1 );
|
||||
m_stIdeasDirectionsHeader->SetFont( wxFont( 10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
|
||||
|
||||
m_stSizer->Add( m_stIdeasDirectionsHeader, 0, wxALL, 5 );
|
||||
|
||||
m_stTonMachielsen = new wxStaticText( m_stScroll, wxID_ANY, wxT("Ton Machielsen / @Toontje / @EA3HOE "), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stTonMachielsen->Wrap( -1 );
|
||||
m_stSizer->Add( m_stTonMachielsen, 0, wxALL, 5 );
|
||||
|
||||
m_stMikeLadd = new wxStaticText( m_stScroll, wxID_ANY, wxT("Mike Ladd / KD2KOG.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stMikeLadd->Wrap( -1 );
|
||||
m_stSizer->Add( m_stMikeLadd, 0, wxALL, 5 );
|
||||
|
||||
m_stSDRplay = new wxStaticText( m_stScroll, wxID_ANY, wxT("SDRplay team / @SDRplay / SDRplay.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stSDRplay->Wrap( -1 );
|
||||
m_stSizer->Add( m_stSDRplay, 0, wxALL, 5 );
|
||||
|
||||
m_stSDRplayFB = new wxStaticText( m_stScroll, wxID_ANY, wxT("SDRplay Facebook group"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stSDRplayFB->Wrap( -1 );
|
||||
m_stSizer->Add( m_stSDRplayFB, 0, wxALL, 5 );
|
||||
|
||||
m_stPaulWarren = new wxStaticText( m_stScroll, wxID_ANY, wxT("Paul Warren / @pwarren"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stPaulWarren->Wrap( -1 );
|
||||
m_stSizer->Add( m_stPaulWarren, 0, wxALL, 5 );
|
||||
|
||||
m_stSegesdiKaroly = new wxStaticText( m_stScroll, wxID_ANY, wxT("Segesdi Károly / @jazzkutya"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stSegesdiKaroly->Wrap( -1 );
|
||||
m_stSizer->Add( m_stSegesdiKaroly, 0, wxALL, 5 );
|
||||
|
||||
m_stRedditRTLSDR = new wxStaticText( m_stScroll, wxID_ANY, wxT("Reddit RTL-SDR group /r/rtlsdr"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stRedditRTLSDR->Wrap( -1 );
|
||||
m_stSizer->Add( m_stRedditRTLSDR, 0, wxALL, 5 );
|
||||
|
||||
m_stNooElec = new wxStaticText( m_stScroll, wxID_ANY, wxT("NooElec team / NooElec.com"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stNooElec->Wrap( -1 );
|
||||
m_stSizer->Add( m_stNooElec, 0, wxALL, 5 );
|
||||
|
||||
m_stGHIssues = new wxStaticText( m_stScroll, wxID_ANY, wxT("Everyone who's contributed to the GitHub issues; thanks!"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stGHIssues->Wrap( -1 );
|
||||
m_stSizer->Add( m_stGHIssues, 0, wxALL, 5 );
|
||||
|
||||
m_stNominate = new wxStaticText( m_stScroll, wxID_ANY, wxT("Please feel free to nominate anyone we might have missed."), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stNominate->Wrap( -1 );
|
||||
m_stSizer->Add( m_stNominate, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_stBSizer->Add( m_stSizer, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_stScroll->SetSizer( m_stBSizer );
|
||||
m_stScroll->Layout();
|
||||
m_stBSizer->Fit(m_stScroll);
|
||||
m_aboutNotebook->AddPage(m_stScroll, wxT("Special Thanks"), false);
|
||||
|
||||
dlgSizer->Add(m_aboutNotebook, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
|
||||
this->SetSizer(dlgSizer);
|
||||
m_stBSizer->Fit( m_stScroll );
|
||||
m_aboutNotebook->AddPage( m_stScroll, wxT("Special Thanks"), false );
|
||||
|
||||
dlgSizer->Add( m_aboutNotebook, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( dlgSizer );
|
||||
this->Layout();
|
||||
|
||||
this->Centre(wxBOTH);
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
}
|
||||
|
||||
AboutDialogBase::~AboutDialogBase()
|
||||
|
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 27 2017)
|
||||
// C++ code generated with wxFormBuilder (version Nov 6 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -32,114 +32,119 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class AboutDialogBase
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class AboutDialogBase : public wxDialog
|
||||
class AboutDialogBase : public wxDialog
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxPanel* m_hPanel;
|
||||
wxStaticText* m_appName;
|
||||
wxNotebook* m_aboutNotebook;
|
||||
wxScrolledWindow* m_dbScroll;
|
||||
wxStaticText* m_dbHeader;
|
||||
wxStaticText* m_dbGHHeader;
|
||||
wxStaticText* m_dbTwitter;
|
||||
wxStaticText* m_dbCharlesCliffe;
|
||||
wxStaticText* m_dbghCC;
|
||||
wxStaticText* m_dbtCC;
|
||||
wxStaticText* m_dbVincentSonnier;
|
||||
wxStaticText* m_dbghVS;
|
||||
wxStaticText* m_dbtVS;
|
||||
wxStaticLine* m_dbDivider1;
|
||||
wxStaticText* m_cContributorsHeader;
|
||||
wxStaticText* m_cGitHub;
|
||||
wxStaticText* m_cCorneLukken;
|
||||
wxStaticText* m_cghCL;
|
||||
wxStaticText* m_cStainislawPitucha;
|
||||
wxStaticText* m_cghSP;
|
||||
wxStaticText* m_cghStefanTalpalaru;
|
||||
wxStaticText* m_cghST;
|
||||
wxStaticText* m_cCrisMotch;
|
||||
wxStaticText* m_cghCM;
|
||||
wxStaticText* m_cMariuszRyndzionek;
|
||||
wxStaticText* m_cghMR;
|
||||
wxStaticText* m_cJiangWei;
|
||||
wxStaticText* m_cghJW;
|
||||
wxStaticText* m_cTomSwartz;
|
||||
wxStaticText* m_cghTS;
|
||||
wxStaticText* m_cInfinityCyberworks;
|
||||
wxStaticText* m_cghIC;
|
||||
wxScrolledWindow* m_dScroll;
|
||||
wxStaticText* m_dHeader;
|
||||
wxStaticLine* m_dDivider1;
|
||||
wxStaticText* m_dSDRplay;
|
||||
wxStaticText* m_dMichaelLadd;
|
||||
wxStaticText* m_dAutoMotiveTemplates;
|
||||
wxStaticText* m_dJorgeMorales;
|
||||
wxStaticText* m_dMichaelRooke;
|
||||
wxStaticText* m_dTNCOM;
|
||||
wxStaticText* m_dErikWied;
|
||||
wxStaticText* m_dRobertDuering;
|
||||
wxStaticText* m_dJimDeitch;
|
||||
wxStaticText* m_dNooElec;
|
||||
wxStaticText* m_dDavidAhlgren;
|
||||
wxStaticText* m_dRonaldCook;
|
||||
wxStaticText* m_dEricPeterson;
|
||||
wxStaticText* m_dGeoDistributing;
|
||||
wxStaticText* m_dJamesCarson;
|
||||
wxStaticText* m_dCraigWilliams;
|
||||
wxStaticText* m_dRudolfShaffer;
|
||||
wxStaticText* m_dJohnKaton;
|
||||
wxStaticText* m_dVincentSonnier;
|
||||
wxStaticText* m_dCorq;
|
||||
wxStaticText* m_dIvanAlekseev;
|
||||
wxStaticText* m_dOleJorgenKolsrud;
|
||||
wxStaticText* m_dHenrikJagemyr;
|
||||
wxStaticText* m_dPeterHaines;
|
||||
wxStaticText* m_dLeonAbrassart;
|
||||
wxStaticText* m_dGeorgeTalbot;
|
||||
wxStaticText* m_dFranciscoPuerta;
|
||||
wxStaticText* m_dRonaldLundeen;
|
||||
wxStaticText* m_dWalterHorbert;
|
||||
wxStaticText* m_dWilliamLD;
|
||||
wxStaticText* m_dBratislavArandjelovic;
|
||||
wxStaticText* m_dGaryMartin;
|
||||
wxStaticText* m_dEinarsRepse;
|
||||
wxStaticText* m_dTimothyGatton;
|
||||
wxStaticText* m_dStephenCuccio;
|
||||
wxStaticText* m_dKeshavlalPatel;
|
||||
wxStaticText* m_dBobSchatzman;
|
||||
wxStaticText* m_dRobertRoss;
|
||||
wxStaticText* m_dRobertoBellotti;
|
||||
wxStaticText* m_dSergeVanderTorre;
|
||||
wxStaticText* m_dDieterSchneider;
|
||||
wxStaticText* m_dPetrikaJaneku;
|
||||
wxScrolledWindow* m_stScroll;
|
||||
wxStaticText* m_stHeader;
|
||||
wxStaticLine* m_stDivider1;
|
||||
wxStaticText* m_stSoapyDevAssistHeader;
|
||||
wxStaticText* m_stJoshBlum;
|
||||
wxStaticLine* m_stDivider2;
|
||||
wxStaticText* m_stLiquidDSPHeader;
|
||||
wxStaticText* m_stJosephGaeddert;
|
||||
wxStaticLine* m_stDivider3;
|
||||
wxStaticText* m_stIdeasDirectionsHeader;
|
||||
wxStaticText* m_stTonMachielsen;
|
||||
wxStaticText* m_stMikeLadd;
|
||||
wxStaticText* m_stSDRplay;
|
||||
wxStaticText* m_stSDRplayFB;
|
||||
wxStaticText* m_stPaulWarren;
|
||||
wxStaticText* m_stSegesdiKaroly;
|
||||
wxStaticText* m_stRedditRTLSDR;
|
||||
wxStaticText* m_stNooElec;
|
||||
wxStaticText* m_stGHIssues;
|
||||
wxStaticText* m_stNominate;
|
||||
|
||||
public:
|
||||
|
||||
AboutDialogBase(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(530, 420), long style = wxDEFAULT_DIALOG_STYLE);
|
||||
~AboutDialogBase();
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxPanel* m_hPanel;
|
||||
wxStaticText* m_appName;
|
||||
wxNotebook* m_aboutNotebook;
|
||||
wxScrolledWindow* m_dbScroll;
|
||||
wxStaticText* m_dbHeader;
|
||||
wxStaticText* m_dbGHHeader;
|
||||
wxStaticText* m_dbTwitter;
|
||||
wxStaticText* m_dbCharlesCliffe;
|
||||
wxStaticText* m_dbghCC;
|
||||
wxStaticText* m_dbtCC;
|
||||
wxStaticText* m_dbVincentSonnier;
|
||||
wxStaticText* m_dbghVS;
|
||||
wxStaticText* m_dbtVS;
|
||||
wxStaticLine* m_dbDivider1;
|
||||
wxStaticText* m_cContributorsHeader;
|
||||
wxStaticText* m_cGitHub;
|
||||
wxStaticText* m_cCorneLukken;
|
||||
wxStaticText* m_cghCL;
|
||||
wxStaticText* m_cStainislawPitucha;
|
||||
wxStaticText* m_cghSP;
|
||||
wxStaticText* m_cghStefanTalpalaru;
|
||||
wxStaticText* m_cghST;
|
||||
wxStaticText* m_cCrisMotch;
|
||||
wxStaticText* m_cghCM;
|
||||
wxStaticText* m_cMariuszRyndzionek;
|
||||
wxStaticText* m_cghMR;
|
||||
wxStaticText* m_cJiangWei;
|
||||
wxStaticText* m_cghJW;
|
||||
wxStaticText* m_cTomSwartz;
|
||||
wxStaticText* m_cghTS;
|
||||
wxStaticText* m_cInfinityCyberworks;
|
||||
wxStaticText* m_cghIC;
|
||||
wxScrolledWindow* m_dScroll;
|
||||
wxStaticText* m_dHeader;
|
||||
wxStaticLine* m_dDivider1;
|
||||
wxStaticText* m_dSDRplay;
|
||||
wxStaticText* m_dMichaelLadd;
|
||||
wxStaticText* m_dAutoMotiveTemplates;
|
||||
wxStaticText* m_dJorgeMorales;
|
||||
wxStaticText* m_dMichaelRooke;
|
||||
wxStaticText* m_dTNCOM;
|
||||
wxStaticText* m_dErikWied;
|
||||
wxStaticText* m_dRobertDuering;
|
||||
wxStaticText* m_dJimDeitch;
|
||||
wxStaticText* m_dNooElec;
|
||||
wxStaticText* m_dDavidAhlgren;
|
||||
wxStaticText* m_dRonaldCook;
|
||||
wxStaticText* m_dEricPeterson;
|
||||
wxStaticText* m_dGeoDistributing;
|
||||
wxStaticText* m_dJamesCarson;
|
||||
wxStaticText* m_dCraigWilliams;
|
||||
wxStaticText* m_dRudolfShaffer;
|
||||
wxStaticText* m_dJohnKaton;
|
||||
wxStaticText* m_dVincentSonnier;
|
||||
wxStaticText* m_dCorq;
|
||||
wxStaticText* m_dIvanAlekseev;
|
||||
wxStaticText* m_dOleJorgenKolsrud;
|
||||
wxStaticText* m_dHenrikJagemyr;
|
||||
wxStaticText* m_dPeterHaines;
|
||||
wxStaticText* m_dLeonAbrassart;
|
||||
wxStaticText* m_dGeorgeTalbot;
|
||||
wxStaticText* m_dFranciscoPuerta;
|
||||
wxStaticText* m_dRonaldLundeen;
|
||||
wxStaticText* m_dWalterHorbert;
|
||||
wxStaticText* m_dWilliamLD;
|
||||
wxStaticText* m_dBratislavArandjelovic;
|
||||
wxStaticText* m_dGaryMartin;
|
||||
wxStaticText* m_dEinarsRepse;
|
||||
wxStaticText* m_dTimothyGatton;
|
||||
wxStaticText* m_dStephenCuccio;
|
||||
wxStaticText* m_dKeshavlalPatel;
|
||||
wxStaticText* m_dBobSchatzman;
|
||||
wxStaticText* m_dRobertRoss;
|
||||
wxStaticText* m_dRobertoBellotti;
|
||||
wxStaticText* m_dSergeVanderTorre;
|
||||
wxStaticText* m_dDieterSchneider;
|
||||
wxStaticText* m_dPetrikaJaneku;
|
||||
wxStaticText* m_dChadMyslinsky;
|
||||
wxStaticText* m_dCharlieBruckner;
|
||||
wxStaticText* m_dJordanParker;
|
||||
wxStaticText* m_dRobertChave;
|
||||
wxStaticText* m_dMarvinCalvert;
|
||||
wxScrolledWindow* m_stScroll;
|
||||
wxStaticText* m_stHeader;
|
||||
wxStaticLine* m_stDivider1;
|
||||
wxStaticText* m_stSoapyDevAssistHeader;
|
||||
wxStaticText* m_stJoshBlum;
|
||||
wxStaticLine* m_stDivider2;
|
||||
wxStaticText* m_stLiquidDSPHeader;
|
||||
wxStaticText* m_stJosephGaeddert;
|
||||
wxStaticLine* m_stDivider3;
|
||||
wxStaticText* m_stIdeasDirectionsHeader;
|
||||
wxStaticText* m_stTonMachielsen;
|
||||
wxStaticText* m_stMikeLadd;
|
||||
wxStaticText* m_stSDRplay;
|
||||
wxStaticText* m_stSDRplayFB;
|
||||
wxStaticText* m_stPaulWarren;
|
||||
wxStaticText* m_stSegesdiKaroly;
|
||||
wxStaticText* m_stRedditRTLSDR;
|
||||
wxStaticText* m_stNooElec;
|
||||
wxStaticText* m_stGHIssues;
|
||||
wxStaticText* m_stNominate;
|
||||
|
||||
public:
|
||||
|
||||
AboutDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 530,420 ), long style = wxDEFAULT_DIALOG_STYLE );
|
||||
~AboutDialogBase();
|
||||
|
||||
};
|
||||
|
||||
#endif //__ABOUTDIALOGBASE_H__
|
||||
|
@ -104,17 +104,26 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstancePtr demod, RGBA4f color,
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
bool soloMode = wxGetApp().getSoloMode();
|
||||
bool isRecording = demod->isRecording();
|
||||
bool isSolo = soloMode && demod == wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||
|
||||
RGBA4f labelBg(0, 0, 0, 0.35f);
|
||||
|
||||
if (isSolo) {
|
||||
glColor4f(0.8f, 0.8f, 0, 0.35f);
|
||||
labelBg.r = labelBg.g = 0.8f;
|
||||
} else if (demod->isMuted()) {
|
||||
glColor4f(0.8f, 0, 0, 0.35f);
|
||||
labelBg.r = 0.8f;
|
||||
} else if (soloMode) {
|
||||
glColor4f(0.2f, 0, 0, 0.35f);
|
||||
} else {
|
||||
glColor4f(0, 0, 0, 0.35f);
|
||||
labelBg.r = 0.2f;
|
||||
}
|
||||
|
||||
// TODO: Better recording indicator... pulsating red circle?
|
||||
if (isRecording) {
|
||||
auto t = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
||||
labelBg.g = sinf(2.0f * M_PI * (float(t) / 1000.0f)) * 0.25f + 0.75f;
|
||||
}
|
||||
|
||||
glColor4f(labelBg.r, labelBg.g, labelBg.b, labelBg.a);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(uxPos - ofsLeft, hPos + labelHeight, 0.0);
|
||||
@ -156,18 +165,29 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstancePtr demod, RGBA4f color,
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, 0.8f);
|
||||
|
||||
std::string demodLabel = demod->getLabel();
|
||||
|
||||
if (demod->isMuted()) {
|
||||
demodLabel = std::string("[M] ") + demodLabel;
|
||||
} else if (isSolo) {
|
||||
demodLabel = std::string("[S] ") + demodLabel;
|
||||
}
|
||||
|
||||
std::string demodLabel, demodPrefix;
|
||||
|
||||
if (demod->isDeltaLock()) {
|
||||
demodLabel.append(" [V]");
|
||||
demodPrefix.append("V");
|
||||
}
|
||||
|
||||
|
||||
if (isRecording) {
|
||||
demodPrefix.append("R");
|
||||
}
|
||||
|
||||
if (demod->isMuted()) {
|
||||
demodPrefix.append("M");
|
||||
} else if (isSolo) {
|
||||
demodPrefix.append("S");
|
||||
}
|
||||
|
||||
// Set the prefix
|
||||
if (!demodPrefix.empty()) {
|
||||
demodLabel = "[" + demodPrefix + "] ";
|
||||
}
|
||||
// Append the default label
|
||||
demodLabel.append(demod->getLabel());
|
||||
|
||||
if (demod->getDemodulatorType() == "USB") {
|
||||
GLFont::getFont(16, GLFont::getScaleFactor()).drawString(demodLabel, uxPos, hPos, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER, 0, 0, true);
|
||||
} else if (demod->getDemodulatorType() == "LSB") {
|
||||
|
@ -565,25 +565,25 @@ void WaterfallCanvas::updateHoverState() {
|
||||
|
||||
mouseTracker.setVertDragLock(true);
|
||||
mouseTracker.setHorizDragLock(false);
|
||||
setStatusText("Click and drag to change demodulator bandwidth. SPACE or numeric key for direct frequency input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label.");
|
||||
setStatusText("Drag to change bandwidth. SPACE or 0-9 for direct frequency input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label, R to record.");
|
||||
} else {
|
||||
SetCursor(wxCURSOR_SIZING);
|
||||
nextDragState = WF_DRAG_FREQUENCY;
|
||||
|
||||
mouseTracker.setVertDragLock(true);
|
||||
mouseTracker.setHorizDragLock(false);
|
||||
setStatusText("Click and drag to change demodulator frequency; SPACE or numeric key for direct input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label.");
|
||||
setStatusText("Drag to change frequency; SPACE or 0-9 for direct input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label, R to record.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
SetCursor(wxCURSOR_CROSS);
|
||||
nextDragState = WF_DRAG_NONE;
|
||||
if (shiftDown) {
|
||||
setStatusText("Click to create a new demodulator or hold ALT to drag range, SPACE or numeric key for direct center frequency input.");
|
||||
setStatusText("Click to create a new demodulator or hold ALT to drag new range.");
|
||||
}
|
||||
else {
|
||||
setStatusText(
|
||||
"Click to set active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or wheel to Zoom. Arrow keys to navigate/zoom, C to center.");
|
||||
"Click to set demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or wheel to Zoom. Arrow keys to navigate/zoom, C to center. Shift-R record/stop all.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user