1 // Copyright (c) Charles J. Cliffe
2 // SPDX-License-Identifier: GPL-2.0+
3 
4 #pragma once
5 
6 //WX_GL_CORE_PROFILE 1
7 //WX_GL_MAJOR_VERSION 3
8 //WX_GL_MINOR_VERSION 2
9 
10 #include <thread>
11 
12 #include "GLExt.h"
13 #include "PrimaryGLContext.h"
14 
15 #include "ThreadBlockingQueue.h"
16 #include "SoapySDRThread.h"
17 #include "SDREnumerator.h"
18 #include "SDRPostThread.h"
19 #include "AudioThread.h"
20 #include "DemodulatorMgr.h"
21 #include "AppConfig.h"
22 #include "AppFrame.h"
23 #include "FrequencyDialog.h"
24 #include "DemodLabelDialog.h"
25 #include "BookmarkMgr.h"
26 #include "SessionMgr.h"
27 
28 #include "ScopeVisualProcessor.h"
29 #include "SpectrumVisualProcessor.h"
30 #include "SpectrumVisualDataThread.h"
31 #include "SDRDevices.h"
32 #include "Modem.h"
33 
34 #include "ModemFM.h"
35 #include "ModemNBFM.h"
36 #include "ModemFMStereo.h"
37 #include "ModemCW.h"
38 #include "ModemAM.h"
39 #include "ModemUSB.h"
40 #include "ModemLSB.h"
41 #include "ModemDSB.h"
42 #include "ModemIQ.h"
43 
44 #ifdef ENABLE_DIGITAL_LAB
45 #include "ModemAPSK.h"
46 #include "ModemASK.h"
47 #include "ModemBPSK.h"
48 #include "ModemDPSK.h"
49 #include "ModemFSK.h"
50 #include "ModemGMSK.h"
51 #include "ModemOOK.h"
52 #include "ModemPSK.h"
53 #include "ModemQAM.h"
54 #include "ModemQPSK.h"
55 #include "ModemSQAM.h"
56 #include "ModemST.h"
57 #endif
58 
59 #ifdef USE_HAMLIB
60 class RigThread;
61 #endif
62 
63 #include <wx/cmdline.h>
64 
65 #define NUM_DEMODULATORS 1
66 
67 std::string& filterChars(std::string& s, const std::string& allowed);
68 std::string frequencyToStr(long long freq);
69 long long strToFrequency(std::string freqStr);
70 
71 class CubicSDR: public wxApp {
72 public:
73     CubicSDR();
74 
75     PrimaryGLContext &GetContext(wxGLCanvas *canvas);
76     wxGLContextAttrs* GetContextAttributes();
77 
78     bool OnInit() override;
79     int OnExit() override;
80 
81     void OnInitCmdLine(wxCmdLineParser& parser) override;
82     bool OnCmdLineParsed(wxCmdLineParser& parser) override;
83 
84     void deviceSelector();
85     void sdrThreadNotify(SDRThread::SDRThreadState state, const std::string& message);
86     void sdrEnumThreadNotify(SDREnumerator::SDREnumState state, std::string message);
87 
88     void setFrequency(long long freq);
89     long long getFrequency();
90 
91     void lockFrequency(long long freq);
92     bool isFrequencyLocked();
93     void unlockFrequency();
94 
95     void setOffset(long long ofs);
96     long long getOffset();
97 
98     void setAntennaName(const std::string& name);
99     const std::string& getAntennaName();
100 
101     void setChannelizerType(SDRPostThreadChannelizerType chType);
102     SDRPostThreadChannelizerType getChannelizerType();
103 
104 
105     void setSampleRate(long long rate_in);
106     long long getSampleRate();
107 
108 
109     std::vector<SDRDeviceInfo *> *getDevices();
110     void setDevice(SDRDeviceInfo *dev, int waitMsForTermination);
111     void stopDevice(bool store, int waitMsForTermination);
112     SDRDeviceInfo * getDevice();
113 
114     ScopeVisualProcessor *getScopeProcessor();
115     SpectrumVisualProcessor *getSpectrumProcessor();
116     SpectrumVisualProcessor *getDemodSpectrumProcessor();
117 
118     DemodulatorThreadOutputQueuePtr getAudioVisualQueue();
119     DemodulatorThreadInputQueuePtr getIQVisualQueue();
120     DemodulatorThreadInputQueuePtr getWaterfallVisualQueue();
121 
122     DemodulatorMgr &getDemodMgr();
123     BookmarkMgr &getBookmarkMgr();
124     SessionMgr &getSessionMgr();
125 
126     SDRPostThread *getSDRPostThread();
127     SDRThread *getSDRThread();
128 
129     void notifyDemodulatorsChanged();
130 
131     void removeDemodulator(const DemodulatorInstancePtr& demod);
132 
133     void setFrequencySnap(int snap_in);
134     int getFrequencySnap();
135 
136     AppConfig *getConfig();
137     void saveConfig();
138 
139     void setPPM(int ppm_in);
140     int getPPM();
141 
142     void showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetMode = FrequencyDialog::FDIALOG_TARGET_DEFAULT, const wxString& initString = "");
143     void showLabelInput();
144     AppFrame *getAppFrame();
145 
146     bool areDevicesReady();
147     bool areDevicesEnumerating();
148     bool areModulesMissing();
149     std::string getNotification();
150 
151     void notifyMainUIOfDeviceChange(bool forceRefreshOfGains = false);
152 
153     void addRemote(const std::string& remoteAddr);
154     void removeRemote(const std::string& remoteAddr);
155 
156     void setDeviceSelectorClosed();
157     void reEnumerateDevices();
158     bool isDeviceSelectorOpen();
159     void closeDeviceSelector();
160 
161     void setAGCMode(bool mode);
162     bool getAGCMode();
163 
164     void setGain(const std::string& name, float gain_in);
165     float getGain(const std::string& name);
166 
167     void setStreamArgs(SoapySDR::Kwargs streamArgs_in);
168     void setDeviceArgs(SoapySDR::Kwargs settingArgs_in);
169 
170     bool getUseLocalMod();
171     std::string getModulePath();
172 
173     void setActiveGainEntry(std::string gainName);
174     std::string getActiveGainEntry();
175 
176     void setSoloMode(bool solo);
177     bool getSoloMode();
178 
179     bool isShuttingDown();
180 
181 #ifdef USE_HAMLIB
182     RigThread *getRigThread();
183     void initRig(int rigModel, std::string rigPort, int rigSerialRate);
184     void stopRig();
185     bool rigIsActive();
186 #endif
187 
188 private:
189     int FilterEvent(wxEvent& event) override;
190 
191     AppFrame *appframe = nullptr;
192     AppConfig config;
193     PrimaryGLContext *m_glContext = nullptr;
194     wxGLContextAttrs *m_glContextAttributes = nullptr;
195 
196     std::vector<SDRDeviceInfo *> *devs = nullptr;
197 
198     DemodulatorMgr demodMgr;
199     BookmarkMgr bookmarkMgr;
200     SessionMgr sessionMgr;
201 
202     std::atomic_llong frequency;
203     std::atomic_llong offset;
204     std::atomic_int ppm, snap;
205     std::atomic_llong sampleRate;
206     std::string antennaName;
207     std::atomic_bool agcMode;
208     std::atomic_bool shuttingDown;
209 
210     SDRThread *sdrThread = nullptr;
211     SDREnumerator *sdrEnum = nullptr;
212     SDRPostThread *sdrPostThread = nullptr;
213     SpectrumVisualDataThread *spectrumVisualThread = nullptr;
214     SpectrumVisualDataThread *demodVisualThread = nullptr;
215 
216     SDRThreadIQDataQueuePtr pipeSDRIQData;
217     DemodulatorThreadInputQueuePtr pipeIQVisualData;
218     DemodulatorThreadOutputQueuePtr pipeAudioVisualData;
219     DemodulatorThreadInputQueuePtr pipeDemodIQVisualData;
220     DemodulatorThreadInputQueuePtr pipeWaterfallIQVisualData;
221     DemodulatorThreadInputQueuePtr pipeActiveDemodIQVisualData;
222 
223     ScopeVisualProcessor scopeProcessor;
224 
225     SDRDevicesDialog *deviceSelectorDialog = nullptr;
226 
227     SoapySDR::Kwargs streamArgs;
228     SoapySDR::Kwargs settingArgs;
229 
230     std::thread *t_SDR = nullptr;
231     std::thread *t_SDREnum = nullptr;
232     std::thread *t_PostSDR = nullptr;
233     std::thread *t_SpectrumVisual = nullptr;
234     std::thread *t_DemodVisual = nullptr;
235     std::atomic_bool devicesReady;
236     std::atomic_bool devicesFailed;
237     std::atomic_bool deviceSelectorOpen;
238     std::atomic_bool sampleRateInitialized;
239     std::atomic_bool useLocalMod;
240     std::string notifyMessage;
241     std::string modulePath;
242 
243     std::mutex notify_busy;
244 
245     std::atomic_bool frequency_locked;
246     std::atomic_llong lock_freq;
247     FrequencyDialog::FrequencyDialogTarget fdlgTarget;
248     std::string activeGain;
249     std::atomic_bool soloMode;
250     SDRDeviceInfo *stoppedDev;
251 #ifdef USE_HAMLIB
252     RigThread* rigThread = nullptr;
253     std::thread *t_Rig = nullptr;
254 #endif
255 
256     void initAudioDevices() const;
257 };
258 
259 static const wxCmdLineEntryDesc commandLineInfo [] =
260 {
261     { wxCMD_LINE_SWITCH, "h", "help", "Command line parameter help", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
262     { wxCMD_LINE_OPTION, "c", "config", "Specify a named configuration to use, i.e. '-c ham'", wxCMD_LINE_VAL_STRING, 0 },
263     { wxCMD_LINE_OPTION, "m", "modpath", "Load modules from suppplied path, i.e. '-m ~/SoapyMods/'", wxCMD_LINE_VAL_STRING, 0 },
264 #ifdef BUNDLE_SOAPY_MODS
265     { wxCMD_LINE_SWITCH, "b", "bundled", "Use bundled SoapySDR modules first instead of local.", wxCMD_LINE_VAL_NONE, 0 },
266 #endif
267     { wxCMD_LINE_NONE, nullptr, nullptr, nullptr, wxCMD_LINE_VAL_NONE, 0 }
268 };
269 
270 DECLARE_APP(CubicSDR)
271