OSDN Git Service

[OSD][SOUND][Qt] QT_MULTIMEDIA: Reduce jitter and delay.
[csp-qt/common_source_project-fm7.git] / source / src / qt / sound-drivers / qt_multimedia / osd_sound_mod_qtmultimedia.cpp
1 #include "../../../config.h"
2 #include "../../gui/menu_flags.h"
3 #include "../../osd_base.h"
4
5 #include "../sound_buffer_qt.h"
6
7 #include "./osd_sound_mod_qtmultimedia.h"
8
9 #include <algorithm>
10
11 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
12 #include <QMediaDevices>
13 #endif
14
15 namespace SOUND_MODULE {
16 /* SOUND_MODULE */
17         
18         namespace OUTPUT {
19         /* SOUND_MODULE */
20         M_QT_MULTIMEDIA::M_QT_MULTIMEDIA(
21                 OSD_BASE *parent,
22                 SOUND_BUFFER_QT* deviceIO,
23                 int base_rate,
24                 int base_latency_ms,
25                 int base_channels,
26                 void *extra_config_values,
27                 int extra_config_bytes )
28                 :
29         M_BASE(
30                 parent,
31                 deviceIO,
32                 base_rate,
33                 base_latency_ms,
34                 base_channels,
35                 extra_config_values,
36                 extra_config_bytes )
37 {
38         m_classname = "SOUND_MODULE::OUTPUT::M_QT_MULTIMEDIA";
39         
40         connect(this, SIGNAL(sig_start_audio()),  this, SLOT(do_sound_start()), Qt::QueuedConnection);
41         connect(this, SIGNAL(sig_stop_audio()),  this, SLOT(do_sound_stop()), Qt::QueuedConnection);
42         connect(this, SIGNAL(sig_pause_audio()),  this, SLOT(do_sound_suspend()), Qt::QueuedConnection);
43         connect(this, SIGNAL(sig_resume_audio()),  this, SLOT(do_sound_resume()), Qt::QueuedConnection);
44         connect(this, SIGNAL(sig_discard_audio()),  this, SLOT(do_discard_sound()), Qt::QueuedConnection);
45         connect(this, SIGNAL(sig_set_volume(double)),  this, SLOT(do_sound_volume(double)), Qt::QueuedConnection);
46
47         connect(parent, SIGNAL(sig_set_sound_volume(int)),  this, SLOT(set_volume(int)), Qt::QueuedConnection);
48         connect(parent, SIGNAL(sig_set_sound_volume(double)),  this, SLOT(set_volume(double)), Qt::QueuedConnection);
49         connect(parent, SIGNAL(sig_set_sound_device(QString)),  this, SLOT(do_set_device_by_name(QString)), Qt::QueuedConnection);
50         
51         initialize_sound_devices_list();
52 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
53         m_audioOutputDevice = QMediaDevices::defaultAudioOutput();
54 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
55         m_audioOutputDevice = QAudioDeviceInfo::defaultOutputDevice();
56 #endif          
57         m_device_is_default = true;
58         m_device_name = "Default";
59         
60         QString _drv = QString::fromStdString(m_device_name);
61         config_t* _ccp = get_config_ptr();
62         if(_ccp != nullptr) {
63                 if(strlen(_ccp->sound_device_name) > 0) {
64                         _drv = QString::fromUtf8(_ccp->sound_device_name);
65                 }
66         }
67         auto _match = std::find(devices_name_list.begin(), devices_name_list.end(), _drv.toLocal8Bit().toStdString());
68         if(_match != devices_name_list.end()) {
69                 m_device_name = (*_match);
70         }
71         m_config_ok = initialize_driver();
72 }
73
74 M_QT_MULTIMEDIA::~M_QT_MULTIMEDIA()
75 {
76 }
77
78 void M_QT_MULTIMEDIA::driver_state_changed(QAudio::State newState)
79 {
80         switch(newState) {
81         case QAudio::ActiveState:
82                 __debug_log_func(_T("AUDIO:ACTIVE"));
83                 break;
84         case QAudio::IdleState:
85                 __debug_log_func(_T("AUDIO:IDLE"));
86                 //if(m_audioOutputSink != nullptr) {
87                 //      m_audioOutputSink->stop();
88                 //}
89                 break;
90         case QAudio::StoppedState:
91                 __debug_log_func(_T("AUDIO:STOP"));
92                 break;
93         case QAudio::SuspendedState:
94                 __debug_log_func(_T("AUDIO:SUSPEND"));
95                 break;
96         #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
97         case QAudio::InterruptedState:
98                 __debug_log_func(_T("AUDIO:INTERRUPTED"));
99                 break;
100         #endif
101         
102         }
103 }
104
105
106 void M_QT_MULTIMEDIA::update_driver_fileio()
107 {
108         m_driver_fileio = m_fileio;
109 }
110
111
112
113 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
114 void M_QT_MULTIMEDIA::set_audio_format(QAudioDevice dest_device, QAudioFormat& desired, int& channels, int& rate)
115 {
116         int _channels = channels;
117         if(dest_device.minimumChannelCount() > _channels) {
118                 _channels = dest_device.minimumChannelCount();
119         } else if(dest_device.maximumChannelCount() < _channels) {
120                 _channels = dest_device.maximumChannelCount();
121         }
122         int _rate = rate;
123         if(dest_device.minimumSampleRate() > _rate) {
124                 _rate = dest_device.minimumSampleRate();
125         } else if(dest_device.maximumSampleRate() < _rate) {
126                 _rate = dest_device.maximumSampleRate();
127         }
128         //if(_rate > 0) {
129         rate = _rate; // Workaround 20221018 K.O
130         //}
131         if(_rate <= 0) {
132                 return;
133         }
134         if(_channels > 0) {
135                 channels = _channels; // Workaround 20221008 K.O
136         }
137         desired.setSampleRate(rate);
138
139         QList<QAudioFormat::SampleFormat> _al = dest_device.supportedSampleFormats();
140         if(_al.contains(QAudioFormat::Int16)) {
141                 desired.setSampleFormat(QAudioFormat::Int16);
142         } else if(_al.contains(QAudioFormat::Int32)) {
143                 desired.setSampleFormat(QAudioFormat::Int32);
144         } else {
145                 desired.setSampleFormat(QAudioFormat::Unknown);
146         }
147
148         switch(channels) {
149         case 1:
150                 channels = 1;
151                 desired.setChannelConfig(QAudioFormat::ChannelConfigMono);
152                 break;
153         case 2:
154                 desired.setChannelConfig(QAudioFormat::ChannelConfigStereo);
155                 break;
156         case 3:
157                 desired.setChannelConfig(QAudioFormat::ChannelConfig2Dot1);
158                 break;
159         case 5:
160                 desired.setChannelConfig(QAudioFormat::ChannelConfigSurround5Dot0);
161                 break;
162         case 6:
163                 desired.setChannelConfig(QAudioFormat::ChannelConfigSurround5Dot1);
164                 break;
165         case 7:
166                 desired.setChannelConfig(QAudioFormat::ChannelConfigSurround7Dot0);
167                 break;
168         case 8:
169                 desired.setChannelConfig(QAudioFormat::ChannelConfigSurround7Dot1);
170                 break;
171         default:
172                 channels = 2;
173                 desired.setChannelConfig(QAudioFormat::ChannelConfigStereo);
174                 break;
175         }
176         desired.setChannelCount(channels);      
177 }
178 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
179 void M_QT_MULTIMEDIA::set_audio_format(QAudioDeviceInfo dest_device, QAudioFormat& desired, int& channels, int& rate)
180 {
181         int _channels = channels;
182         QList<int> channelsList = dest_device.supportedChannelCounts();
183         QList<int> ratesList    = dest_device.supportedSampleRates();
184
185         int _min_channels = INT_MAX;
186         int _max_channels = 0;
187         for(auto i = channelsList.begin() ; i != channelsList.end(); ++i) {
188                 if((*i) < _min_channels) _min_channels = (*i);
189                 if((*i) > _max_channels) _max_channels = (*i);
190         }
191         if(_min_channels > _channels) {
192                 _channels = _min_channels;
193         } else if(_max_channels < _channels) {
194                 _channels = _max_channels;
195         }
196         
197         int _min_rate = INT_MAX;
198         int _max_rate = 0;
199         for(auto i = ratesList.begin() ; i != ratesList.end(); ++i) {
200                 if((*i) < _min_rate) _min_rate = (*i);
201                 if((*i) > _max_rate) _max_rate = (*i);
202         }
203         if(_min_rate > rate) {
204                 rate = _min_rate;
205         } else if(_max_rate < rate) {
206                 rate = _max_rate;
207         }
208         if((rate <= 0)) {
209                 return;
210         }
211         if(_channels > 0) {
212                 channels = _channels; // Workaround 20221008 K.O
213         }
214         
215         desired.setSampleRate(rate);
216         desired.setSampleSize(16);
217         desired.setSampleType(QAudioFormat::SignedInt);
218         #if Q_BYTE_ORDER == Q_BIG_ENDIAN        
219         desired.setByteOrder(QAudioFormat::BigEndian);
220         #else
221         desired.setByteOrder(QAudioFormat::LittleEndian);
222         #endif
223
224         desired.setChannelCount(channels);      
225 }
226 #endif          
227
228 bool M_QT_MULTIMEDIA::initialize_driver()
229 {
230         bool result = false;
231
232 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
233         QAudioDevice tmp_output_device;
234 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
235         QAudioDeviceInfo tmp_output_device;
236 #endif
237         tmp_output_device = get_device_by_name(QString::fromStdString(m_device_name));
238         QAudioFormat tmp_output_format = tmp_output_device.preferredFormat();
239         
240         int _channels = m_channels;
241         int _rate = m_rate;
242         set_audio_format(tmp_output_device, tmp_output_format, _channels, _rate);
243         if((_channels > 0) && (_rate > 0)) {
244                 m_channels = _channels;
245                 m_rate = _rate;
246         } else {
247                 tmp_output_format = tmp_output_device.preferredFormat();
248                 _channels = tmp_output_format.channelCount();
249                 _rate     = tmp_output_format.sampleRate();
250                 if((_rate <= 0) || (_channels <= 0)) {
251                         return false; // None devices.
252                 }
253         }
254         m_audioOutputDevice = tmp_output_device;
255         m_audioOutputFormat = tmp_output_format;
256         
257 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
258         m_audioOutputSink.reset(new QAudioSink(m_audioOutputDevice, m_audioOutputFormat, this));
259 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
260         m_audioOutputSink.reset(new QAudioOutput(m_audioOutputDevice, m_audioOutputFormat, this));
261 #endif  
262         result = ((m_audioOutputSink.get() != nullptr) /* || (m_audioInputSource.get() != nullptr) */);
263         if(result) {
264                 connect(m_audioOutputSink.get(), SIGNAL(stateChanged(QAudio::State)), this, SLOT(driver_state_changed(QAudio::State)));
265                 m_channels = m_audioOutputSink->format().channelCount();
266                 m_rate = m_audioOutputSink->format().sampleRate();
267                 m_config_ok = true;
268         }
269         m_samples = ((qint64)m_latency_ms * (qint64)(m_rate)) / 1000;
270         if(m_samples <= 0) {
271                 m_samples = 4800;
272         }
273         update_driver_fileio();
274
275         __debug_log_func(_T("status=%s"), (m_config_ok) ? _T("OK") : _T("NG"));
276         return result;
277 }
278
279 void M_QT_MULTIMEDIA::initialize_sound_devices_list()
280 {
281         devices_name_list.clear();
282 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
283         m_audioOutputsList = QMediaDevices::audioOutputs();
284         for(auto i = m_audioOutputsList.begin(); i != m_audioOutputsList.end(); ++i) {
285                 devices_name_list.push_back((*i).description().toStdString());
286         }
287 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
288         m_audioOutputsList = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
289         for(auto i = m_audioOutputsList.begin(); i != m_audioOutputsList.end(); ++i) {
290                 devices_name_list.push_back((*i).deviceName().toStdString());
291         }
292 #endif  
293 }
294
295 std::list<std::string> M_QT_MULTIMEDIA::get_sound_devices_list()
296 {
297         return devices_name_list;
298 }
299
300 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
301 QAudioDevice M_QT_MULTIMEDIA::get_device_by_name(QString driver_name)
302 #else
303 QAudioDeviceInfo M_QT_MULTIMEDIA::get_device_by_name(QString driver_name)
304 #endif
305 {
306 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
307         QAudioDevice dest_device = m_audioOutputDevice;
308 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
309         QAudioDeviceInfo dest_device = m_audioOutputDevice;
310 #endif
311         
312         if((driver_name == QString::fromUtf8("Default")) || (driver_name.isEmpty())) {
313                 m_device_is_default = true;
314 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
315                 dest_device = QMediaDevices::defaultAudioOutput();
316 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
317                 dest_device = QAudioDeviceInfo::defaultOutputDevice();
318 #endif          
319         } else {
320                 for(auto i = m_audioOutputsList.begin(); i != m_audioOutputsList.end(); ++i) {
321 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
322                         if((*i).description().compare(driver_name) == 0) {
323                                 dest_device = *i;
324                                 m_device_is_default = false;
325                                 break;
326                         }
327 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
328                         if((*i).deviceName().compare(driver_name) == 0) {
329                                 dest_device = *i;
330                                 m_device_is_default = false;
331                                 break;
332                         }
333 #endif
334                 }
335         }
336         QString dest_device_name;
337 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
338         dest_device_name = dest_device.description();
339 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
340         dest_device_name = dest_device.deviceName();
341 #endif
342         
343         __debug_log_func(_T("desired_driver=%s using=%s"), driver_name.toLocal8Bit().constData(), dest_device_name.toLocal8Bit().constData());
344
345         return dest_device;
346 }
347         
348 void M_QT_MULTIMEDIA::do_set_device_by_name(QString driver_name)
349 {
350         if(m_device_name == driver_name.toLocal8Bit().toStdString()) {
351                 return;
352         }
353 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
354         QAudioDevice dest_device = get_device_by_name(driver_name);
355 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
356         QAudioDeviceInfo dest_device = get_device_by_name(driver_name);
357 #endif
358
359         setup_device(dest_device, m_rate, m_channels, m_latency_ms, true);
360 }
361
362 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
363 void M_QT_MULTIMEDIA::setup_device(QAudioDevice dest_device, int& rate,int& channels,int& latency_ms, bool force_reinit)
364 #else
365 void M_QT_MULTIMEDIA::setup_device(QAudioDeviceInfo dest_device, int& rate,int& channels,int& latency_ms, bool force_reinit)
366 #endif
367 {
368         if(dest_device.isNull()) return; // None initialize if NULL.
369         
370         __debug_log_func(_T("Expected: rate=%d channels=%d latency=%dmSec reinit=%d"), rate, channels, latency_ms, force_reinit);
371         
372         if(!(force_reinit)) {
373                 // If already initialized and not changed, skip.
374                 if((m_audioOutputDevice == dest_device)
375                    && (rate == m_rate)
376                    && (channels == m_channels)
377                    && (latency_ms == m_latency_ms)
378                    && (m_audioOutputSink.get() != nullptr)
379                    && (m_fileio.get() != nullptr)) {
380                         if(m_fileio->isOpen()) {
381                                 return;
382                         }
383                         update_driver_fileio();
384                         __debug_log_func(_T("Nothing changed.Exit."));
385
386                         //real_reconfig_sound(rate, channels, latency_ms);
387                         emit sig_start_audio();
388                         return;
389                 }
390         }
391         if((m_audioOutputDevice.isNull()) || (m_audioOutputDevice != dest_device)) {
392                 force_reinit = true;
393         }
394         bool force_req_reinit = false;
395         if(!(force_reinit)) {
396                 if(m_latency_ms != latency_ms) {
397                         force_req_reinit = true;
398                 }
399                 if(m_audioOutputSink.get() != nullptr) {
400                         if((m_audioOutputSink->format().channelCount() != channels) ||
401                            (m_audioOutputSink->format().sampleRate() != rate)) {
402                                 force_req_reinit = true;
403                         }
404                 } else {
405                         force_reinit = true;
406                 }
407         }
408
409         
410         if((force_reinit) || (force_req_reinit)) {
411                 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
412                 QString __name = dest_device.description();
413                 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
414                 QString __name = dest_device.deviceName();
415                 #endif
416                 
417                 QAudioFormat desired = dest_device.preferredFormat();
418                 int _channels = channels;
419                 int _rate = rate;
420                 set_audio_format(dest_device, desired, channels, rate);
421                 if((channels <= 0) || (rate <= 0)) {
422                         __debug_log_func(_T("Desired device \"%s\" don't be effective.Make fallback. rate=%d channels=%d"), __name.toLocal8Bit().constData(), rate, channels);
423                         channels = _channels;
424                         rate = _rate;
425                         return;
426                 }
427                 
428                 if(m_audioOutputSink.get() != nullptr) {
429                         if(m_audioOutputSink->state() != QAudio::StoppedState) {
430                                 m_audioOutputSink->stop();
431                                 wait_driver_stopped(1000);
432                         }
433                         m_audioOutputSink->disconnect();
434                         m_audioOutputSink.reset();
435                 }
436                 
437                 m_audioOutputDevice = dest_device;
438                 m_audioOutputFormat = desired;
439                 
440 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
441                 m_audioOutputSink.reset(new QAudioSink(dest_device, desired, this));
442 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
443                 m_audioOutputSink.reset(new QAudioOutput(dest_device, desired, this));
444 #endif
445                 do_discard_sound();
446                 m_prev_started = false;
447                 m_before_rendered = 0;
448                 
449                 if(m_audioOutputSink.get() != nullptr) {
450                         m_audioOutputSink->setBufferSize(m_chunk_bytes);
451                         connect(m_audioOutputSink.get(), SIGNAL(stateChanged(QAudio::State)), this, SLOT(driver_state_changed(QAudio::State)));
452                         channels = m_audioOutputSink->format().channelCount();
453                         rate = m_audioOutputSink->format().sampleRate();
454                         QString _tmpname = QString::fromUtf8("Defalut");
455                         if(!(m_device_is_default)) {
456                                 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
457                                 _tmpname = m_audioOutputDevice.description();
458                                 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
459                                 _tmpname = m_audioOutputDevice.deviceName();
460                                 #endif
461                         }
462                         m_device_name = _tmpname.toLocal8Bit().toStdString();
463                         config_t* _ccp = get_config_ptr();
464                         if(_ccp != nullptr) {
465                                 memset(_ccp->sound_device_name, 0x00, sizeof(_ccp->sound_device_name));
466                                 my_tcscpy_s(_ccp->sound_device_name, (sizeof(_ccp->sound_device_name) / sizeof(_TCHAR)) - 1, _tmpname.toUtf8().constData());
467                         }
468
469                         recalc_samples(rate, latency_ms, true, true);
470                         m_config_ok = (m_fileio.get() != nullptr);
471                         if(m_config_ok.load()) {
472                                 real_reconfig_sound(rate, channels, latency_ms);
473                         }
474                 } else {
475                         m_device_name.clear();
476                         m_config_ok = false;
477                         
478                         int64_t _samples =
479                                 ((int64_t)rate * latency_ms) / 1000;
480                         if(_samples < 100) _samples = 100;
481                         if(m_fileio.get() != nullptr) {
482                                 if(m_fileio->isOpen()) {
483                                         m_fileio->close();
484                                 }
485                                 m_fileio.reset();
486                                 update_driver_fileio();
487                         }
488                         m_samples = _samples;
489                         m_latency_ms = latency_ms;
490                         m_rate = rate;
491                         m_channels = channels;
492                 }
493         }
494         __debug_log_func(_T("Result: rate=%d channels=%d latency=%dmSec reinit=%d"), m_rate, m_channels, m_latency_ms, force_reinit);
495         if(m_audioOutputSink.get() != nullptr) {
496                 update_driver_fileio();
497                 emit sig_start_audio();
498                 //update_render_point_usec();
499         }
500 }
501
502 const std::string M_QT_MULTIMEDIA::set_device_sound(const _TCHAR* driver_name, int& rate,int& channels,int& latency_ms)
503 {
504         if(driver_name == nullptr) {
505                 return (const std::string)(std::string(""));
506         }
507         if(strlen(driver_name) <= 0) {
508                 return (const std::string)(std::string(""));
509         }
510         
511         QString _name = QString::fromUtf8(driver_name);
512         
513 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
514         QAudioDevice dest_device = get_device_by_name(_name);
515 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
516         QAudioDeviceInfo dest_device = get_device_by_name(_name);
517 #endif
518         setup_device(dest_device, rate, channels, latency_ms, false);
519         
520 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
521         return m_audioOutputDevice.description().toStdString();
522 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
523         return m_audioOutputDevice.deviceName().toStdString();
524 #else
525         return (const std::string)(std::string(""));
526 #endif  
527 }
528
529 bool M_QT_MULTIMEDIA::real_reconfig_sound(int& rate,int& channels,int& latency_ms)
530 {
531         if((rate <= 0) || (channels < 1) || (latency_ms < 10)) {
532                 return false;
533         }
534
535         int64_t _samples = (rate * latency_ms) / 1000;
536 //      if((rate != m_rate) || (_samples != m_samples) || (m_latency_ms != latency_ms)) {
537                 m_device_name = set_device_sound((const _TCHAR *)(m_device_name.c_str()), rate, channels, latency_ms);
538                 __debug_log_func(_T("Returned Driver=\"%s\" rate=%dHz channles=%d latency=%dmSec"), m_device_name.c_str(), rate, channels, latency_ms);
539                 //emit sig_set_sound_device(m_device_name);
540 //      }
541         if((rate <= 0) || (latency_ms <= 0)) {
542                 rate = 48000;
543                 latency_ms = 100;
544                 channels = 2;
545                 m_config_ok = false;
546         }
547         if(recalc_samples(rate, latency_ms, true, false)) {
548                 m_prev_started = m_mute = false;
549         }
550         
551         return m_config_ok.load();
552 }
553
554
555 void M_QT_MULTIMEDIA::release_sound()
556 {
557 //      std::lock_guard<std::recursive_timed_mutex> locker(m_locker);
558         if(m_audioOutputSink.get() != nullptr) {
559                 m_audioOutputSink->stop();
560                 m_audioOutputSink->disconnect();
561         }
562         m_audioOutputSink.reset();
563
564         M_BASE::release_sound();
565 }
566
567 bool M_QT_MULTIMEDIA::release_driver()
568 {
569         emit sig_stop_audio();
570         if(!(wait_driver_stopped(1000))) return false;
571         return release_driver_fileio();
572 }
573         
574 void M_QT_MULTIMEDIA::do_sound_start()
575 {
576 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
577         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
578 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
579         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
580 #endif
581         if(p.get() == nullptr) {
582                 return;
583         }
584         if((p->state() != QAudio::StoppedState) && (m_prev_started)) {
585 //              update_render_point_usec();
586                 return;
587         }
588         if(m_driver_fileio.get() == nullptr) {
589                 //m_driver_fileio->reset();
590                 return;
591         }
592         m_driver_fileio->reset();
593         p->setBufferSize(m_chunk_bytes);
594         p->start(m_driver_fileio.get());
595         update_render_point_usec();
596         __debug_log_func("GO. fileio=%0llx", m_driver_fileio.get());
597
598         //update_render_point_usec();
599         m_prev_started = true;
600 }
601
602 void M_QT_MULTIMEDIA::do_sound_stop()
603 {
604 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
605         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
606 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
607         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
608 #endif
609         if(p.get() != nullptr) {
610                 p->stop();
611         }
612         do_discard_sound();
613         m_before_rendered = 0;
614         m_prev_started = false;
615 }
616
617 void M_QT_MULTIMEDIA::do_sound_resume()
618 {
619 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
620         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
621 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
622         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
623 #endif
624         if(p.get() != nullptr) {
625                 p->resume();
626                 update_render_point_usec();
627         }
628 }
629
630 void M_QT_MULTIMEDIA::do_sound_suspend()
631 {
632 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
633         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
634 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
635         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
636 #endif
637         if(p.get() != nullptr) {
638                 p->suspend();
639         }
640 }
641
642 void M_QT_MULTIMEDIA::do_sound_volume(double level)
643 {
644 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
645         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
646 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
647         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
648 #endif
649         if(p.get() != nullptr) {
650                 p->setVolume(level);
651         }
652 }
653
654 int64_t M_QT_MULTIMEDIA::driver_elapsed_usec()
655 {
656 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
657         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
658 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
659         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
660 #endif
661         if(p.get() != nullptr) {
662                 return (int64_t)(p->elapsedUSecs());
663                 //return (int64_t)(p->processedUSecs());
664         }
665         return 0;
666 }
667
668 int64_t M_QT_MULTIMEDIA::driver_processed_usec()
669 {
670 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
671         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
672 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
673         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
674 #endif
675         if(p.get() != nullptr) {
676                 return (int64_t)(p->processedUSecs());
677         }
678         return 0;
679 }
680
681 bool M_QT_MULTIMEDIA::is_driver_started()
682 {
683         bool _b = M_BASE::is_driver_started();
684         std::shared_ptr<SOUND_BUFFER_QT> q = m_driver_fileio;
685         if(q.get() == nullptr) {
686                 return false;
687         }
688         if(!(q->isOpen())) {
689                 return false;
690         }
691         
692 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
693         std::shared_ptr<QAudioSink> p = m_audioOutputSink;
694 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
695         std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
696 #endif
697         if(p.get() == nullptr) {
698                 return false;
699         }
700         if(p->state() == QAudio::StoppedState) {
701                 return false;
702         }
703         return _b;
704 }
705
706 void M_QT_MULTIMEDIA::mute_sound()
707 {
708         if(!(m_mute.load()) && (m_config_ok.load())) {
709                 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
710                 std::shared_ptr<QAudioSink> p = m_audioOutputSink;
711                 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
712                 std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
713                 #endif
714                 
715                 if(p.get() != nullptr) {
716                         switch(p->state()) {
717                         case QAudio::ActiveState:
718                         case QAudio::IdleState:
719                                 emit sig_pause_audio();
720                                 emit sig_discard_audio();
721                                 break;
722                         default:
723                                 break;
724                         }
725                 }
726         }
727         m_mute = true;
728 }
729
730 void M_QT_MULTIMEDIA::do_discard_sound()
731 {
732         std::shared_ptr<SOUND_BUFFER_QT> q = m_driver_fileio;
733         if(q.get() != nullptr) {
734                 q->reset();
735         }
736 }
737
738 void M_QT_MULTIMEDIA::stop_sound()
739 {
740         if((m_config_ok.load()) && (m_prev_started)) {
741                 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
742                 std::shared_ptr<QAudioSink> p = m_audioOutputSink;
743                 #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
744                 std::shared_ptr<QAudioOutput> p = m_audioOutputSink;
745                 #endif
746                 if(p.get() != nullptr) {
747                         switch(p->state()) {
748                         case QAudio::ActiveState:
749                         case QAudio::IdleState:
750                         case QAudio::SuspendedState:
751                                 emit sig_stop_audio();
752                                 break;
753                         default:
754                                 break;
755                         }
756                 }
757         }
758 }
759
760         /* SOUND_MODULE::OUTPUT */
761         }
762 /* SOUND_MODULE */
763
764 }
765