| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2017 F4EXB                                                      //
 | 
					
						
							|  |  |  | // written by Edouard Griffiths                                                  //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:32:15 +02:00
										 |  |  | // (at your option) any later version.                                           //
 | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "audio/audiodevicemanager.h"
 | 
					
						
							|  |  |  | #include "util/simpleserializer.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | #include "util/messagequeue.h"
 | 
					
						
							|  |  |  | #include "dsp/dspcommands.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  | #include <QDataStream>
 | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | #include <QSet>
 | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-30 19:01:09 +02:00
										 |  |  | const float AudioDeviceManager::m_defaultAudioInputVolume = 1.0f; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  | const QString AudioDeviceManager::m_defaultUDPAddress = "127.0.0.1"; | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | const QString AudioDeviceManager::m_defaultDeviceName = "System default device"; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ds << info.sampleRate << info.volume; | 
					
						
							|  |  |  |     return ds; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::InputDeviceInfo& info) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ds >> info.sampleRate >> info.volume; | 
					
						
							|  |  |  |     return ds; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  | QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::OutputDeviceInfo& info) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-02-13 07:53:38 +01:00
										 |  |  |     ds << info.sampleRate | 
					
						
							|  |  |  |         << info.udpAddress | 
					
						
							|  |  |  |         << info.udpPort | 
					
						
							|  |  |  |         << info.copyToUDP | 
					
						
							|  |  |  |         << info.udpUseRTP | 
					
						
							|  |  |  |         << (int) info.udpChannelMode | 
					
						
							| 
									
										
										
										
											2019-02-14 08:31:18 +01:00
										 |  |  |         << (int) info.udpChannelCodec | 
					
						
							| 
									
										
										
										
											2019-02-15 07:57:16 +01:00
										 |  |  |         << info.udpDecimationFactor; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     return ds; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::OutputDeviceInfo& info) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-26 21:10:09 +02:00
										 |  |  |     int intChannelMode; | 
					
						
							| 
									
										
										
										
											2019-02-13 07:53:38 +01:00
										 |  |  |     int intChannelCodec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ds >> info.sampleRate | 
					
						
							|  |  |  |         >> info.udpAddress | 
					
						
							|  |  |  |         >> info.udpPort | 
					
						
							|  |  |  |         >> info.copyToUDP | 
					
						
							|  |  |  |         >> info.udpUseRTP | 
					
						
							|  |  |  |         >> intChannelMode | 
					
						
							| 
									
										
										
										
											2019-02-14 08:31:18 +01:00
										 |  |  |         >> intChannelCodec | 
					
						
							| 
									
										
										
										
											2019-02-15 07:57:16 +01:00
										 |  |  |         >> info.udpDecimationFactor; | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |     info.udpChannelMode = (AudioOutputDevice::UDPChannelMode) intChannelMode; | 
					
						
							|  |  |  |     info.udpChannelCodec = (AudioOutputDevice::UDPChannelCodec) intChannelCodec; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     return ds; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | AudioDeviceManager::AudioDeviceManager() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-06 23:01:07 +02:00
										 |  |  |     qDebug("AudioDeviceManager::AudioDeviceManager: scan input devices"); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     m_inputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); | 
					
						
							| 
									
										
										
										
											2018-10-06 22:34:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < m_inputDevicesInfo.size(); i++) { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::AudioDeviceManager: input device #%d: %s", i, qPrintable(m_inputDevicesInfo[i].deviceName())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 23:01:07 +02:00
										 |  |  |     qDebug("AudioDeviceManager::AudioDeviceManager: scan output devices"); | 
					
						
							|  |  |  |     m_outputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 22:34:48 +02:00
										 |  |  |     for (int i = 0; i < m_outputDevicesInfo.size(); i++) { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::AudioDeviceManager: output device #%d: %s", i, qPrintable(m_outputDevicesInfo[i].deviceName())); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_defaultInputStarted = false; | 
					
						
							|  |  |  |     m_defaultOutputStarted = false; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioDeviceManager::~AudioDeviceManager() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |     QMap<int, AudioOutputDevice*>::iterator it = m_audioOutputs.begin(); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (; it != m_audioOutputs.end(); ++it) { | 
					
						
							|  |  |  |         delete(*it); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AudioDeviceManager::getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (outputDeviceIndex < 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         deviceName = m_defaultDeviceName; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (outputDeviceIndex < m_outputDevicesInfo.size()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             deviceName = m_outputDevicesInfo[outputDeviceIndex].deviceName(); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AudioDeviceManager::getInputDeviceName(int inputDeviceIndex, QString &deviceName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (inputDeviceIndex < 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         deviceName = m_defaultDeviceName; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (inputDeviceIndex < m_inputDevicesInfo.size()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             deviceName = m_inputDevicesInfo[inputDeviceIndex].deviceName(); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-26 18:41:09 +02:00
										 |  |  | int AudioDeviceManager::getOutputDeviceIndex(const QString &deviceName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (int i = 0; i < m_outputDevicesInfo.size(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         //qDebug("AudioDeviceManager::getOutputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(m_outputDevicesInfo[i].deviceName()));
 | 
					
						
							|  |  |  |         if (deviceName == m_outputDevicesInfo[i].deviceName()) { | 
					
						
							|  |  |  |             return i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return -1; // system default
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AudioDeviceManager::getInputDeviceIndex(const QString &deviceName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (int i = 0; i < m_inputDevicesInfo.size(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         //qDebug("AudioDeviceManager::getInputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(m_inputDevicesInfo[i].deviceName()));
 | 
					
						
							|  |  |  |         if (deviceName == m_inputDevicesInfo[i].deviceName()) { | 
					
						
							|  |  |  |             return i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return -1; // system default
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | void AudioDeviceManager::resetToDefaults() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QByteArray AudioDeviceManager::serialize() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::serialize"); | 
					
						
							|  |  |  |     debugAudioInputInfos(); | 
					
						
							|  |  |  |     debugAudioOutputInfos(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SimpleSerializer s(1); | 
					
						
							|  |  |  |     QByteArray data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     serializeInputMap(data); | 
					
						
							|  |  |  |     s.writeBlob(1, data); | 
					
						
							|  |  |  |     serializeOutputMap(data); | 
					
						
							|  |  |  |     s.writeBlob(2, data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return s.final(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::serializeInputMap(QByteArray& data) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); | 
					
						
							|  |  |  |     *stream << m_audioInputInfos; | 
					
						
							|  |  |  |     delete stream; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::serializeOutputMap(QByteArray& data) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     *stream << m_audioOutputInfos; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     delete stream; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AudioDeviceManager::deserialize(const QByteArray& data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::deserialize"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SimpleDeserializer d(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(!d.isValid()) { | 
					
						
							|  |  |  |         resetToDefaults(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(d.getVersion() == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QByteArray data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         d.readBlob(1, &data); | 
					
						
							|  |  |  |         deserializeInputMap(data); | 
					
						
							|  |  |  |         d.readBlob(2, &data); | 
					
						
							|  |  |  |         deserializeOutputMap(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         debugAudioInputInfos(); | 
					
						
							|  |  |  |         debugAudioOutputInfos(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         resetToDefaults(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::deserializeInputMap(QByteArray& data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDataStream readStream(&data, QIODevice::ReadOnly); | 
					
						
							|  |  |  |     readStream >> m_audioInputInfos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::deserializeOutputMap(QByteArray& data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDataStream readStream(&data, QIODevice::ReadOnly); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     readStream >> m_audioOutputInfos; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  | void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex) | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::addAudioSink: %d: %p", outputDeviceIndex, audioFifo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) { | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |         m_audioOutputs[outputDeviceIndex] = new AudioOutputDevice(); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  |     if ((m_audioOutputs[outputDeviceIndex]->getNbFifos() == 0) && | 
					
						
							|  |  |  |        ((outputDeviceIndex != -1) || !m_defaultOutputStarted)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         startAudioOutput(outputDeviceIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end()) // new FIFO
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo); | 
					
						
							| 
									
										
										
										
											2018-03-26 18:41:09 +02:00
										 |  |  |         m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO
 | 
					
						
							|  |  |  |         m_audioFifoToSinkMessageQueues[audioFifo] = sampleSinkMessageQueue; | 
					
						
							|  |  |  |         m_outputDeviceSinkMessageQueues[outputDeviceIndex].append(sampleSinkMessageQueue); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int audioOutputDeviceIndex = m_audioSinkFifos[audioFifo]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (audioOutputDeviceIndex != outputDeviceIndex) // change of audio device
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             removeAudioSink(audioFifo); // remove from current
 | 
					
						
							|  |  |  |             m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo); // add to new
 | 
					
						
							| 
									
										
										
										
											2018-03-26 18:41:09 +02:00
										 |  |  |             m_audioSinkFifos[audioFifo] = outputDeviceIndex; // new index
 | 
					
						
							|  |  |  |             m_outputDeviceSinkMessageQueues[audioOutputDeviceIndex].removeOne(sampleSinkMessageQueue); | 
					
						
							|  |  |  |             m_outputDeviceSinkMessageQueues[outputDeviceIndex].append(sampleSinkMessageQueue); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::removeAudioSink: %p", audioFifo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::removeAudioSink: audio FIFO %p not found", audioFifo); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int audioOutputDeviceIndex = m_audioSinkFifos[audioFifo]; | 
					
						
							|  |  |  |     m_audioOutputs[audioOutputDeviceIndex]->removeFifo(audioFifo); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  |     if ((audioOutputDeviceIndex != -1) && (m_audioOutputs[audioOutputDeviceIndex]->getNbFifos() == 0)) { | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         stopAudioOutput(audioOutputDeviceIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO
 | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     m_outputDeviceSinkMessageQueues[audioOutputDeviceIndex].removeOne(m_audioFifoToSinkMessageQueues[audioFifo]); | 
					
						
							|  |  |  |     m_audioFifoToSinkMessageQueues.remove(audioFifo); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  | void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex) | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::addAudioSource: %d: %p", inputDeviceIndex, audioFifo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { | 
					
						
							| 
									
										
										
										
											2020-11-12 20:30:34 +01:00
										 |  |  |         m_audioInputs[inputDeviceIndex] = new AudioInputDevice(); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  |     if ((m_audioInputs[inputDeviceIndex]->getNbFifos() == 0) && | 
					
						
							|  |  |  |        ((inputDeviceIndex != -1) || !m_defaultInputStarted)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         startAudioInput(inputDeviceIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioSourceFifos.find(audioFifo) == m_audioSourceFifos.end()) // new FIFO
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_audioInputs[inputDeviceIndex]->addFifo(audioFifo); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int audioInputDeviceIndex = m_audioSourceFifos[audioFifo]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (audioInputDeviceIndex != inputDeviceIndex) // change of audio device
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             removeAudioSource(audioFifo); // remove from current
 | 
					
						
							|  |  |  |             m_audioInputs[inputDeviceIndex]->addFifo(audioFifo); // add to new
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioSourceFifos[audioFifo] = inputDeviceIndex; // register audio FIFO
 | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     m_audioFifoToSourceMessageQueues[audioFifo] = sampleSourceMessageQueue; | 
					
						
							|  |  |  |     m_outputDeviceSinkMessageQueues[inputDeviceIndex].append(sampleSourceMessageQueue); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::removeAudioSource: %p", audioFifo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioSourceFifos.find(audioFifo) == m_audioSourceFifos.end()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::removeAudioSource: audio FIFO %p not found", audioFifo); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int audioInputDeviceIndex = m_audioSourceFifos[audioFifo]; | 
					
						
							|  |  |  |     m_audioInputs[audioInputDeviceIndex]->removeFifo(audioFifo); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  |     if ((audioInputDeviceIndex != -1) && (m_audioInputs[audioInputDeviceIndex]->getNbFifos() == 0)) { | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         stopAudioInput(audioInputDeviceIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO
 | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     m_inputDeviceSourceMessageQueues[audioInputDeviceIndex].removeOne(m_audioFifoToSourceMessageQueues[audioFifo]); | 
					
						
							|  |  |  |     m_audioFifoToSourceMessageQueues.remove(audioFifo); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::startAudioOutput(int outputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned int sampleRate; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     QString udpAddress; | 
					
						
							|  |  |  |     quint16 udpPort; | 
					
						
							|  |  |  |     bool copyAudioToUDP; | 
					
						
							|  |  |  |     bool udpUseRTP; | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |     AudioOutputDevice::UDPChannelMode udpChannelMode; | 
					
						
							|  |  |  |     AudioOutputDevice::UDPChannelCodec udpChannelCodec; | 
					
						
							| 
									
										
										
										
											2019-02-14 08:31:18 +01:00
										 |  |  |     uint32_t decimationFactor; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getOutputDeviceName(outputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |         if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end()) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |             sampleRate = m_defaultAudioSampleRate; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |             udpAddress = m_defaultUDPAddress; | 
					
						
							|  |  |  |             udpPort = m_defaultUDPPort; | 
					
						
							|  |  |  |             copyAudioToUDP = false; | 
					
						
							|  |  |  |             udpUseRTP = false; | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |             udpChannelMode = AudioOutputDevice::UDPChannelLeft; | 
					
						
							|  |  |  |             udpChannelCodec = AudioOutputDevice::UDPCodecL16; | 
					
						
							| 
									
										
										
										
											2019-02-14 08:31:18 +01:00
										 |  |  |             decimationFactor = 1; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             sampleRate = m_audioOutputInfos[deviceName].sampleRate; | 
					
						
							|  |  |  |             udpAddress = m_audioOutputInfos[deviceName].udpAddress; | 
					
						
							|  |  |  |             udpPort = m_audioOutputInfos[deviceName].udpPort; | 
					
						
							|  |  |  |             copyAudioToUDP = m_audioOutputInfos[deviceName].copyToUDP; | 
					
						
							|  |  |  |             udpUseRTP = m_audioOutputInfos[deviceName].udpUseRTP; | 
					
						
							| 
									
										
										
										
											2018-03-26 21:10:09 +02:00
										 |  |  |             udpChannelMode = m_audioOutputInfos[deviceName].udpChannelMode; | 
					
						
							| 
									
										
										
										
											2019-02-13 07:53:38 +01:00
										 |  |  |             udpChannelCodec = m_audioOutputInfos[deviceName].udpChannelCodec; | 
					
						
							| 
									
										
										
										
											2019-02-15 07:57:16 +01:00
										 |  |  |             decimationFactor = m_audioOutputInfos[deviceName].udpDecimationFactor; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_audioOutputs[outputDeviceIndex]->start(outputDeviceIndex, sampleRate); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |         m_audioOutputInfos[deviceName].sampleRate = m_audioOutputs[outputDeviceIndex]->getRate(); // update with actual rate
 | 
					
						
							|  |  |  |         m_audioOutputInfos[deviceName].udpAddress = udpAddress; | 
					
						
							|  |  |  |         m_audioOutputInfos[deviceName].udpPort = udpPort; | 
					
						
							|  |  |  |         m_audioOutputInfos[deviceName].copyToUDP = copyAudioToUDP; | 
					
						
							|  |  |  |         m_audioOutputInfos[deviceName].udpUseRTP = udpUseRTP; | 
					
						
							| 
									
										
										
										
											2018-03-26 21:10:09 +02:00
										 |  |  |         m_audioOutputInfos[deviceName].udpChannelMode = udpChannelMode; | 
					
						
							| 
									
										
										
										
											2019-02-13 07:53:38 +01:00
										 |  |  |         m_audioOutputInfos[deviceName].udpChannelCodec = udpChannelCodec; | 
					
						
							| 
									
										
										
										
											2019-02-15 07:57:16 +01:00
										 |  |  |         m_audioOutputInfos[deviceName].udpDecimationFactor = decimationFactor; | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  |         m_defaultOutputStarted = (outputDeviceIndex == -1); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::startAudioOutput: unknown device index %d", outputDeviceIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::stopAudioOutput(int outputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_audioOutputs[outputDeviceIndex]->stop(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::startAudioInput(int inputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned int sampleRate; | 
					
						
							|  |  |  |     float volume; | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getInputDeviceName(inputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_audioInputInfos.find(deviceName) == m_audioInputInfos.end()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             sampleRate = m_defaultAudioSampleRate; | 
					
						
							|  |  |  |             volume = m_defaultAudioInputVolume; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             sampleRate = m_audioInputInfos[deviceName].sampleRate; | 
					
						
							|  |  |  |             volume = m_audioInputInfos[deviceName].volume; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_audioInputs[inputDeviceIndex]->start(inputDeviceIndex, sampleRate); | 
					
						
							|  |  |  |         m_audioInputs[inputDeviceIndex]->setVolume(volume); | 
					
						
							|  |  |  |         m_audioInputInfos[deviceName].sampleRate = m_audioInputs[inputDeviceIndex]->getRate(); | 
					
						
							|  |  |  |         m_audioInputInfos[deviceName].volume = volume; | 
					
						
							| 
									
										
										
										
											2020-01-25 19:02:33 +01:00
										 |  |  |         m_defaultInputStarted = (inputDeviceIndex == -1); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::startAudioInput: unknown device index %d", inputDeviceIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::stopAudioInput(int inputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_audioInputs[inputDeviceIndex]->stop(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | bool AudioDeviceManager::getInputDeviceInfo(const QString& deviceName, InputDeviceInfo& deviceInfo) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_audioInputInfos.find(deviceName) == m_audioInputInfos.end()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         deviceInfo = m_audioInputInfos[deviceName]; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AudioDeviceManager::getOutputDeviceInfo(const QString& deviceName, OutputDeviceInfo& deviceInfo) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         deviceInfo = m_audioOutputInfos[deviceName]; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AudioDeviceManager::getInputSampleRate(int inputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getInputDeviceName(inputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::getInputSampleRate: unknown device index %d", inputDeviceIndex); | 
					
						
							|  |  |  |         return m_defaultAudioSampleRate; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InputDeviceInfo deviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getInputDeviceInfo(deviceName, deviceInfo)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::getInputSampleRate: unknown device %s", qPrintable(deviceName)); | 
					
						
							|  |  |  |         return m_defaultAudioSampleRate; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-05-15 19:37:50 +02:00
										 |  |  |         if (deviceInfo.sampleRate > 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return deviceInfo.sampleRate; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug("AudioDeviceManager::getInputSampleRate: device %s has invalid sample rate", qPrintable(deviceName)); | 
					
						
							|  |  |  |             return m_defaultAudioSampleRate; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AudioDeviceManager::getOutputSampleRate(int outputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getOutputDeviceName(outputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::getOutputSampleRate: unknown device index %d", outputDeviceIndex); | 
					
						
							|  |  |  |         return m_defaultAudioSampleRate; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OutputDeviceInfo deviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getOutputDeviceInfo(deviceName, deviceInfo)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::getOutputSampleRate: unknown device %s", qPrintable(deviceName)); | 
					
						
							|  |  |  |         return m_defaultAudioSampleRate; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-05-15 19:37:50 +02:00
										 |  |  |         if (deviceInfo.sampleRate > 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return deviceInfo.sampleRate; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug("AudioDeviceManager::getOutputSampleRate: device %s has invalid sample rate", qPrintable(deviceName)); | 
					
						
							|  |  |  |             return m_defaultAudioSampleRate; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::setInputDeviceInfo(int inputDeviceIndex, const InputDeviceInfo& deviceInfo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getInputDeviceName(inputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::setInputDeviceInfo: unknown device index %d", inputDeviceIndex); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InputDeviceInfo oldDeviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getInputDeviceInfo(deviceName, oldDeviceInfo)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::setInputDeviceInfo: unknown device %s", qPrintable(deviceName)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioInputInfos[deviceName] = deviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { // no FIFO registered yet hence no audio input has been allocated yet
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 20:30:34 +01:00
										 |  |  |     AudioInputDevice *audioInput = m_audioInputs[inputDeviceIndex]; | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (oldDeviceInfo.sampleRate != deviceInfo.sampleRate) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         audioInput->stop(); | 
					
						
							|  |  |  |         audioInput->start(inputDeviceIndex, deviceInfo.sampleRate); | 
					
						
							|  |  |  |         m_audioInputInfos[deviceName].sampleRate = audioInput->getRate(); // store actual sample rate
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send message to attached channels
 | 
					
						
							|  |  |  |         QList<MessageQueue *>::const_iterator it = m_inputDeviceSourceMessageQueues[inputDeviceIndex].begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; it != m_inputDeviceSourceMessageQueues[inputDeviceIndex].end(); ++it) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-07-30 21:27:48 +02:00
										 |  |  |             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioInputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioInput); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |             (*it)->push(msg); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     audioInput->setVolume(deviceInfo.volume); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::setOutputDeviceInfo(int outputDeviceIndex, const OutputDeviceInfo& deviceInfo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getOutputDeviceName(outputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::setOutputDeviceInfo: unknown device index %d", outputDeviceIndex); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OutputDeviceInfo oldDeviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getOutputDeviceInfo(deviceName, oldDeviceInfo)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-05-29 00:14:45 +02:00
										 |  |  |         qInfo("AudioDeviceManager::setOutputDeviceInfo: unknown device %s", qPrintable(deviceName)); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioOutputInfos[deviceName] = deviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 00:14:45 +02:00
										 |  |  |     if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::setOutputDeviceInfo: index: %d device: %s no FIFO registered yet hence no audio output has been allocated yet", | 
					
						
							|  |  |  |                 outputDeviceIndex, qPrintable(deviceName)); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |     AudioOutputDevice *audioOutput = m_audioOutputs[outputDeviceIndex]; | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (oldDeviceInfo.sampleRate != deviceInfo.sampleRate) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         audioOutput->stop(); | 
					
						
							|  |  |  |         audioOutput->start(outputDeviceIndex, deviceInfo.sampleRate); | 
					
						
							|  |  |  |         m_audioOutputInfos[deviceName].sampleRate = audioOutput->getRate(); // store actual sample rate
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send message to attached channels
 | 
					
						
							|  |  |  |         QList<MessageQueue *>::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-07-30 21:27:48 +02:00
										 |  |  |             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioOutput); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |             (*it)->push(msg); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     audioOutput->setUdpCopyToUDP(deviceInfo.copyToUDP); | 
					
						
							|  |  |  |     audioOutput->setUdpDestination(deviceInfo.udpAddress, deviceInfo.udpPort); | 
					
						
							|  |  |  |     audioOutput->setUdpUseRTP(deviceInfo.udpUseRTP); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:09:52 +02:00
										 |  |  |     audioOutput->setUdpChannelMode(deviceInfo.udpChannelMode); | 
					
						
							| 
									
										
										
										
											2020-11-12 22:13:44 +01:00
										 |  |  |     audioOutput->setUdpChannelFormat(deviceInfo.udpChannelCodec, deviceInfo.udpChannelMode == AudioOutputDevice::UDPChannelStereo, deviceInfo.sampleRate); | 
					
						
							| 
									
										
										
										
											2019-02-15 07:57:16 +01:00
										 |  |  |     audioOutput->setUdpDecimation(deviceInfo.udpDecimationFactor); | 
					
						
							| 
									
										
										
										
											2018-05-29 00:14:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     qDebug("AudioDeviceManager::setOutputDeviceInfo: index: %d device: %s updated", | 
					
						
							|  |  |  |             outputDeviceIndex, qPrintable(deviceName)); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::unsetOutputDeviceInfo(int outputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getOutputDeviceName(outputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::unsetOutputDeviceInfo: unknown device index %d", outputDeviceIndex); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OutputDeviceInfo oldDeviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getOutputDeviceInfo(deviceName, oldDeviceInfo)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::unsetOutputDeviceInfo: unregistered device %s", qPrintable(deviceName)); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioOutputInfos.remove(deviceName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) { // no FIFO registered yet hence no audio output has been allocated yet
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stopAudioOutput(outputDeviceIndex); | 
					
						
							|  |  |  |     startAudioOutput(outputDeviceIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (oldDeviceInfo.sampleRate != m_audioOutputInfos[deviceName].sampleRate) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // send message to attached channels
 | 
					
						
							|  |  |  |         QList<MessageQueue *>::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-07-30 21:27:48 +02:00
										 |  |  |             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioOutput); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |             (*it)->push(msg); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::unsetInputDeviceInfo(int inputDeviceIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString deviceName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getInputDeviceName(inputDeviceIndex, deviceName)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning("AudioDeviceManager::unsetInputDeviceInfo: unknown device index %d", inputDeviceIndex); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InputDeviceInfo oldDeviceInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!getInputDeviceInfo(deviceName, oldDeviceInfo)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::unsetInputDeviceInfo: unregistered device %s", qPrintable(deviceName)); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_audioInputInfos.remove(deviceName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { // no FIFO registered yet hence no audio input has been allocated yet
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stopAudioInput(inputDeviceIndex); | 
					
						
							|  |  |  |     startAudioInput(inputDeviceIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (oldDeviceInfo.sampleRate != m_audioInputInfos[deviceName].sampleRate) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // send message to attached channels
 | 
					
						
							|  |  |  |         QList<MessageQueue *>::const_iterator it = m_inputDeviceSourceMessageQueues[inputDeviceIndex].begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; it != m_inputDeviceSourceMessageQueues[inputDeviceIndex].end(); ++it) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-07-30 21:27:48 +02:00
										 |  |  |             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioInputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioInput); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |             (*it)->push(msg); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::inputInfosCleanup() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QSet<QString> deviceNames; | 
					
						
							|  |  |  |     deviceNames.insert(m_defaultDeviceName); | 
					
						
							|  |  |  |     QList<QAudioDeviceInfo>::const_iterator itd = m_inputDevicesInfo.begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 21:25:27 +02:00
										 |  |  |     for (; itd != m_inputDevicesInfo.end(); ++itd) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::inputInfosCleanup: device: %s", qPrintable(itd->deviceName())); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         deviceNames.insert(itd->deviceName()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QMap<QString, InputDeviceInfo>::iterator itm = m_audioInputInfos.begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 21:25:27 +02:00
										 |  |  |     for (; itm != m_audioInputInfos.end();) | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (!deviceNames.contains(itm.key())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug("AudioDeviceManager::inputInfosCleanup: removing key: %s", qPrintable(itm.key())); | 
					
						
							| 
									
										
										
										
											2018-10-06 21:25:27 +02:00
										 |  |  |             m_audioInputInfos.erase(itm++); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ++itm; | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::outputInfosCleanup() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QSet<QString> deviceNames; | 
					
						
							|  |  |  |     deviceNames.insert(m_defaultDeviceName); | 
					
						
							|  |  |  |     QList<QAudioDeviceInfo>::const_iterator itd = m_outputDevicesInfo.begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 21:25:27 +02:00
										 |  |  |     for (; itd != m_outputDevicesInfo.end(); ++itd) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("AudioDeviceManager::outputInfosCleanup: device: %s", qPrintable(itd->deviceName())); | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         deviceNames.insert(itd->deviceName()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QMap<QString, OutputDeviceInfo>::iterator itm = m_audioOutputInfos.begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 21:25:27 +02:00
										 |  |  |     for (; itm != m_audioOutputInfos.end();) | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (!deviceNames.contains(itm.key())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug("AudioDeviceManager::outputInfosCleanup: removing key: %s", qPrintable(itm.key())); | 
					
						
							| 
									
										
										
										
											2018-10-06 21:25:27 +02:00
										 |  |  |             m_audioOutputInfos.erase(itm++); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ++itm; | 
					
						
							| 
									
										
										
										
											2018-03-26 11:55:45 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | void AudioDeviceManager::debugAudioInputInfos() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMap<QString, InputDeviceInfo>::const_iterator it = m_audioInputInfos.begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (; it != m_audioInputInfos.end(); ++it) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "AudioDeviceManager::debugAudioInputInfos:" | 
					
						
							|  |  |  |                 << " name: " << it.key() | 
					
						
							|  |  |  |                 << " sampleRate: " << it.value().sampleRate | 
					
						
							|  |  |  |                 << " volume: " << it.value().volume; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioDeviceManager::debugAudioOutputInfos() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     QMap<QString, OutputDeviceInfo>::const_iterator it = m_audioOutputInfos.begin(); | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |     for (; it != m_audioOutputInfos.end(); ++it) | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "AudioDeviceManager::debugAudioOutputInfos:" | 
					
						
							|  |  |  |                 << " name: " << it.key() | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |                 << " sampleRate: " << it.value().sampleRate | 
					
						
							|  |  |  |                 << " udpAddress: " << it.value().udpAddress | 
					
						
							|  |  |  |                 << " udpPort: " << it.value().udpPort | 
					
						
							|  |  |  |                 << " copyToUDP: " << it.value().copyToUDP | 
					
						
							| 
									
										
										
										
											2018-03-26 21:10:09 +02:00
										 |  |  |                 << " udpUseRTP: " << it.value().udpUseRTP | 
					
						
							| 
									
										
										
										
											2019-02-13 07:53:38 +01:00
										 |  |  |                 << " udpChannelMode: " << (int) it.value().udpChannelMode | 
					
						
							| 
									
										
										
										
											2019-02-14 08:31:18 +01:00
										 |  |  |                 << " udpChannelCodec: " << (int) it.value().udpChannelCodec | 
					
						
							| 
									
										
										
										
											2019-02-15 07:57:16 +01:00
										 |  |  |                 << " decimationFactor: " << it.value().udpDecimationFactor; | 
					
						
							| 
									
										
										
										
											2018-03-25 04:22:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } |