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/ModemUSB.cpp
|
||||
src/audio/AudioThread.cpp
|
||||
src/audio/AudioSinkThread.cpp
|
||||
src/util/Gradient.cpp
|
||||
src/util/Timer.cpp
|
||||
src/util/MouseTracker.cpp
|
||||
@ -451,6 +452,7 @@ SET (cubicsdr_headers
|
||||
src/modules/modem/analog/ModemLSB.h
|
||||
src/modules/modem/analog/ModemUSB.h
|
||||
src/audio/AudioThread.h
|
||||
src/audio/AudioSinkThread.h
|
||||
src/util/Gradient.h
|
||||
src/util/Timer.h
|
||||
src/util/ThreadBlockingQueue.h
|
||||
|
@ -505,6 +505,14 @@ bool AppConfig::getBookmarksVisible() {
|
||||
return bookmarksVisible.load();
|
||||
}
|
||||
|
||||
void AppConfig::setRecordingPath(std::string recPath) {
|
||||
recordingPath = recPath;
|
||||
}
|
||||
|
||||
std::string AppConfig::getRecordingPath() {
|
||||
return recordingPath;
|
||||
}
|
||||
|
||||
|
||||
void AppConfig::setConfigName(std::string configName) {
|
||||
this->configName = configName;
|
||||
@ -559,6 +567,9 @@ bool AppConfig::save() {
|
||||
*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");
|
||||
|
||||
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")) {
|
||||
DataNode *devices_node = cfg.rootNode()->getNext("devices");
|
||||
|
||||
|
@ -138,6 +138,8 @@ public:
|
||||
void setBookmarksVisible(bool state);
|
||||
bool getBookmarksVisible();
|
||||
|
||||
void setRecordingPath(std::string recPath);
|
||||
std::string getRecordingPath();
|
||||
|
||||
#if USE_HAMLIB
|
||||
int getRigModel();
|
||||
@ -185,6 +187,7 @@ private:
|
||||
std::atomic_int dbOffset;
|
||||
std::vector<SDRManualDef> manualDevices;
|
||||
std::atomic_bool bookmarksVisible;
|
||||
std::string recordingPath;
|
||||
#if USE_HAMLIB
|
||||
std::atomic_int rigModel, rigRate;
|
||||
std::string rigPort;
|
||||
|
@ -412,6 +412,8 @@ AppFrame::AppFrame() :
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_SDR_START_STOP, "Stop / Start Device");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_RECORDING_PATH, "Set Recording Path");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_OPEN, "&Open Session");
|
||||
menu->Append(wxID_SAVE, "&Save Session");
|
||||
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) {
|
||||
lowPerfMode = lowPerfMenuItem->IsChecked();
|
||||
wxGetApp().getConfig()->setLowPerfMode(lowPerfMode);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define wxID_LOW_PERF 2011
|
||||
#define wxID_SET_DB_OFFSET 2012
|
||||
#define wxID_ABOUT_CUBICSDR 2013
|
||||
#define wxID_RECORDING_PATH 2014
|
||||
|
||||
#define wxID_MAIN_SPLITTER 2050
|
||||
#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;
|
||||
|
||||
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