mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 21:58:37 -05:00
Initial AudioSink thread base and recoring preference
This commit is contained in:
parent
927d727a16
commit
a398bc57f1
@ -347,6 +347,7 @@ SET (cubicsdr_sources
|
|||||||
src/modules/modem/analog/ModemLSB.cpp
|
src/modules/modem/analog/ModemLSB.cpp
|
||||||
src/modules/modem/analog/ModemUSB.cpp
|
src/modules/modem/analog/ModemUSB.cpp
|
||||||
src/audio/AudioThread.cpp
|
src/audio/AudioThread.cpp
|
||||||
|
src/audio/AudioSinkThread.cpp
|
||||||
src/util/Gradient.cpp
|
src/util/Gradient.cpp
|
||||||
src/util/Timer.cpp
|
src/util/Timer.cpp
|
||||||
src/util/MouseTracker.cpp
|
src/util/MouseTracker.cpp
|
||||||
@ -451,6 +452,7 @@ SET (cubicsdr_headers
|
|||||||
src/modules/modem/analog/ModemLSB.h
|
src/modules/modem/analog/ModemLSB.h
|
||||||
src/modules/modem/analog/ModemUSB.h
|
src/modules/modem/analog/ModemUSB.h
|
||||||
src/audio/AudioThread.h
|
src/audio/AudioThread.h
|
||||||
|
src/audio/AudioSinkThread.h
|
||||||
src/util/Gradient.h
|
src/util/Gradient.h
|
||||||
src/util/Timer.h
|
src/util/Timer.h
|
||||||
src/util/ThreadBlockingQueue.h
|
src/util/ThreadBlockingQueue.h
|
||||||
|
@ -505,6 +505,14 @@ bool AppConfig::getBookmarksVisible() {
|
|||||||
return bookmarksVisible.load();
|
return bookmarksVisible.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppConfig::setRecordingPath(std::string recPath) {
|
||||||
|
recordingPath = recPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AppConfig::getRecordingPath() {
|
||||||
|
return recordingPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AppConfig::setConfigName(std::string configName) {
|
void AppConfig::setConfigName(std::string configName) {
|
||||||
this->configName = configName;
|
this->configName = configName;
|
||||||
@ -559,6 +567,9 @@ bool AppConfig::save() {
|
|||||||
*window_node->newChild("bookmark_visible") = bookmarksVisible.load();
|
*window_node->newChild("bookmark_visible") = bookmarksVisible.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataNode *rec_node = cfg.rootNode()->newChild("recording");
|
||||||
|
*rec_node->newChild("path") = recordingPath;
|
||||||
|
|
||||||
DataNode *devices_node = cfg.rootNode()->newChild("devices");
|
DataNode *devices_node = cfg.rootNode()->newChild("devices");
|
||||||
|
|
||||||
std::map<std::string, DeviceConfig *>::iterator device_config_i;
|
std::map<std::string, DeviceConfig *>::iterator device_config_i;
|
||||||
@ -741,6 +752,15 @@ bool AppConfig::load() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cfg.rootNode()->hasAnother("recording")) {
|
||||||
|
DataNode *rec_node = cfg.rootNode()->getNext("recording");
|
||||||
|
|
||||||
|
if (rec_node->hasAnother("path")) {
|
||||||
|
DataNode *rec_path = cfg.rootNode()->getNext("path");
|
||||||
|
recordingPath = rec_path->element()->toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg.rootNode()->hasAnother("devices")) {
|
if (cfg.rootNode()->hasAnother("devices")) {
|
||||||
DataNode *devices_node = cfg.rootNode()->getNext("devices");
|
DataNode *devices_node = cfg.rootNode()->getNext("devices");
|
||||||
|
|
||||||
|
@ -138,6 +138,8 @@ public:
|
|||||||
void setBookmarksVisible(bool state);
|
void setBookmarksVisible(bool state);
|
||||||
bool getBookmarksVisible();
|
bool getBookmarksVisible();
|
||||||
|
|
||||||
|
void setRecordingPath(std::string recPath);
|
||||||
|
std::string getRecordingPath();
|
||||||
|
|
||||||
#if USE_HAMLIB
|
#if USE_HAMLIB
|
||||||
int getRigModel();
|
int getRigModel();
|
||||||
@ -185,6 +187,7 @@ private:
|
|||||||
std::atomic_int dbOffset;
|
std::atomic_int dbOffset;
|
||||||
std::vector<SDRManualDef> manualDevices;
|
std::vector<SDRManualDef> manualDevices;
|
||||||
std::atomic_bool bookmarksVisible;
|
std::atomic_bool bookmarksVisible;
|
||||||
|
std::string recordingPath;
|
||||||
#if USE_HAMLIB
|
#if USE_HAMLIB
|
||||||
std::atomic_int rigModel, rigRate;
|
std::atomic_int rigModel, rigRate;
|
||||||
std::string rigPort;
|
std::string rigPort;
|
||||||
|
@ -412,6 +412,8 @@ AppFrame::AppFrame() :
|
|||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
menu->Append(wxID_SDR_START_STOP, "Stop / Start Device");
|
menu->Append(wxID_SDR_START_STOP, "Stop / Start Device");
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
|
menu->Append(wxID_RECORDING_PATH, "Set Recording Path");
|
||||||
|
menu->AppendSeparator();
|
||||||
menu->Append(wxID_OPEN, "&Open Session");
|
menu->Append(wxID_OPEN, "&Open Session");
|
||||||
menu->Append(wxID_SAVE, "&Save Session");
|
menu->Append(wxID_SAVE, "&Save Session");
|
||||||
menu->Append(wxID_SAVEAS, "Save Session &As..");
|
menu->Append(wxID_SAVEAS, "Save Session &As..");
|
||||||
@ -1564,6 +1566,16 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGetApp().getConfig()->setRecordingPath(recPathDialog.GetPath().ToStdString());
|
||||||
|
}
|
||||||
else if (event.GetId() == wxID_LOW_PERF) {
|
else if (event.GetId() == wxID_LOW_PERF) {
|
||||||
lowPerfMode = lowPerfMenuItem->IsChecked();
|
lowPerfMode = lowPerfMenuItem->IsChecked();
|
||||||
wxGetApp().getConfig()->setLowPerfMode(lowPerfMode);
|
wxGetApp().getConfig()->setLowPerfMode(lowPerfMode);
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#define wxID_LOW_PERF 2011
|
#define wxID_LOW_PERF 2011
|
||||||
#define wxID_SET_DB_OFFSET 2012
|
#define wxID_SET_DB_OFFSET 2012
|
||||||
#define wxID_ABOUT_CUBICSDR 2013
|
#define wxID_ABOUT_CUBICSDR 2013
|
||||||
|
#define wxID_RECORDING_PATH 2014
|
||||||
|
|
||||||
#define wxID_MAIN_SPLITTER 2050
|
#define wxID_MAIN_SPLITTER 2050
|
||||||
#define wxID_VIS_SPLITTER 2051
|
#define wxID_VIS_SPLITTER 2051
|
||||||
|
83
src/audio/AudioSinkThread.cpp
Normal file
83
src/audio/AudioSinkThread.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// 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>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Thread termination, prevent fancy things to happen, lock the whole thing:
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
// Drain any remaining inputs, with a non-blocking pop
|
||||||
|
inputQueuePtr->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSinkThread::terminate()
|
||||||
|
{
|
||||||
|
IOThread::terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSinkThread::sink(AudioThreadInputPtr * input)
|
||||||
|
{
|
||||||
|
// do something with the audio data
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSinkThread::inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps)
|
||||||
|
{
|
||||||
|
// handle changes in stream properties
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSinkThread::setSinkName(std::string sinkName_in)
|
||||||
|
{
|
||||||
|
sinkName = sinkName_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AudioSinkThread::getSinkName()
|
||||||
|
{
|
||||||
|
return sinkName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
28
src/audio/AudioSinkThread.h
Normal file
28
src/audio/AudioSinkThread.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// 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);
|
||||||
|
virtual void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps);
|
||||||
|
|
||||||
|
virtual void setSinkName(std::string sinkName_in);
|
||||||
|
virtual std::string getSinkName();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::recursive_mutex m_mutex;
|
||||||
|
AudioThreadInputQueuePtr inputQueuePtr;
|
||||||
|
std::string sinkName;
|
||||||
|
};
|
@ -24,7 +24,7 @@ public:
|
|||||||
std::vector<float> data;
|
std::vector<float> data;
|
||||||
|
|
||||||
AudioThreadInput() :
|
AudioThreadInput() :
|
||||||
frequency(0), sampleRate(0), channels(0), peak(0) {
|
frequency(0), sampleRate(0), inputRate(0), channels(0), peak(0), type(0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user