mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-09-27 15:56:48 -04:00
Can now choose demodulator output devices
This commit is contained in:
parent
b7793ef905
commit
6679b20fbb
@ -22,13 +22,15 @@
|
|||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
|
||||||
//EVT_MENU(wxID_NEW, AppFrame::OnNewWindow)
|
//EVT_MENU(wxID_NEW, AppFrame::OnNewWindow)
|
||||||
EVT_MENU(wxID_CLOSE, AppFrame::OnClose)
|
//EVT_MENU(wxID_CLOSE, AppFrame::OnClose)
|
||||||
|
EVT_MENU(wxID_ANY, AppFrame::OnMenu)
|
||||||
|
|
||||||
EVT_COMMAND(wxID_ANY, wxEVT_THREAD, AppFrame::OnThread)
|
EVT_COMMAND(wxID_ANY, wxEVT_THREAD, AppFrame::OnThread)
|
||||||
EVT_IDLE(AppFrame::OnIdle)
|
EVT_IDLE(AppFrame::OnIdle)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
AppFrame::AppFrame() :
|
AppFrame::AppFrame() :
|
||||||
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
|
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")), activeDemodulator(NULL) {
|
||||||
|
|
||||||
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||||||
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
|
||||||
@ -137,12 +139,14 @@ AppFrame::AppFrame() :
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
for (mdevices_i = output_devices.begin(); mdevices_i != output_devices.end(); mdevices_i++) {
|
for (mdevices_i = output_devices.begin(); mdevices_i != output_devices.end(); mdevices_i++) {
|
||||||
wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE+i,mdevices_i->second.name,wxT("Description?"));
|
wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE+mdevices_i->first,mdevices_i->second.name,wxT("Description?"));
|
||||||
if (mdevices_i->second.isDefaultOutput) {
|
if (mdevices_i->second.isDefaultOutput) {
|
||||||
itm->Check(true);
|
itm->Check(true);
|
||||||
}
|
}
|
||||||
|
output_device_menuitems[mdevices_i->first] = itm;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMenuBar *menuBar = new wxMenuBar;
|
wxMenuBar *menuBar = new wxMenuBar;
|
||||||
@ -166,10 +170,13 @@ AppFrame::~AppFrame() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
|
void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||||
|
if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE+output_devices.size()) {
|
||||||
// true is to force the frame to close
|
if (activeDemodulator) {
|
||||||
Close(true);
|
activeDemodulator->setOutputDevice(event.GetId()-wxID_RT_AUDIO_DEVICE);
|
||||||
|
activeDemodulator = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
|
void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
|
||||||
@ -193,6 +200,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
if (demod) {
|
if (demod) {
|
||||||
if (demod != activeDemodulator) {
|
if (demod != activeDemodulator) {
|
||||||
demodSignalMeter->setInputValue(demod->getSquelchLevel());
|
demodSignalMeter->setInputValue(demod->getSquelchLevel());
|
||||||
|
int outputDevice = demod->getOutputDevice();
|
||||||
|
scopeCanvas->setDeviceName(output_devices[outputDevice].name);
|
||||||
|
output_device_menuitems[outputDevice]->Check(true);
|
||||||
}
|
}
|
||||||
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
|
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
|
||||||
if (demod->getParams().frequency != demodWaterfallCanvas->GetCenterFrequency()) {
|
if (demod->getParams().frequency != demodWaterfallCanvas->GetCenterFrequency()) {
|
||||||
|
@ -21,7 +21,7 @@ public:
|
|||||||
void OnEventInput(wxThreadEvent& event);
|
void OnEventInput(wxThreadEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnClose(wxCommandEvent& event);
|
void OnMenu(wxCommandEvent& event);
|
||||||
void OnNewWindow(wxCommandEvent& event);
|
void OnNewWindow(wxCommandEvent& event);
|
||||||
void OnIdle(wxIdleEvent& event);
|
void OnIdle(wxIdleEvent& event);
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ private:
|
|||||||
|
|
||||||
std::map<int,RtAudio::DeviceInfo> input_devices;
|
std::map<int,RtAudio::DeviceInfo> input_devices;
|
||||||
std::map<int,RtAudio::DeviceInfo> output_devices;
|
std::map<int,RtAudio::DeviceInfo> output_devices;
|
||||||
|
std::map<int,wxMenuItem *> output_device_menuitems;
|
||||||
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@ std::map<int, std::thread *> AudioThread::deviceThread;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
|
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
|
||||||
currentInput(NULL), inputQueue(inputQueue), audio_queue_ptr(0), underflow_count(0), terminated(false), active(false), gain(1.0), threadQueueNotify(
|
currentInput(NULL), inputQueue(inputQueue), audio_queue_ptr(0), underflow_count(0), terminated(false), active(false), output_device(-1), gain(1.0), threadQueueNotify(
|
||||||
threadQueueNotify) {
|
threadQueueNotify) {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
boundThreads = new std::vector<AudioThread *>;
|
boundThreads = new std::vector<AudioThread *>;
|
||||||
@ -25,7 +25,9 @@ AudioThread::~AudioThread() {
|
|||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
void AudioThread::bindThread(AudioThread *other) {
|
void AudioThread::bindThread(AudioThread *other) {
|
||||||
boundThreads.load()->push_back(other);
|
if (boundThreads.find(other) == boundThreads.end()) {
|
||||||
|
boundThreads.load()->push_back(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioThread::removeThread(AudioThread *other) {
|
void AudioThread::removeThread(AudioThread *other) {
|
||||||
@ -263,22 +265,8 @@ void AudioThread::enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioThread::threadMain() {
|
void AudioThread::setupDevice(int deviceId) {
|
||||||
#ifdef __APPLE__
|
parameters.deviceId = deviceId;
|
||||||
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
|
|
||||||
|
|
||||||
std::cout << "Audio thread initializing.." << std::endl;
|
|
||||||
|
|
||||||
if (dac.getDeviceCount() < 1) {
|
|
||||||
std::cout << "No audio devices found!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters.deviceId = dac.getDefaultOutputDevice();
|
|
||||||
parameters.nChannels = 2;
|
parameters.nChannels = 2;
|
||||||
parameters.firstChannel = 0;
|
parameters.firstChannel = 0;
|
||||||
unsigned int sampleRate = AUDIO_FREQUENCY;
|
unsigned int sampleRate = AUDIO_FREQUENCY;
|
||||||
@ -287,9 +275,15 @@ void AudioThread::threadMain() {
|
|||||||
RtAudio::StreamOptions opts;
|
RtAudio::StreamOptions opts;
|
||||||
opts.streamName = "CubicSDR Audio Output";
|
opts.streamName = "CubicSDR Audio Output";
|
||||||
|
|
||||||
|
output_device = deviceId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
if (active && deviceController.find(parameters.deviceId) != deviceController.end()) {
|
||||||
|
deviceController[parameters.deviceId]->removeThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
opts.priority = sched_get_priority_max(SCHED_FIFO);
|
opts.priority = sched_get_priority_max(SCHED_FIFO);
|
||||||
// opts.flags = RTAUDIO_MINIMIZE_LATENCY;
|
// opts.flags = RTAUDIO_MINIMIZE_LATENCY;
|
||||||
opts.flags = RTAUDIO_SCHEDULE_REALTIME;
|
opts.flags = RTAUDIO_SCHEDULE_REALTIME;
|
||||||
@ -306,6 +300,13 @@ void AudioThread::threadMain() {
|
|||||||
}
|
}
|
||||||
active = true;
|
active = true;
|
||||||
#else
|
#else
|
||||||
|
if (dac.isStreamOpen()) {
|
||||||
|
if (dac.isStreamRunning()) {
|
||||||
|
dac.stopStream();
|
||||||
|
}
|
||||||
|
dac.closeStream();
|
||||||
|
}
|
||||||
|
|
||||||
dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, (void *) this, &opts);
|
dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, (void *) this, &opts);
|
||||||
dac.startStream();
|
dac.startStream();
|
||||||
|
|
||||||
@ -314,10 +315,39 @@ void AudioThread::threadMain() {
|
|||||||
e.printMessage();
|
e.printMessage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AudioThread::getOutputDevice() {
|
||||||
|
if (output_device == -1) {
|
||||||
|
return dac.getDefaultOutputDevice();
|
||||||
|
}
|
||||||
|
return output_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioThread::threadMain() {
|
||||||
|
#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
|
||||||
|
|
||||||
|
std::cout << "Audio thread initializing.." << std::endl;
|
||||||
|
|
||||||
|
if (dac.getDeviceCount() < 1) {
|
||||||
|
std::cout << "No audio devices found!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupDevice(dac.getDefaultOutputDevice());
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
AudioThreadCommand command;
|
AudioThreadCommand command;
|
||||||
cmdQueue.pop(command);
|
cmdQueue.pop(command);
|
||||||
|
|
||||||
|
if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE) {
|
||||||
|
setupDevice(command.int_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -387,3 +417,8 @@ void AudioThread::setActive(bool state) {
|
|||||||
#endif
|
#endif
|
||||||
active = state;
|
active = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AudioThreadCommandQueue *AudioThread::getCommandQueue() {
|
||||||
|
return &cmdQueue;
|
||||||
|
}
|
||||||
|
@ -61,6 +61,7 @@ public:
|
|||||||
std::atomic<unsigned int> underflow_count;
|
std::atomic<unsigned int> underflow_count;
|
||||||
std::atomic<bool> terminated;
|
std::atomic<bool> terminated;
|
||||||
std::atomic<bool> active;
|
std::atomic<bool> active;
|
||||||
|
std::atomic<int> output_device;
|
||||||
float gain;
|
float gain;
|
||||||
|
|
||||||
AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
|
AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
|
||||||
@ -68,12 +69,16 @@ public:
|
|||||||
|
|
||||||
static void enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs);
|
static void enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs);
|
||||||
|
|
||||||
|
void setupDevice(int deviceId);
|
||||||
|
int getOutputDevice();
|
||||||
void threadMain();
|
void threadMain();
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
bool isActive();
|
bool isActive();
|
||||||
void setActive(bool state);
|
void setActive(bool state);
|
||||||
|
|
||||||
|
AudioThreadCommandQueue *getCommandQueue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RtAudio dac;
|
RtAudio dac;
|
||||||
RtAudio::StreamParameters parameters;
|
RtAudio::StreamParameters parameters;
|
||||||
|
@ -194,3 +194,16 @@ float DemodulatorInstance::getSquelchLevel() {
|
|||||||
return demodulatorThread->getSquelchLevel();
|
return demodulatorThread->getSquelchLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DemodulatorInstance::setOutputDevice(int device_id) {
|
||||||
|
if (audioThread) {
|
||||||
|
AudioThreadCommand command;
|
||||||
|
command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE;
|
||||||
|
command.int_value = device_id;
|
||||||
|
audioThread->getCommandQueue()->push(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DemodulatorInstance::getOutputDevice() {
|
||||||
|
return audioThread->getOutputDevice();
|
||||||
|
}
|
||||||
|
@ -60,6 +60,9 @@ public:
|
|||||||
void setSquelchLevel(float signal_level_in);
|
void setSquelchLevel(float signal_level_in);
|
||||||
float getSquelchLevel();
|
float getSquelchLevel();
|
||||||
|
|
||||||
|
void setOutputDevice(int device_id);
|
||||||
|
int getOutputDevice();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<std::string *> label; //
|
std::atomic<std::string *> label; //
|
||||||
bool terminated; //
|
bool terminated; //
|
||||||
|
@ -382,7 +382,7 @@ void GLFont::drawString(std::string str, float xpos, float ypos, int pxHeight, A
|
|||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(xpos, ypos, 0.0f);
|
glTranslatef(xpos, ypos, 0.0f);
|
||||||
|
|
||||||
switch (hAlign) {
|
switch (vAlign) {
|
||||||
case GLFONT_ALIGN_TOP:
|
case GLFONT_ALIGN_TOP:
|
||||||
glTranslatef(0.0, -size, 0.0);
|
glTranslatef(0.0, -size, 0.0);
|
||||||
break;
|
break;
|
||||||
@ -393,7 +393,7 @@ void GLFont::drawString(std::string str, float xpos, float ypos, int pxHeight, A
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (vAlign) {
|
switch (hAlign) {
|
||||||
case GLFONT_ALIGN_RIGHT:
|
case GLFONT_ALIGN_RIGHT:
|
||||||
glTranslatef(-msgWidth, 0.0, 0.0);
|
glTranslatef(-msgWidth, 0.0, 0.0);
|
||||||
break;
|
break;
|
||||||
@ -445,5 +445,6 @@ void GLFont::drawString(std::string str, float xpos, float ypos, int pxHeight, A
|
|||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +21,9 @@ wxEND_EVENT_TABLE()
|
|||||||
|
|
||||||
ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) :
|
ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) :
|
||||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), stereo(false) {
|
wxFULL_REPAINT_ON_RESIZE), parent(parent), stereo(false) {
|
||||||
|
|
||||||
glContext = new ScopeContext(this, &wxGetApp().GetContext(this));
|
glContext = new ScopeContext(this, &wxGetApp().GetContext(this));
|
||||||
timer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeCanvas::~ScopeCanvas() {
|
ScopeCanvas::~ScopeCanvas() {
|
||||||
@ -39,6 +38,11 @@ void ScopeCanvas::setStereo(bool state) {
|
|||||||
stereo = state;
|
stereo = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScopeCanvas::setDeviceName(std::string device_name) {
|
||||||
|
deviceName = device_name;
|
||||||
|
deviceName.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
const wxSize ClientSize = GetClientSize();
|
const wxSize ClientSize = GetClientSize();
|
||||||
@ -47,17 +51,16 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
||||||
|
|
||||||
glContext->DrawBegin();
|
glContext->DrawBegin();
|
||||||
|
if (!deviceName.empty()) {
|
||||||
|
glContext->DrawDeviceName(deviceName);
|
||||||
|
}
|
||||||
glContext->Plot(waveform_points, stereo);
|
glContext->Plot(waveform_points, stereo);
|
||||||
glContext->DrawEnd();
|
glContext->DrawEnd();
|
||||||
|
|
||||||
|
|
||||||
SwapBuffers();
|
SwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeCanvas::OnIdle(wxIdleEvent &event) {
|
void ScopeCanvas::OnIdle(wxIdleEvent &event) {
|
||||||
// timer.update();
|
|
||||||
// frameTimer += timer.lastUpdateSeconds();
|
|
||||||
// if (frameTimer > 1.0/30.0) {
|
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
// frameTimer = 0;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "ScopeContext.h"
|
#include "ScopeContext.h"
|
||||||
|
|
||||||
#include "fftw3.h"
|
#include "fftw3.h"
|
||||||
#include "Timer.h"
|
|
||||||
|
|
||||||
class ScopeCanvas: public wxGLCanvas {
|
class ScopeCanvas: public wxGLCanvas {
|
||||||
public:
|
public:
|
||||||
@ -20,6 +18,7 @@ public:
|
|||||||
|
|
||||||
void setWaveformPoints(std::vector<float> &waveform_points_in);
|
void setWaveformPoints(std::vector<float> &waveform_points_in);
|
||||||
void setStereo(bool state);
|
void setStereo(bool state);
|
||||||
|
void setDeviceName(std::string device_name);
|
||||||
private:
|
private:
|
||||||
void OnPaint(wxPaintEvent& event);
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
|
||||||
@ -28,8 +27,7 @@ private:
|
|||||||
wxWindow *parent;
|
wxWindow *parent;
|
||||||
|
|
||||||
ScopeContext *glContext;
|
ScopeContext *glContext;
|
||||||
Timer timer;
|
std::string deviceName;
|
||||||
float frameTimer;
|
|
||||||
bool stereo;
|
bool stereo;
|
||||||
// event table
|
// event table
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
@ -4,20 +4,20 @@
|
|||||||
|
|
||||||
ScopeContext::ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext) :
|
ScopeContext::ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext) :
|
||||||
PrimaryGLContext(canvas, sharedContext) {
|
PrimaryGLContext(canvas, sharedContext) {
|
||||||
glDisable (GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable (GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glMatrixMode (GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeContext::DrawBegin() {
|
void ScopeContext::DrawBegin() {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glMatrixMode (GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
glDisable (GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeContext::Plot(std::vector<float> &points, bool stereo) {
|
void ScopeContext::Plot(std::vector<float> &points, bool stereo) {
|
||||||
@ -26,27 +26,27 @@ void ScopeContext::Plot(std::vector<float> &points, bool stereo) {
|
|||||||
if (stereo) {
|
if (stereo) {
|
||||||
glColor3f(0.7, 0.7, 0.7);
|
glColor3f(0.7, 0.7, 0.7);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex2f(-1.0,0.0);
|
glVertex2f(-1.0, 0.0);
|
||||||
glVertex2f(1.0,0.0);
|
glVertex2f(1.0, 0.0);
|
||||||
glEnd();
|
glEnd();
|
||||||
glColor3f(0.3, 0.3, 0.3);
|
glColor3f(0.3, 0.3, 0.3);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex2f(-1.0,0.5);
|
glVertex2f(-1.0, 0.5);
|
||||||
glVertex2f(1.0,0.5);
|
glVertex2f(1.0, 0.5);
|
||||||
glVertex2f(-1.0,-0.5);
|
glVertex2f(-1.0, -0.5);
|
||||||
glVertex2f(1.0,-0.5);
|
glVertex2f(1.0, -0.5);
|
||||||
glEnd();
|
glEnd();
|
||||||
} else {
|
} else {
|
||||||
glColor3f(0.3, 0.3, 0.3);
|
glColor3f(0.3, 0.3, 0.3);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex2f(-1.0,0.0);
|
glVertex2f(-1.0, 0.0);
|
||||||
glVertex2f(1.0,0.0);
|
glVertex2f(1.0, 0.0);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
glColor3f(0.9, 0.9, 0.9);
|
glColor3f(0.9, 0.9, 0.9);
|
||||||
if (points.size()) {
|
if (points.size()) {
|
||||||
glEnableClientState (GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glVertexPointer(2, GL_FLOAT, 0, &points[0]);
|
glVertexPointer(2, GL_FLOAT, 0, &points[0]);
|
||||||
if (stereo) {
|
if (stereo) {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
@ -74,6 +74,16 @@ void ScopeContext::Plot(std::vector<float> &points, bool stereo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScopeContext::DrawDeviceName(std::string deviceName) {
|
||||||
|
GLint vp[4];
|
||||||
|
glGetIntegerv( GL_VIEWPORT, vp);
|
||||||
|
float viewHeight = (float) vp[3];
|
||||||
|
float hPos = (float) (viewHeight - 20) / viewHeight;
|
||||||
|
|
||||||
|
glColor3f(0.65,0.65,0.65);
|
||||||
|
getFont(PrimaryGLContext::GLFONT_SIZE12).drawString(deviceName.c_str(), 1.0, hPos, 12, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
void ScopeContext::DrawEnd() {
|
void ScopeContext::DrawEnd() {
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
@ -83,7 +93,7 @@ void ScopeContext::DrawEnd() {
|
|||||||
void ScopeContext::DrawDivider() {
|
void ScopeContext::DrawDivider() {
|
||||||
glColor3f(1.0, 1.0, 1.0);
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex2f(0.0,-1.0);
|
glVertex2f(0.0, -1.0);
|
||||||
glVertex2f(0.0,1.0);
|
glVertex2f(0.0, 1.0);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ public:
|
|||||||
|
|
||||||
void DrawBegin();
|
void DrawBegin();
|
||||||
void Plot(std::vector<float> &points, bool stereo=false);
|
void Plot(std::vector<float> &points, bool stereo=false);
|
||||||
|
void DrawDeviceName(std::string deviceName);
|
||||||
void DrawDivider();
|
void DrawDivider();
|
||||||
void DrawEnd();
|
void DrawEnd();
|
||||||
|
|
||||||
|
@ -207,12 +207,7 @@ unsigned int SpectrumCanvas::GetBandwidth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SpectrumCanvas::OnIdle(wxIdleEvent &event) {
|
void SpectrumCanvas::OnIdle(wxIdleEvent &event) {
|
||||||
// timer.update();
|
|
||||||
// frameTimer += timer.lastUpdateSeconds();
|
|
||||||
// if (frameTimer > 1.0/30.0) {
|
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
// frameTimer = 0;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
|
void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "SpectrumContext.h"
|
#include "SpectrumContext.h"
|
||||||
|
|
||||||
#include "fftw3.h"
|
#include "fftw3.h"
|
||||||
#include "Timer.h"
|
|
||||||
#include "MouseTracker.h"
|
#include "MouseTracker.h"
|
||||||
|
|
||||||
class SpectrumCanvas: public wxGLCanvas {
|
class SpectrumCanvas: public wxGLCanvas {
|
||||||
|
@ -32,7 +32,7 @@ wxEND_EVENT_TABLE()
|
|||||||
|
|
||||||
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), spectrumCanvas(NULL), frameTimer(0), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState(
|
wxFULL_REPAINT_ON_RESIZE), parent(parent), spectrumCanvas(NULL), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState(
|
||||||
WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown(false), altDown(false), ctrlDown(false), fft_size(0), waterfall_lines(0), plan(
|
WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown(false), altDown(false), ctrlDown(false), fft_size(0), waterfall_lines(0), plan(
|
||||||
NULL), in(NULL), out(NULL), center_freq(0), bandwidth(0), isView(false), resampler(NULL), resample_ratio(0), last_bandwidth(0), last_input_bandwidth(
|
NULL), in(NULL), out(NULL), center_freq(0), bandwidth(0), isView(false), resampler(NULL), resample_ratio(0), last_bandwidth(0), last_input_bandwidth(
|
||||||
0) {
|
0) {
|
||||||
@ -85,7 +85,6 @@ void WaterfallCanvas::Setup(int fft_size_in, int waterfall_lines_in) {
|
|||||||
plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE);
|
plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE);
|
||||||
|
|
||||||
glContext->Setup(fft_size, waterfall_lines);
|
glContext->Setup(fft_size, waterfall_lines);
|
||||||
timer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WaterfallCanvas::GetFrequencyAt(float x) {
|
int WaterfallCanvas::GetFrequencyAt(float x) {
|
||||||
@ -447,12 +446,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
||||||
// timer.update();
|
|
||||||
// frameTimer += timer.lastUpdateSeconds();
|
|
||||||
// if (frameTimer > 1.0/30.0) {
|
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
// frameTimer = 0;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
|
void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "SpectrumCanvas.h"
|
#include "SpectrumCanvas.h"
|
||||||
|
|
||||||
#include "fftw3.h"
|
#include "fftw3.h"
|
||||||
#include "Timer.h"
|
|
||||||
|
|
||||||
class WaterfallCanvas: public wxGLCanvas {
|
class WaterfallCanvas: public wxGLCanvas {
|
||||||
public:
|
public:
|
||||||
@ -69,8 +68,6 @@ private:
|
|||||||
std::vector<float> fft_result_maa;
|
std::vector<float> fft_result_maa;
|
||||||
|
|
||||||
WaterfallContext *glContext;
|
WaterfallContext *glContext;
|
||||||
Timer timer;
|
|
||||||
float frameTimer;
|
|
||||||
MouseTracker mTracker;
|
MouseTracker mTracker;
|
||||||
|
|
||||||
int activeDemodulatorBandwidth;
|
int activeDemodulatorBandwidth;
|
||||||
|
Loading…
Reference in New Issue
Block a user