+
+ bool _f = is_running_sound();
+ if(m_fileio.get() != nullptr) {
+ _f &= m_fileio->isOpen();
+ }
+ stop();
+ if(p == nullptr) {
+ m_fileio.reset(new SOUND_BUFFER_QT(m_chunk_bytes * 4, this));
+ } else {
+ m_fileio.reset(p);
+ }
+ update_driver_fileio();
+ if(_f) {
+ start();
+ }
+ return m_fileio;
+}
+
+std::shared_ptr<QIODevice> SOUND_OUTPUT_MODULE_BASE::set_io_device(std::shared_ptr<QIODevice> ps)
+{
+ bool _f = is_running_sound();
+ if(m_fileio.get() != nullptr) {
+ _f &= m_fileio->isOpen();
+ }
+ stop();
+ m_fileio = ps;
+ update_driver_fileio();
+ if(_f) {
+ start();
+ }
+ return m_fileio;
+}
+
+
+bool SOUND_OUTPUT_MODULE_BASE::update_latency(int latency_ms, bool force)
+{
+ std::lock_guard<std::recursive_timed_mutex> locker(m_locker);
+ if(latency_ms <= 0) {
+ return false;
+ }
+ if(!(force) && (m_latency_ms == latency_ms)) return true;
+
+ m_latency_ms = latency_ms;
+ m_chunk_bytes = ((qint64)(m_channels * ((int)m_wordsize) * latency_ms) * (quint64)m_rate) / 1000;
+ m_buffer_bytes = m_chunk_bytes * 4;
+
+ stop();
+
+ std::shared_ptr<SOUND_BUFFER_QT> q = m_fileio;
+ if(q.get() != nullptr) {
+ q->reset();
+ if(!(q->resize(m_buffer_bytes))) {
+ q->reset();
+ m_buffer_bytes = (int64_t)(q->size());
+ }
+ } else {
+ m_fileio.reset(new SOUND_BUFFER_QT(m_buffer_bytes, this));
+ }
+ update_driver_fileio();
+ return (start() && (m_fileio.get() != nullptr));
+}
+
+
+bool SOUND_OUTPUT_MODULE_BASE::reconfig_sound(int rate, int channels)
+{
+ // ToDo
+ std::lock_guard<std::recursive_timed_mutex> locker(m_locker);
+ if((rate != m_rate) || (channels != m_channels)) {
+ if(real_reconfig_sound(rate, channels)) {
+ m_rate = rate;
+ m_channels = channels;
+ m_config_ok = update_latency(m_latency_ms, true);
+ return m_config_ok.load();
+ }
+ }
+ return false;
+}
+
+int64_t SOUND_OUTPUT_MODULE_BASE::update_sound(void* datasrc, int samples)
+{
+ std::shared_ptr<SOUND_BUFFER_QT>q = m_fileio;
+
+ if(q.get() == nullptr) return -1;
+
+ if(samples > 0) {
+ qint64 _size = (qint64)(samples * m_channels) * (qint64)m_wordsize;
+ return (int64_t)q->write((const char *)datasrc, _size);
+ } else if(samples < 0) {
+ return (int64_t)q->write((const char *)datasrc, m_chunk_bytes);
+ }
+ return -1;
+}
+
+bool SOUND_OUTPUT_MODULE_BASE::start()
+{
+ std::shared_ptr<SOUND_BUFFER_QT>q = m_fileio;
+ if(is_running_sound()) { // ToDo: STOP
+ stop();
+ }
+ bool _stat = false;
+
+ if(q.get() != nullptr) {
+ _stat = q->open(QIODeviceBase::Write | QIODeviceBase::Unbuffered);
+ update_driver_fileio();
+ }
+ if(_stat) {
+ QMetaMethod _sig = QMetaMethod::fromSignal(SIGNAL(sig_start_audio()));
+ if(isSignalConnected(_sig)) {
+ emit sig_start_audio();
+ }
+ }
+ return _stat;
+}
+
+bool SOUND_OUTPUT_MODULE_BASE::pause()
+{
+ QMetaMethod _sig = QMetaMethod::fromSignal(SIGNAL(sig_pause_audio()));
+ if(isSignalConnected(_sig)) {
+ emit sig_pause_audio();
+ return true;
+ }
+ return false;
+}
+
+bool SOUND_OUTPUT_MODULE_BASE::resume()
+{
+ QMetaMethod _sig = QMetaMethod::fromSignal(SIGNAL(sig_resume_audio()));
+ if(isSignalConnected(_sig)) {
+ emit sig_resume_audio();
+ return true;
+ }
+ return false;
+}
+
+bool SOUND_OUTPUT_MODULE_BASE::stop()
+{
+ bool _stat = false;
+ QMetaMethod _sig = QMetaMethod::fromSignal(SIGNAL(sig_close_audio()));
+ if(isSignalConnected(_sig)) {
+ emit sig_close_audio();
+ _stat = true;
+ }
+ std::shared_ptr<SOUND_BUFFER_QT>q = m_fileio;
+
+ if(q.get() != nullptr) {
+ if(q->isOpen()) {
+ q->close();
+ }
+ return _stat;
+ }
+ return false;
+}
+
+bool SOUND_OUTPUT_MODULE_BASE::discard()
+{
+// std::lock_guard<std::recursive_timed_mutex> locker(m_locker);
+// std::shared_ptr<SOUND_BUFFER_QT> q = m_fileio;
+// if(q.get() != nullptr) {
+ QMetaMethod _sig = QMetaMethod::fromSignal(SIGNAL(sig_discard_audio()));
+ if(isSignalConnected(_sig)) {
+ emit sig_discard_audio();
+ return true;
+ }
+// }
+ return false;