/////////////////////////////////////////////////////////////////////////////////// // 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 // // // // 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 . // /////////////////////////////////////////////////////////////////////////////////// #include "audio/audiodevicemanager.h" #include "util/simpleserializer.h" #include const float AudioDeviceManager::m_defaultAudioInputVolume = 0.15f; 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; } AudioDeviceManager::AudioDeviceManager() { m_inputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); m_outputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); } AudioDeviceManager::~AudioDeviceManager() { QMap::iterator it = m_audioOutputs.begin(); for (; it != m_audioOutputs.end(); ++it) { delete(*it); } } bool AudioDeviceManager::getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const { if (outputDeviceIndex < 0) { deviceName = "System default device"; 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) { deviceName = "System default device"; return true; } else { if (inputDeviceIndex < m_inputDevicesInfo.size()) { deviceName = m_inputDevicesInfo[inputDeviceIndex].deviceName(); return true; } else { return false; } } } 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); *stream << m_audioOutputSampleRates; 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); readStream >> m_audioOutputSampleRates; } void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, int outputDeviceIndex) { qDebug("AudioDeviceManager::addAudioSink: %d: %p", outputDeviceIndex, audioFifo); if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) { m_audioOutputs[outputDeviceIndex] = new AudioOutput(); } if (m_audioOutputs[outputDeviceIndex]->getNbFifos() == 0) { startAudioOutput(outputDeviceIndex); } if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end()) // new FIFO { m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo); } 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 } } m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO } 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); if (m_audioOutputs[audioOutputDeviceIndex]->getNbFifos() == 0) { stopAudioOutput(audioOutputDeviceIndex); } m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO } void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, int inputDeviceIndex) { qDebug("AudioDeviceManager::addAudioSource: %d: %p", inputDeviceIndex, audioFifo); if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { m_audioInputs[inputDeviceIndex] = new AudioInput(); } if (m_audioInputs[inputDeviceIndex]->getNbFifos() == 0) { 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 } 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); if (m_audioInputs[audioInputDeviceIndex]->getNbFifos() == 0) { stopAudioInput(audioInputDeviceIndex); } m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO } void AudioDeviceManager::startAudioOutput(int outputDeviceIndex) { unsigned int sampleRate; QString deviceName; if (getOutputDeviceName(outputDeviceIndex, deviceName)) { if (m_audioOutputSampleRates.find(deviceName) == m_audioOutputSampleRates.end()) { sampleRate = m_defaultAudioSampleRate; } else { sampleRate = m_audioOutputSampleRates[deviceName]; } m_audioOutputs[outputDeviceIndex]->start(outputDeviceIndex, sampleRate); m_audioOutputSampleRates[deviceName] = m_audioOutputs[outputDeviceIndex]->getRate(); // update with actual rate } 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; } else { qWarning("AudioDeviceManager::startAudioInput: unknown device index %d", inputDeviceIndex); } } void AudioDeviceManager::stopAudioInput(int inputDeviceIndex) { m_audioInputs[inputDeviceIndex]->stop(); } void AudioDeviceManager::debugAudioInputInfos() const { QMap::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 { QMap::const_iterator it = m_audioOutputSampleRates.begin(); for (; it != m_audioOutputSampleRates.end(); ++it) { qDebug() << "AudioDeviceManager::debugAudioOutputInfos:" << " name: " << it.key() << " sampleRate: " << it.value(); } }