#include <QObject>
#include <mutex>
+#include <memory>
#include "../common.h"
-#include "../fifo_templates.h"
+#include "./sound_buffer_qt.h"
QT_BEGIN_NAMESPACE
class OSD_BASE;
class USING_FLAGS;
class CSP_Logger;
-class DLL_PREFIX SOUND_MODULE_BASE : public QObject
+
+class DLL_PREFIX SOUND_OUTPUT_MODULE_BASE : public QObject
{
Q_OBJECT
protected:
- OSD_BASE *m_OSD;
- USING_FLAGS *m_using_flags;
- CSP_Logger *m_logger;
- void *m_extconfig;
- FIFO_BASE::LOCKED_RINGBUFFER<int16_t> *m_queue;
- std::recursive_mutex m_locker;
- std::recursive_mutex m_locker_outqueue;
-public:
- SOUND_MODULE_BASE(OSD_BASE *parent, USING_FLAGS *pflags, CSP_Logger *logger, int buffer_size = 4096, void *configvalues = nullptr)
- : m_OSD(parent), m_using_flags(pflags), m_logger(logger),
- m_extconfig(configvalues),
- QObject(qobject_cast<QObject*>parent)
- {
- m_queue = new FIFO_BASE::LOCKED_RINGBUFFER<int16_t>(buffer_size);
- }
- ~SOUND_MODULE_BASE()
+ OSD* m_OSD;
+ std::shared_ptr<SOUND_BUFFER_QT> m_fileio;
+ std::shared_ptr<USING_FLAGS> m_using_flags;
+
+ std::atomic<bool> m_config_ok;
+
+ int64_t m_chunk_bytes;
+ int64_t m_buffer_bytes;
+
+ int m_rate;
+ int m_latency_ms;
+ int m_channels;
+ size_t m_wordsize;
+ std::atomic<void*> m_extconfig_ptr;
+ std::atomic<int> m_extconfig_bytes;
+ std::atomic<int> m_loglevel;
+ std::atomic<int> m_logdomain;
+
+ virtual void update_driver_fileio()
{
- std::lock_guard<std::recursive_mutex> locker(m_locker);
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- delete m_queue;
- }
+ release_driver_fileio();
+ // Update driver side of fileio by m_fileio;
+ //connect(m_fileio.get(), SIGNAL(bytesWritten(qint64)), real_driver, SLOT, QObject::DirectConnection);
+ //connect(m_fileio.get(), SIGNAL(aboutToClose()), real_driver, SLOT, QObject::DirectConnection);
+ // Optional:
+ // connect(m_fileio.get(), SIGNAL(readyRead()), real_driver, SLOT, QObject::DirectConnection);
}
- virtual int get_sound_rate(bool is_input = false, int dev_channel = 0)
+
+ virtual void release_driver_fileio()
{
- return 44100;
+ // Maybe disconnect some signals via m_fileio.
}
- virtual int64_t enqueueOutputSink(int16_t* p, int64_t size)
+ template <class... Args>
+ bool debug_log(Args... args)
{
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- bool flag;
- int64_t wsize = m_queue->write(p, size, flag);
- if((wsize > size) || (wsize <= 0) || !(flag)) {
- return 0;
- }
- return wsize;
- }
- return 0;
+ _TCHAR buf[1024];
+ memset(buf, 0x00, sizeof(buf));
+ my_sprintf_s(buf, sizeof(buf) - 1, args);
+
+ return do_send_log(m_loglevel.load(), m_logdomain.load(),
+ QString::fromUtf8(buf, sizeof(buf)));
}
- virtual int64_t dequeueOutputSink(int16_t* p, int64_t size)
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- bool flag;
- int64_t rsize = m_queue->read(p, size, flag);
- if((rsize > size) || (rsize <= 0) || !(flag)) {
- return 0;
- }
- return rsize;
- }
- return 0;
+public:
+ SOUND_OUTPUT_MODULE_BASE(OSD_BASE *parent,
+ SOUND_BUFFER_QT* deviceIO = nullptr,
+ int base_rate = 48000,
+ int base_latency_ms = 100,
+ int base_channels = 2,
+ void *extra_config_values = nullptr);
+ ~SOUND_OUTPUT_MODULE_BASE();
+
+ std::recursive_timed_mutex m_locker;
+
+ virtual void initialize_driver()
+ {
+ // AT LEAST:
+ // connect(this, SIGNAL(sig_start_audio()), ..., QObject::QueuedConnection);
+ // connect(this, SIGNAL(sig_pause_audio()), ..., QObject::QueuedConnection);
+ // connect(this, SIGNAL(sig_resume_audio()), ..., QObject::QueuedConnection);
+ // connect(this, SIGNAL(sig_close_audio()), ..., QObject::QueuedConnection);
+ // connect(this, SIGNAL(sig_discard_audio()), ..., QObject::QueuedConnection);
+ // connect(this, SIGNAL(sig_released(bool)), ..., QObject::QueuedConnection);
+ // connect(this, SIGNAL(sig_req_open_sound(int, int, QString)), ..., QObject::QueuedConnection);
+
+ // For Logging
+ // connect(real_driver, SIGNAL(sig_log(QString)), this, SLOT(do_send_log(QString)), QObject::QueuedConnection);
+ // connect(real_driver, SIGNAL(sig_log(int, int, QString)), this, SLOT(do_send_log(int, int, QString)), QObject::QueuedConnection);
}
- virtual int64_t enqueueInputSource(int device_ch, int16_t* p, int64_t size)
+ virtual void release_driver()
{
- return 0;
}
- virtual int64_t dequeueInputSource(int device_ch, int16_t* p, int64_t size)
+
+ int64_t update_sound(void* datasrc, int samples);
+
+ std::shared_ptr<QIODevice> set_io_device(QIODevice *p);
+ std::shared_ptr<QIODevice> set_io_device(std::shared_ptr<QIODevice> ps);
+ std::shared_ptr<QIODevice> get_io_device()
{
- return 0;
+ return m_fileio;
}
+ bool is_io_device_exists();
- virtual int64_t outputSinkQueueSize()
+ virtual uint64_t wrote_data_to()
{
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- return m_queue->size();
- }
return 0;
}
- virtual int64_t outputSinkDataCount()
+ virtual int64_t driver_elapsed_usec()
{
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- return m_queue->count();
- }
return 0;
}
- virtual bool outputSinkQueueAvailable()
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- return m_queue->available();
- }
- return false;
- }
- virtual bool outputSinkQueueReadReady()
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- return m_queue->read_ready();
- }
- return false;
- }
- virtual bool outputSinkQueueWriteReady()
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- if(m_queue != nullptr) {
- return m_queue->write_ready();
- }
- return false;
- }
-
-
- virtual int64_t inputSourceQueueSize(int input_ch = 0)
+ virtual int64_t driver_processed_usec()
{
return 0;
}
- virtual int64_t inputSourceDataCount(int input_ch = 0)
+ bool config_ok()
{
- return 0;
+ return m_config_ok.load();
}
- virtual bool inputSourceQueueAvailable(int input_ch = 0)
- {
- return false;
- }
- virtual bool inputSourceQueueReadReady(int input_ch = 0)
+
+ int64_t get_buffer_bytes();
+ int64_t get_chunk_bytes();
+ int get_latency_ms();
+ int get_channels();
+ int get_sample_rate();
+ size_t get_word_size();
+ void get_buffer_parameters(int& channels, int& rate, int& latency_ms,
+ size_t& word_size, int& chunk_bytes, int& buffer_bytes);
+ virtual int64_t get_bytes_available();
+ virtual int64_t get_bytes_left();
+
+ virtual SOUND_OUTPUT_MODULE_BASE* get_real_driver()
{
- return false;
+ return dynamic_cast<SOUND_OUTPUT_MODULE_BASE>this;
}
- virtual bool inputSourceQueueWriteReady(int input_ch = 0)
+
+ virtual std::list<std::string> get_sound_devices_list()
{
- return false;
+ static std::list<std::string> dummy_list;
+ return dummy_list;
}
- virtual bool initalizeSoundOutputDevice(int channels, int sample_rate, int& samples_per_chunk, int& chunks, std::string device_name)
+ virtual const _TCHAR* get_sound_device_name(int num)
{
- return true;
+ return (const _TCHAR*)nullptr;
}
-
- virtual bool initalizeSoundOutputDevice(int channels, int sample_rate, int& samples_per_chunk, int& chunks, int device_num)
+ virtual const _TCHAR* get_current_device_name()
{
- return true;
+ return (const _TCHAR*)(_T("Empty"));
}
- virtual bool detachSoundOutputDevice()
- {
- return true;
- }
- virtual bool isSoundOutputDeviceReady()
+
+ virtual void set_logger(const std::shared_ptr<CSP_Logger> logger);
+ virtual void set_system_flags(const std::shared_ptr<USING_FLAGS> p);
+ void* get_extra_config_ptr()
{
- return false;
+ return m_extconfig_ptr.load();
}
-
- virtual bool initalizeSoundInputDevice(int channels, int sample_rate, int& samples_per_chunk, int& chunks, std::string device_name)
+ int get_extra_config_bytes()
{
- return true;
+ return m_extconfig_bytes.load();
}
+ virtual bool set_extra_config(void* p, int bytes);
+ virtual bool modify_extra_config(void* p, int& bytes);
+public slot:
+ virtual void update_config() {}
+ virtual void update_extra_config() {}
+
+ bool start();
+ bool pause();
+ bool resume();
+ bool stop();
+ bool discard();
- virtual bool initalizeSoundInputDevice(int input_channel, int channels, int sample_rate, int& samples_per_chunk, int& chunks, int device_num)
+ virtual void reset_to_defalut() {}
+ virtual void set_volume(double level) {}
+ virtual bool is_running_sound()
{
return true;
}
- virtual void detachSoundInputDevice(int input_channel = 0)
+ bool update_rate(int rate)
{
- return true;
+ return reconfig_sound(rate, m_channels);
}
- virtual bool isSoundInputDeviceReady(int input_channel = 0)
+ bool update_channels(int channels)
{
- return false;
+ return reconfig_sound(m_rate, channels);
}
+ bool update_latency(int latency_ms, bool fortce = false);
+ bool reconfig_sound(int rate, int channels);
+ void request_to_release();
- virtual void soundOutHandler(int64_t& req_size, void* userdata = nullptr)
+ virtual bool do_send_log(int level, int domain, QString _str);
+ virtual bool do_send_log(int level, int domain, const _TCHAR* _str, int maxlen);
+ virtual bool do_send_log(const _TCHAR* str, int maxlen)
{
+ do_send_log(m_loglevel.load(), m_logdomain.load(), _str, maxlen);
}
- virtual void soundInHandler(int64_t &req_size, void* userdata = nullptr)
+ virtual bool do_send_log(const QString _str)
{
+ do_send_log(m_loglevel.load(), m_logdomain.load(), _str);
}
- // Kick sound out handler
- virtual bool soundOutReq()
- {
- return true;
- }
- // Kick sound in handler
- virtual bool soundInReq(int input_ch)
- {
- return true;
- }
-public slot:
- virtual void initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples)
+
+ virtual void do_set_device_by_name(QString name) {};
+ virtual void do_set_device_by_name(const _TCHAR *name)
{
- std::lock_guard<std::recursive_mutex> locker(m_locker_outqueue);
- // more lock via m_locker etc, if needs.
- if(presented_rate != nullptr) {
- *presenyted_rate = rate;
- }
- if(presented_samples != nullptr) {
- *presenyted_samples = samples;
+ if(name != nullptr) {
+ do_set_device_by_name(QString::fromUtf8(name));
}
}
- virtual void update_sound(int* extra_frames) {}
- virtual void mute_sound() {}
- virtual void stop_sound() {}
-
- // *PURE* SLOTS
- virtual void do_start_recording_sound() {}
- virtual void do_stop_recording_sound() {}
- virtual void do_restart_recording_sound() {}
- virtual void do_request_capture_sound(int ch) {}
- virtual void do_resize_output_buffer(int count, int channels) {}
- virtual void do_resize_capture_buffer(int ch, int count, int channels) {}
- virtual void do_receive_external_sound(int count, int channels, int16_t* data) {}
-
- virtual void set_logger(CSP_Logger* logger)
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker);
- m_logger = logger;
- }
- virtual void set_osd(OSD_BASE* p)
+ virtual void do_set_device_by_name(const _TCHAR *name, int maxlen)
{
- std::lock_guard<std::recursive_mutex> locker(m_locker);
- m_OSD = p;
+ if((name != nullptr) && (maxlen > 0)) {
+ do_set_device_by_name(QString::fromUtf8(name, maxlen));
+ }
}
+ virtual void do_set_device_by_number(int) {};
+
+ // This set device by device-name having QAction (as QObject).
+ virtual void do_set_device_by_name(void);
+ virtual void do_set_device_by_number(void);
- virtual void set_system_flags(USING_FLAGS* p)
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker);
- m_using_flags = p;
- }
- virtual void update_extra_config(void* p)
- {
- std::lock_guard<std::recursive_mutex> locker(m_locker);
- m_extconfig = p;
- // more lock via m_locker_outqueue etc, if needs.
- }
+ // From real driver: notify to update sound devices list.
+ virtual void do_update_device_list() {}
+ virtual void set_osd(OSD_BASE* p);
+
signals:
- void sig_send_log(QString);
- void sig_send_log_with_class(int, int, QString);
- void sig_req_input(int64_t);
- void sig_complete_output(int64_t);
- void sig_send_captured_sound_data(int, int64_t, int, int16_t[]);
- void sig_send_output_sound_data(int64_t, int, int16_t[]);
+ // loglevel, logdomain, message
+ void sig_send_log(int, int, QString);
+ // rate, channels, path
+ void sig_req_open_sound(int, int, QString);
+ //
+ void sig_start_audio();
+ void sig_pause_audio();
+ void sig_resume_audio();
+ void sig_close_audio();
+ void sig_discard_audio();
+ //
+ // notify completed to release sound driver.
+ void sig_released(bool);
+ // To UI: notify reset sound device list.
+ void sig_reset_sound_device_list();
+ // To UI: notify update sound device list #arg1 to #arg2.
+ void sig_set_sound_device(int, QString);
+ // To UI: notify adding sound device list #arg1.
+ void sig_add_sound_device(QString);
};
QT_END_NAMESPACE