SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
audiodevicemanager.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
20 #include "util/simpleserializer.h"
21 #include "util/messagequeue.h"
22 #include "dsp/dspcommands.h"
23 
24 #include <QDataStream>
25 #include <QSet>
26 #include <QDebug>
27 
29 const QString AudioDeviceManager::m_defaultUDPAddress = "127.0.0.1";
30 const QString AudioDeviceManager::m_defaultDeviceName = "System default device";
31 
32 QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info)
33 {
34  ds << info.sampleRate << info.volume;
35  return ds;
36 }
37 
38 QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::InputDeviceInfo& info)
39 {
40  ds >> info.sampleRate >> info.volume;
41  return ds;
42 }
43 
44 QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::OutputDeviceInfo& info)
45 {
46  ds << info.sampleRate
47  << info.udpAddress
48  << info.udpPort
49  << info.copyToUDP
50  << info.udpUseRTP
51  << (int) info.udpChannelMode
52  << (int) info.udpChannelCodec
53  << info.udpDecimationFactor;
54  return ds;
55 }
56 
57 QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::OutputDeviceInfo& info)
58 {
59  int intChannelMode;
60  int intChannelCodec;
61 
62  ds >> info.sampleRate
63  >> info.udpAddress
64  >> info.udpPort
65  >> info.copyToUDP
66  >> info.udpUseRTP
67  >> intChannelMode
68  >> intChannelCodec
69  >> info.udpDecimationFactor;
70  info.udpChannelMode = (AudioOutput::UDPChannelMode) intChannelMode;
71  info.udpChannelCodec = (AudioOutput::UDPChannelCodec) intChannelCodec;
72  return ds;
73 }
74 
76 {
77  qDebug("AudioDeviceManager::AudioDeviceManager: scan input devices");
78  m_inputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
79 
80  for (int i = 0; i < m_inputDevicesInfo.size(); i++) {
81  qDebug("AudioDeviceManager::AudioDeviceManager: input device #%d: %s", i, qPrintable(m_inputDevicesInfo[i].deviceName()));
82  }
83 
84  qDebug("AudioDeviceManager::AudioDeviceManager: scan output devices");
85  m_outputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
86 
87  for (int i = 0; i < m_outputDevicesInfo.size(); i++) {
88  qDebug("AudioDeviceManager::AudioDeviceManager: output device #%d: %s", i, qPrintable(m_outputDevicesInfo[i].deviceName()));
89  }
90 }
91 
93 {
94  QMap<int, AudioOutput*>::iterator it = m_audioOutputs.begin();
95 
96  for (; it != m_audioOutputs.end(); ++it) {
97  delete(*it);
98  }
99 }
100 
101 bool AudioDeviceManager::getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const
102 {
103  if (outputDeviceIndex < 0)
104  {
105  deviceName = m_defaultDeviceName;
106  return true;
107  }
108  else
109  {
110  if (outputDeviceIndex < m_outputDevicesInfo.size())
111  {
112  deviceName = m_outputDevicesInfo[outputDeviceIndex].deviceName();
113  return true;
114  }
115  else
116  {
117  return false;
118  }
119  }
120 }
121 
122 bool AudioDeviceManager::getInputDeviceName(int inputDeviceIndex, QString &deviceName) const
123 {
124  if (inputDeviceIndex < 0)
125  {
126  deviceName = m_defaultDeviceName;
127  return true;
128  }
129  else
130  {
131  if (inputDeviceIndex < m_inputDevicesInfo.size())
132  {
133  deviceName = m_inputDevicesInfo[inputDeviceIndex].deviceName();
134  return true;
135  }
136  else
137  {
138  return false;
139  }
140  }
141 }
142 
143 int AudioDeviceManager::getOutputDeviceIndex(const QString &deviceName) const
144 {
145  for (int i = 0; i < m_outputDevicesInfo.size(); i++)
146  {
147  //qDebug("AudioDeviceManager::getOutputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(m_outputDevicesInfo[i].deviceName()));
148  if (deviceName == m_outputDevicesInfo[i].deviceName()) {
149  return i;
150  }
151  }
152 
153  return -1; // system default
154 }
155 
156 int AudioDeviceManager::getInputDeviceIndex(const QString &deviceName) const
157 {
158  for (int i = 0; i < m_inputDevicesInfo.size(); i++)
159  {
160  //qDebug("AudioDeviceManager::getInputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(m_inputDevicesInfo[i].deviceName()));
161  if (deviceName == m_inputDevicesInfo[i].deviceName()) {
162  return i;
163  }
164  }
165 
166  return -1; // system default
167 }
168 
169 
171 {
172 }
173 
175 {
176  qDebug("AudioDeviceManager::serialize");
179 
180  SimpleSerializer s(1);
181  QByteArray data;
182 
183  serializeInputMap(data);
184  s.writeBlob(1, data);
185  serializeOutputMap(data);
186  s.writeBlob(2, data);
187 
188  return s.final();
189 }
190 
191 void AudioDeviceManager::serializeInputMap(QByteArray& data) const
192 {
193  QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
194  *stream << m_audioInputInfos;
195  delete stream;
196 }
197 
198 void AudioDeviceManager::serializeOutputMap(QByteArray& data) const
199 {
200  QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
201  *stream << m_audioOutputInfos;
202  delete stream;
203 }
204 
205 bool AudioDeviceManager::deserialize(const QByteArray& data)
206 {
207  qDebug("AudioDeviceManager::deserialize");
208 
209  SimpleDeserializer d(data);
210 
211  if(!d.isValid()) {
212  resetToDefaults();
213  return false;
214  }
215 
216  if(d.getVersion() == 1)
217  {
218  QByteArray data;
219 
220  d.readBlob(1, &data);
221  deserializeInputMap(data);
222  d.readBlob(2, &data);
223  deserializeOutputMap(data);
224 
227 
228  return true;
229  }
230  else
231  {
232  resetToDefaults();
233  return false;
234  }
235 }
236 
238 {
239  QDataStream readStream(&data, QIODevice::ReadOnly);
240  readStream >> m_audioInputInfos;
241 }
242 
244 {
245  QDataStream readStream(&data, QIODevice::ReadOnly);
246  readStream >> m_audioOutputInfos;
247 }
248 
249 void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex)
250 {
251  qDebug("AudioDeviceManager::addAudioSink: %d: %p", outputDeviceIndex, audioFifo);
252 
253  if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) {
254  m_audioOutputs[outputDeviceIndex] = new AudioOutput();
255  }
256 
257  if (m_audioOutputs[outputDeviceIndex]->getNbFifos() == 0) {
258  startAudioOutput(outputDeviceIndex);
259  }
260 
261  if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end()) // new FIFO
262  {
263  m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo);
264  m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO
265  m_audioFifoToSinkMessageQueues[audioFifo] = sampleSinkMessageQueue;
266  m_outputDeviceSinkMessageQueues[outputDeviceIndex].append(sampleSinkMessageQueue);
267  }
268  else
269  {
270  int audioOutputDeviceIndex = m_audioSinkFifos[audioFifo];
271 
272  if (audioOutputDeviceIndex != outputDeviceIndex) // change of audio device
273  {
274  removeAudioSink(audioFifo); // remove from current
275  m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo); // add to new
276  m_audioSinkFifos[audioFifo] = outputDeviceIndex; // new index
277  m_outputDeviceSinkMessageQueues[audioOutputDeviceIndex].removeOne(sampleSinkMessageQueue);
278  m_outputDeviceSinkMessageQueues[outputDeviceIndex].append(sampleSinkMessageQueue);
279  }
280  }
281 }
282 
284 {
285  qDebug("AudioDeviceManager::removeAudioSink: %p", audioFifo);
286 
287  if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end())
288  {
289  qWarning("AudioDeviceManager::removeAudioSink: audio FIFO %p not found", audioFifo);
290  return;
291  }
292 
293  int audioOutputDeviceIndex = m_audioSinkFifos[audioFifo];
294  m_audioOutputs[audioOutputDeviceIndex]->removeFifo(audioFifo);
295 
296  if (m_audioOutputs[audioOutputDeviceIndex]->getNbFifos() == 0) {
297  stopAudioOutput(audioOutputDeviceIndex);
298  }
299 
300  m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO
301  m_outputDeviceSinkMessageQueues[audioOutputDeviceIndex].removeOne(m_audioFifoToSinkMessageQueues[audioFifo]);
302  m_audioFifoToSinkMessageQueues.remove(audioFifo);
303 }
304 
305 void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex)
306 {
307  qDebug("AudioDeviceManager::addAudioSource: %d: %p", inputDeviceIndex, audioFifo);
308 
309  if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) {
310  m_audioInputs[inputDeviceIndex] = new AudioInput();
311  }
312 
313  if (m_audioInputs[inputDeviceIndex]->getNbFifos() == 0) {
314  startAudioInput(inputDeviceIndex);
315  }
316 
317  if (m_audioSourceFifos.find(audioFifo) == m_audioSourceFifos.end()) // new FIFO
318  {
319  m_audioInputs[inputDeviceIndex]->addFifo(audioFifo);
320  }
321  else
322  {
323  int audioInputDeviceIndex = m_audioSourceFifos[audioFifo];
324 
325  if (audioInputDeviceIndex != inputDeviceIndex) // change of audio device
326  {
327  removeAudioSource(audioFifo); // remove from current
328  m_audioInputs[inputDeviceIndex]->addFifo(audioFifo); // add to new
329  }
330  }
331 
332  m_audioSourceFifos[audioFifo] = inputDeviceIndex; // register audio FIFO
333  m_audioFifoToSourceMessageQueues[audioFifo] = sampleSourceMessageQueue;
334  m_outputDeviceSinkMessageQueues[inputDeviceIndex].append(sampleSourceMessageQueue);
335 }
336 
338 {
339  qDebug("AudioDeviceManager::removeAudioSource: %p", audioFifo);
340 
341  if (m_audioSourceFifos.find(audioFifo) == m_audioSourceFifos.end())
342  {
343  qWarning("AudioDeviceManager::removeAudioSource: audio FIFO %p not found", audioFifo);
344  return;
345  }
346 
347  int audioInputDeviceIndex = m_audioSourceFifos[audioFifo];
348  m_audioInputs[audioInputDeviceIndex]->removeFifo(audioFifo);
349 
350  if (m_audioInputs[audioInputDeviceIndex]->getNbFifos() == 0) {
351  stopAudioInput(audioInputDeviceIndex);
352  }
353 
354  m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO
355  m_inputDeviceSourceMessageQueues[audioInputDeviceIndex].removeOne(m_audioFifoToSourceMessageQueues[audioFifo]);
356  m_audioFifoToSourceMessageQueues.remove(audioFifo);
357 }
358 
359 void AudioDeviceManager::startAudioOutput(int outputDeviceIndex)
360 {
361  unsigned int sampleRate;
362  QString udpAddress;
363  quint16 udpPort;
364  bool copyAudioToUDP;
365  bool udpUseRTP;
366  AudioOutput::UDPChannelMode udpChannelMode;
367  AudioOutput::UDPChannelCodec udpChannelCodec;
368  uint32_t decimationFactor;
369  QString deviceName;
370 
371  if (getOutputDeviceName(outputDeviceIndex, deviceName))
372  {
373  if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end())
374  {
375  sampleRate = m_defaultAudioSampleRate;
376  udpAddress = m_defaultUDPAddress;
377  udpPort = m_defaultUDPPort;
378  copyAudioToUDP = false;
379  udpUseRTP = false;
380  udpChannelMode = AudioOutput::UDPChannelLeft;
381  udpChannelCodec = AudioOutput::UDPCodecL16;
382  decimationFactor = 1;
383  }
384  else
385  {
386  sampleRate = m_audioOutputInfos[deviceName].sampleRate;
387  udpAddress = m_audioOutputInfos[deviceName].udpAddress;
388  udpPort = m_audioOutputInfos[deviceName].udpPort;
389  copyAudioToUDP = m_audioOutputInfos[deviceName].copyToUDP;
390  udpUseRTP = m_audioOutputInfos[deviceName].udpUseRTP;
391  udpChannelMode = m_audioOutputInfos[deviceName].udpChannelMode;
392  udpChannelCodec = m_audioOutputInfos[deviceName].udpChannelCodec;
393  decimationFactor = m_audioOutputInfos[deviceName].udpDecimationFactor;
394  }
395 
396  m_audioOutputs[outputDeviceIndex]->start(outputDeviceIndex, sampleRate);
397  m_audioOutputInfos[deviceName].sampleRate = m_audioOutputs[outputDeviceIndex]->getRate(); // update with actual rate
398  m_audioOutputInfos[deviceName].udpAddress = udpAddress;
399  m_audioOutputInfos[deviceName].udpPort = udpPort;
400  m_audioOutputInfos[deviceName].copyToUDP = copyAudioToUDP;
401  m_audioOutputInfos[deviceName].udpUseRTP = udpUseRTP;
402  m_audioOutputInfos[deviceName].udpChannelMode = udpChannelMode;
403  m_audioOutputInfos[deviceName].udpChannelCodec = udpChannelCodec;
404  m_audioOutputInfos[deviceName].udpDecimationFactor = decimationFactor;
405  }
406  else
407  {
408  qWarning("AudioDeviceManager::startAudioOutput: unknown device index %d", outputDeviceIndex);
409  }
410 }
411 
412 void AudioDeviceManager::stopAudioOutput(int outputDeviceIndex)
413 {
414  m_audioOutputs[outputDeviceIndex]->stop();
415 }
416 
417 void AudioDeviceManager::startAudioInput(int inputDeviceIndex)
418 {
419  unsigned int sampleRate;
420  float volume;
421  QString deviceName;
422 
423  if (getInputDeviceName(inputDeviceIndex, deviceName))
424  {
425  if (m_audioInputInfos.find(deviceName) == m_audioInputInfos.end())
426  {
427  sampleRate = m_defaultAudioSampleRate;
428  volume = m_defaultAudioInputVolume;
429  }
430  else
431  {
432  sampleRate = m_audioInputInfos[deviceName].sampleRate;
433  volume = m_audioInputInfos[deviceName].volume;
434  }
435 
436  m_audioInputs[inputDeviceIndex]->start(inputDeviceIndex, sampleRate);
437  m_audioInputs[inputDeviceIndex]->setVolume(volume);
438  m_audioInputInfos[deviceName].sampleRate = m_audioInputs[inputDeviceIndex]->getRate();
439  m_audioInputInfos[deviceName].volume = volume;
440  }
441  else
442  {
443  qWarning("AudioDeviceManager::startAudioInput: unknown device index %d", inputDeviceIndex);
444  }
445 }
446 
447 void AudioDeviceManager::stopAudioInput(int inputDeviceIndex)
448 {
449  m_audioInputs[inputDeviceIndex]->stop();
450 }
451 
452 bool AudioDeviceManager::getInputDeviceInfo(const QString& deviceName, InputDeviceInfo& deviceInfo) const
453 {
454  if (m_audioInputInfos.find(deviceName) == m_audioInputInfos.end())
455  {
456  return false;
457  }
458  else
459  {
460  deviceInfo = m_audioInputInfos[deviceName];
461  return true;
462  }
463 }
464 
465 bool AudioDeviceManager::getOutputDeviceInfo(const QString& deviceName, OutputDeviceInfo& deviceInfo) const
466 {
467  if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end())
468  {
469  return false;
470  }
471  else
472  {
473  deviceInfo = m_audioOutputInfos[deviceName];
474  return true;
475  }
476 }
477 
478 int AudioDeviceManager::getInputSampleRate(int inputDeviceIndex)
479 {
480  QString deviceName;
481 
482  if (!getInputDeviceName(inputDeviceIndex, deviceName))
483  {
484  qDebug("AudioDeviceManager::getInputSampleRate: unknown device index %d", inputDeviceIndex);
486  }
487 
488  InputDeviceInfo deviceInfo;
489 
490  if (!getInputDeviceInfo(deviceName, deviceInfo))
491  {
492  qDebug("AudioDeviceManager::getInputSampleRate: unknown device %s", qPrintable(deviceName));
494  }
495  else
496  {
497  return deviceInfo.sampleRate;
498  }
499 }
500 
501 int AudioDeviceManager::getOutputSampleRate(int outputDeviceIndex)
502 {
503  QString deviceName;
504 
505  if (!getOutputDeviceName(outputDeviceIndex, deviceName))
506  {
507  qDebug("AudioDeviceManager::getOutputSampleRate: unknown device index %d", outputDeviceIndex);
509  }
510 
511  OutputDeviceInfo deviceInfo;
512 
513  if (!getOutputDeviceInfo(deviceName, deviceInfo))
514  {
515  qDebug("AudioDeviceManager::getOutputSampleRate: unknown device %s", qPrintable(deviceName));
517  }
518  else
519  {
520  return deviceInfo.sampleRate;
521  }
522 }
523 
524 
525 void AudioDeviceManager::setInputDeviceInfo(int inputDeviceIndex, const InputDeviceInfo& deviceInfo)
526 {
527  QString deviceName;
528 
529  if (!getInputDeviceName(inputDeviceIndex, deviceName))
530  {
531  qWarning("AudioDeviceManager::setInputDeviceInfo: unknown device index %d", inputDeviceIndex);
532  return;
533  }
534 
535  InputDeviceInfo oldDeviceInfo;
536 
537  if (!getInputDeviceInfo(deviceName, oldDeviceInfo))
538  {
539  qDebug("AudioDeviceManager::setInputDeviceInfo: unknown device %s", qPrintable(deviceName));
540  }
541 
542  m_audioInputInfos[deviceName] = deviceInfo;
543 
544  if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { // no FIFO registered yet hence no audio input has been allocated yet
545  return;
546  }
547 
548  AudioInput *audioInput = m_audioInputs[inputDeviceIndex];
549 
550  if (oldDeviceInfo.sampleRate != deviceInfo.sampleRate)
551  {
552  audioInput->stop();
553  audioInput->start(inputDeviceIndex, deviceInfo.sampleRate);
554  m_audioInputInfos[deviceName].sampleRate = audioInput->getRate(); // store actual sample rate
555 
556  // send message to attached channels
557  QList<MessageQueue *>::const_iterator it = m_inputDeviceSourceMessageQueues[inputDeviceIndex].begin();
558 
559  for (; it != m_inputDeviceSourceMessageQueues[inputDeviceIndex].end(); ++it)
560  {
562  (*it)->push(msg);
563  }
564  }
565 
566  audioInput->setVolume(deviceInfo.volume);
567 }
568 
569 void AudioDeviceManager::setOutputDeviceInfo(int outputDeviceIndex, const OutputDeviceInfo& deviceInfo)
570 {
571  QString deviceName;
572 
573  if (!getOutputDeviceName(outputDeviceIndex, deviceName))
574  {
575  qWarning("AudioDeviceManager::setOutputDeviceInfo: unknown device index %d", outputDeviceIndex);
576  return;
577  }
578 
579  OutputDeviceInfo oldDeviceInfo;
580 
581  if (!getOutputDeviceInfo(deviceName, oldDeviceInfo))
582  {
583  qInfo("AudioDeviceManager::setOutputDeviceInfo: unknown device %s", qPrintable(deviceName));
584  }
585 
586  m_audioOutputInfos[deviceName] = deviceInfo;
587 
588  if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end())
589  {
590  qWarning("AudioDeviceManager::setOutputDeviceInfo: index: %d device: %s no FIFO registered yet hence no audio output has been allocated yet",
591  outputDeviceIndex, qPrintable(deviceName));
592  return;
593  }
594 
595  AudioOutput *audioOutput = m_audioOutputs[outputDeviceIndex];
596 
597  if (oldDeviceInfo.sampleRate != deviceInfo.sampleRate)
598  {
599  audioOutput->stop();
600  audioOutput->start(outputDeviceIndex, deviceInfo.sampleRate);
601  m_audioOutputInfos[deviceName].sampleRate = audioOutput->getRate(); // store actual sample rate
602 
603  // send message to attached channels
604  QList<MessageQueue *>::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin();
605 
606  for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it)
607  {
609  (*it)->push(msg);
610  }
611  }
612 
613  audioOutput->setUdpCopyToUDP(deviceInfo.copyToUDP);
614  audioOutput->setUdpDestination(deviceInfo.udpAddress, deviceInfo.udpPort);
615  audioOutput->setUdpUseRTP(deviceInfo.udpUseRTP);
616  audioOutput->setUdpChannelMode(deviceInfo.udpChannelMode);
617  audioOutput->setUdpChannelFormat(deviceInfo.udpChannelCodec, deviceInfo.udpChannelMode == AudioOutput::UDPChannelStereo, deviceInfo.sampleRate);
618  audioOutput->setUdpDecimation(deviceInfo.udpDecimationFactor);
619 
620  qDebug("AudioDeviceManager::setOutputDeviceInfo: index: %d device: %s updated",
621  outputDeviceIndex, qPrintable(deviceName));
622 }
623 
624 void AudioDeviceManager::unsetOutputDeviceInfo(int outputDeviceIndex)
625 {
626  QString deviceName;
627 
628  if (!getOutputDeviceName(outputDeviceIndex, deviceName))
629  {
630  qWarning("AudioDeviceManager::unsetOutputDeviceInfo: unknown device index %d", outputDeviceIndex);
631  return;
632  }
633 
634  OutputDeviceInfo oldDeviceInfo;
635 
636  if (!getOutputDeviceInfo(deviceName, oldDeviceInfo))
637  {
638  qDebug("AudioDeviceManager::unsetOutputDeviceInfo: unregistered device %s", qPrintable(deviceName));
639  return;
640  }
641 
642  m_audioOutputInfos.remove(deviceName);
643 
644  if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) { // no FIFO registered yet hence no audio output has been allocated yet
645  return;
646  }
647 
648  stopAudioOutput(outputDeviceIndex);
649  startAudioOutput(outputDeviceIndex);
650 
651  if (oldDeviceInfo.sampleRate != m_audioOutputInfos[deviceName].sampleRate)
652  {
653  // send message to attached channels
654  QList<MessageQueue *>::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin();
655 
656  for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it)
657  {
659  (*it)->push(msg);
660  }
661  }
662 }
663 
665 {
666  QString deviceName;
667 
668  if (!getInputDeviceName(inputDeviceIndex, deviceName))
669  {
670  qWarning("AudioDeviceManager::unsetInputDeviceInfo: unknown device index %d", inputDeviceIndex);
671  return;
672  }
673 
674  InputDeviceInfo oldDeviceInfo;
675 
676  if (!getInputDeviceInfo(deviceName, oldDeviceInfo))
677  {
678  qDebug("AudioDeviceManager::unsetInputDeviceInfo: unregistered device %s", qPrintable(deviceName));
679  return;
680  }
681 
682  m_audioInputInfos.remove(deviceName);
683 
684  if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { // no FIFO registered yet hence no audio input has been allocated yet
685  return;
686  }
687 
688  stopAudioInput(inputDeviceIndex);
689  startAudioInput(inputDeviceIndex);
690 
691  if (oldDeviceInfo.sampleRate != m_audioInputInfos[deviceName].sampleRate)
692  {
693  // send message to attached channels
694  QList<MessageQueue *>::const_iterator it = m_inputDeviceSourceMessageQueues[inputDeviceIndex].begin();
695 
696  for (; it != m_inputDeviceSourceMessageQueues[inputDeviceIndex].end(); ++it)
697  {
699  (*it)->push(msg);
700  }
701  }
702 }
703 
705 {
706  QSet<QString> deviceNames;
707  deviceNames.insert(m_defaultDeviceName);
708  QList<QAudioDeviceInfo>::const_iterator itd = m_inputDevicesInfo.begin();
709 
710  for (; itd != m_inputDevicesInfo.end(); ++itd)
711  {
712  qDebug("AudioDeviceManager::inputInfosCleanup: device: %s", qPrintable(itd->deviceName()));
713  deviceNames.insert(itd->deviceName());
714  }
715 
716  QMap<QString, InputDeviceInfo>::iterator itm = m_audioInputInfos.begin();
717 
718  for (; itm != m_audioInputInfos.end();)
719  {
720  if (!deviceNames.contains(itm.key()))
721  {
722  qDebug("AudioDeviceManager::inputInfosCleanup: removing key: %s", qPrintable(itm.key()));
723  m_audioInputInfos.erase(itm++);
724  }
725  else
726  {
727  ++itm;
728  }
729  }
730 }
731 
733 {
734  QSet<QString> deviceNames;
735  deviceNames.insert(m_defaultDeviceName);
736  QList<QAudioDeviceInfo>::const_iterator itd = m_outputDevicesInfo.begin();
737 
738  for (; itd != m_outputDevicesInfo.end(); ++itd)
739  {
740  qDebug("AudioDeviceManager::outputInfosCleanup: device: %s", qPrintable(itd->deviceName()));
741  deviceNames.insert(itd->deviceName());
742  }
743 
744  QMap<QString, OutputDeviceInfo>::iterator itm = m_audioOutputInfos.begin();
745 
746  for (; itm != m_audioOutputInfos.end();)
747  {
748  if (!deviceNames.contains(itm.key()))
749  {
750  qDebug("AudioDeviceManager::outputInfosCleanup: removing key: %s", qPrintable(itm.key()));
751  m_audioOutputInfos.erase(itm++);
752  }
753  else
754  {
755  ++itm;
756  }
757  }
758 }
759 
761 {
762  QMap<QString, InputDeviceInfo>::const_iterator it = m_audioInputInfos.begin();
763 
764  for (; it != m_audioInputInfos.end(); ++it)
765  {
766  qDebug() << "AudioDeviceManager::debugAudioInputInfos:"
767  << " name: " << it.key()
768  << " sampleRate: " << it.value().sampleRate
769  << " volume: " << it.value().volume;
770  }
771 }
772 
774 {
775  QMap<QString, OutputDeviceInfo>::const_iterator it = m_audioOutputInfos.begin();
776 
777  for (; it != m_audioOutputInfos.end(); ++it)
778  {
779  qDebug() << "AudioDeviceManager::debugAudioOutputInfos:"
780  << " name: " << it.key()
781  << " sampleRate: " << it.value().sampleRate
782  << " udpAddress: " << it.value().udpAddress
783  << " udpPort: " << it.value().udpPort
784  << " copyToUDP: " << it.value().copyToUDP
785  << " udpUseRTP: " << it.value().udpUseRTP
786  << " udpChannelMode: " << (int) it.value().udpChannelMode
787  << " udpChannelCodec: " << (int) it.value().udpChannelCodec
788  << " decimationFactor: " << it.value().udpDecimationFactor;
789  }
790 }
static const QString m_defaultDeviceName
void setUdpChannelMode(UDPChannelMode udpChannelMode)
QList< QAudioDeviceInfo > m_inputDevicesInfo
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
int getOutputSampleRate(int outputDeviceIndex=-1)
void startAudioOutput(int outputDeviceIndex)
QMap< QString, InputDeviceInfo > m_audioInputInfos
audio device name to audio input device info
static const quint16 m_defaultUDPPort
static const QString m_defaultUDPAddress
QMap< int, QList< MessageQueue * > > m_inputDeviceSourceMessageQueues
sink message queues attached to device
int getInputSampleRate(int inputDeviceIndex=-1)
void serializeOutputMap(QByteArray &data) const
unsigned int getRate() const
Definition: audiooutput.h:65
void outputInfosCleanup()
Remove output info from map for output devices not present.
int getOutputDeviceIndex(const QString &deviceName) const
bool deserialize(const QByteArray &data)
QByteArray serialize() const
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
void stopAudioOutput(int outputDeviceIndex)
void writeBlob(quint32 id, const QByteArray &value)
void setUdpCopyToUDP(bool copyToUDP)
bool start(int device, int rate)
Definition: audiooutput.cpp:54
void deserializeOutputMap(QByteArray &data)
AudioOutput::UDPChannelCodec udpChannelCodec
void debugAudioInputInfos() const
void deserializeInputMap(QByteArray &data)
bool isValid() const
unsigned int uint32_t
Definition: rtptypes_win.h:46
void addAudioSource(AudioFifo *audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex=-1)
Add an audio source.
void setUdpDecimation(uint32_t decimation)
bool getInputDeviceName(int inputDeviceIndex, QString &deviceName) const
void setOutputDeviceInfo(int outputDeviceIndex, const OutputDeviceInfo &deviceInfo)
void stopAudioInput(int inputDeviceIndex)
QMap< int, AudioInput * > m_audioInputs
audio device index to audio input map (index -1 is default device)
void setUdpChannelFormat(UDPChannelCodec udpChannelCodec, bool stereo, int sampleRate)
bool readBlob(quint32 id, QByteArray *result, const QByteArray &def=QByteArray()) const
void serializeInputMap(QByteArray &data) const
QMap< int, QList< MessageQueue * > > m_outputDeviceSinkMessageQueues
sink message queues attached to device
QMap< AudioFifo *, MessageQueue * > m_audioFifoToSinkMessageQueues
audio sink FIFO to attached sink message queue
bool getInputDeviceInfo(const QString &deviceName, InputDeviceInfo &deviceInfo) const
void inputInfosCleanup()
Remove input info from map for input devices not present.
QDataStream & operator>>(QDataStream &ds, AudioDeviceManager::InputDeviceInfo &info)
int32_t i
Definition: decimators.h:244
bool start(int device, int rate)
Definition: audioinput.cpp:49
bool getOutputDeviceInfo(const QString &deviceName, OutputDeviceInfo &deviceInfo) const
QDataStream & operator<<(QDataStream &ds, const AudioDeviceManager::InputDeviceInfo &info)
bool getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const
Linear 16 bit (no codec)
Definition: audiooutput.h:47
quint32 getVersion() const
void unsetInputDeviceInfo(int inputDeviceIndex)
void stop()
Definition: audioinput.cpp:121
QMap< AudioFifo *, MessageQueue * > m_audioFifoToSourceMessageQueues
audio source FIFO to attached source message queue
QMap< AudioFifo *, int > m_audioSinkFifos
AudioOutput::UDPChannelMode udpChannelMode
void setVolume(float volume)
Definition: audioinput.h:47
void setUdpDestination(const QString &address, uint16_t port)
static const unsigned int m_defaultAudioSampleRate
void startAudioInput(int inputDeviceIndex)
void setInputDeviceInfo(int inputDeviceIndex, const InputDeviceInfo &deviceInfo)
int getInputDeviceIndex(const QString &deviceName) const
void setUdpUseRTP(bool useRTP)
QMap< AudioFifo *, int > m_audioSourceFifos
void debugAudioOutputInfos() const
QMap< int, AudioOutput * > m_audioOutputs
audio device index to audio output map (index -1 is default device)
uint getRate() const
Definition: audioinput.h:45
static const float m_defaultAudioInputVolume
void unsetOutputDeviceInfo(int outputDeviceIndex)
const QByteArray & final()
QMap< QString, OutputDeviceInfo > m_audioOutputInfos
audio device name to audio output info
void removeAudioSource(AudioFifo *audioFifo)
Remove an audio source.
QList< QAudioDeviceInfo > m_outputDevicesInfo