// Copyright (c) Charles J. Cliffe // SPDX-License-Identifier: GPL-2.0+ #pragma once #include #include #include #include #include #include #include "ThreadBlockingQueue.h" #include "RtAudio.h" #include "DemodDefs.h" class AudioThreadInput { public: long long frequency{}; int inputRate{}; int sampleRate{}; int channels{}; float peak{}; int type{}; bool is_squelch_active{}; std::vector data; AudioThreadInput() : frequency(0), inputRate(0), sampleRate(0), channels(0), peak(0), type(0), is_squelch_active(false) { } explicit 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() = default; }; typedef std::shared_ptr AudioThreadInputPtr; typedef ThreadBlockingQueue DemodulatorThreadOutputQueue; typedef std::shared_ptr DemodulatorThreadOutputQueuePtr; class AudioThreadCommand { public: enum class Type { AUDIO_THREAD_CMD_NULL, AUDIO_THREAD_CMD_SET_DEVICE, AUDIO_THREAD_CMD_SET_SAMPLE_RATE }; AudioThreadCommand() : cmdType(AudioThreadCommand::Type::AUDIO_THREAD_CMD_NULL), int_value(0) { } AudioThreadCommand::Type cmdType; int int_value; }; typedef ThreadBlockingQueue AudioThreadInputQueue; typedef ThreadBlockingQueue AudioThreadCommandQueue; typedef std::shared_ptr AudioThreadInputQueuePtr; typedef std::shared_ptr AudioThreadCommandQueuePtr; class AudioThread : public IOThread { public: AudioThread(); ~AudioThread() override; static void enumerateDevices(std::vector &devs); void setInitOutputDevice(int deviceId, int sampleRate_in = -1); int getOutputDevice(); int getSampleRate(); void run() override; void terminate() override; bool isActive(); void setActive(bool state); void setGain(float gain_in); static std::map deviceSampleRate; AudioThreadCommandQueue *getCommandQueue(); //give access to the this AudioThread lock std::recursive_mutex& getMutex(); static void deviceCleanup(); static void setDeviceSampleRate(int deviceId, int sampleRate); // void attachControllerThread(std::thread* controllerThread); //fields below, only to be used by other AudioThreads ! size_t underflowCount; //protected by m_mutex std::vector boundThreads; AudioThreadInputQueuePtr inputQueue; AudioThreadInputPtr currentInput; size_t audioQueuePtr; float gain; private: std::atomic_bool active; std::atomic_int outputDevice; RtAudio dac; unsigned int nBufferFrames; RtAudio::StreamOptions opts; RtAudio::StreamParameters parameters; AudioThreadCommandQueue cmdQueue; int sampleRate; //if != nullptr, it mean AudioThread is a controller thread. std::thread* controllerThread; //The own m_mutex protecting this AudioThread, in particular boundThreads std::recursive_mutex m_mutex; void setupDevice(int deviceId); void setSampleRate(int sampleRate_in); void bindThread(AudioThread *other); void removeThread(AudioThread *other); static std::map deviceController; //The mutex protecting static deviceController, deviceThread and deviceSampleRate access. static std::recursive_mutex m_device_mutex; };