diff options
Diffstat (limited to 'src/plugins/multimedia/gstreamer/common/qgstreameraudiooutput.cpp')
-rw-r--r-- | src/plugins/multimedia/gstreamer/common/qgstreameraudiooutput.cpp | 193 |
1 files changed, 99 insertions, 94 deletions
diff --git a/src/plugins/multimedia/gstreamer/common/qgstreameraudiooutput.cpp b/src/plugins/multimedia/gstreamer/common/qgstreameraudiooutput.cpp index 0c9f84fbc..9cea7fb62 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstreameraudiooutput.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstreameraudiooutput.cpp @@ -1,83 +1,113 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qgstreameraudiooutput_p.h> -#include <qgstreameraudiodevice_p.h> -#include <qaudiodevice.h> -#include <qaudiooutput.h> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include <common/qgstreameraudiooutput_p.h> +#include <audio/qgstreameraudiodevice_p.h> + +#include <QtMultimedia/qaudiodevice.h> +#include <QtMultimedia/qaudiooutput.h> #include <QtCore/qloggingcategory.h> -#include <QtNetwork/qnetworkaccessmanager.h> -#include <QtNetwork/qnetworkreply.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> +#include <utility> -Q_LOGGING_CATEGORY(qLcMediaAudioOutput, "qt.multimedia.audiooutput") +static Q_LOGGING_CATEGORY(qLcMediaAudioOutput, "qt.multimedia.audiooutput") QT_BEGIN_NAMESPACE +QMaybe<QPlatformAudioOutput *> QGstreamerAudioOutput::create(QAudioOutput *parent) +{ + static const auto error = qGstErrorMessageIfElementsNotAvailable( + "audioconvert", "audioresample", "volume", "autoaudiosink"); + if (error) + return *error; + + return new QGstreamerAudioOutput(parent); +} + QGstreamerAudioOutput::QGstreamerAudioOutput(QAudioOutput *parent) - : QObject(parent), - QPlatformAudioOutput(parent), - gstAudioOutput("audioOutput") + : QObject(parent), + QPlatformAudioOutput(parent), + gstAudioOutput(QGstBin::create("audioOutput")), + audioQueue{ + QGstElement::createFromFactory("queue", "audioQueue"), + }, + audioConvert{ + QGstElement::createFromFactory("audioconvert", "audioConvert"), + }, + audioResample{ + QGstElement::createFromFactory("audioresample", "audioResample"), + }, + audioVolume{ + QGstElement::createFromFactory("volume", "volume"), + }, + audioSink{ + QGstElement::createFromFactory("autoaudiosink", "autoAudioSink"), + } { - audioQueue = QGstElement("queue", "audioQueue"); - audioConvert = QGstElement("audioconvert", "audioConvert"); - audioResample = QGstElement("audioresample", "audioResample"); - audioVolume = QGstElement("volume", "volume"); - audioSink = QGstElement("autoaudiosink", "autoAudioSink"); gstAudioOutput.add(audioQueue, audioConvert, audioResample, audioVolume, audioSink); - audioQueue.link(audioConvert, audioResample, audioVolume, audioSink); + qLinkGstElements(audioQueue, audioConvert, audioResample, audioVolume, audioSink); gstAudioOutput.addGhostPad(audioQueue, "sink"); } +QGstElement QGstreamerAudioOutput::createGstElement() +{ + const auto *customDeviceInfo = + dynamic_cast<const QGStreamerCustomAudioDeviceInfo *>(m_audioOutput.handle()); + + if (customDeviceInfo) { + qCDebug(qLcMediaAudioOutput) + << "requesting custom audio sink element: " << customDeviceInfo->id; + + QGstElement element = + QGstBin::createFromPipelineDescription(customDeviceInfo->id, /*name=*/nullptr, + /*ghostUnlinkedPads=*/true); + if (element) + return element; + + qCWarning(qLcMediaAudioOutput) + << "Cannot create audio sink element:" << customDeviceInfo->id; + } + + const QByteArray &id = m_audioOutput.id(); + if constexpr (QT_CONFIG(pulseaudio)) { + QGstElement newSink = QGstElement::createFromFactory("pulsesink", "audiosink"); + if (newSink) { + newSink.set("device", id.constData()); + return newSink; + } else { + qWarning() << "Cannot create pulsesink"; + } + } else if constexpr (QT_CONFIG(alsa)) { + QGstElement newSink = QGstElement::createFromFactory("alsasink", "audiosink"); + if (newSink) { + newSink.set("device", id.constData()); + return newSink; + } else { + qWarning() << "Cannot create alsasink"; + } + } else { + auto *deviceInfo = dynamic_cast<const QGStreamerAudioDeviceInfo *>(m_audioOutput.handle()); + if (deviceInfo && deviceInfo->gstDevice) { + QGstElement element = QGstElement::createFromDevice(deviceInfo->gstDevice, "audiosink"); + if (element) + return element; + } + } + qCWarning(qLcMediaAudioOutput) << "Invalid audio device:" << m_audioOutput.id(); + qCWarning(qLcMediaAudioOutput) + << "Failed to create a gst element for the audio device, using a default audio sink"; + return QGstElement::createFromFactory("autoaudiosink", "audiosink"); +} + QGstreamerAudioOutput::~QGstreamerAudioOutput() { gstAudioOutput.setStateSync(GST_STATE_NULL); } -void QGstreamerAudioOutput::setVolume(float vol) +void QGstreamerAudioOutput::setVolume(float volume) { - audioVolume.set("volume", vol); + audioVolume.set("volume", volume); } void QGstreamerAudioOutput::setMuted(bool muted) @@ -85,49 +115,24 @@ void QGstreamerAudioOutput::setMuted(bool muted) audioVolume.set("mute", muted); } -void QGstreamerAudioOutput::setPipeline(const QGstPipeline &pipeline) -{ - gstPipeline = pipeline; -} - void QGstreamerAudioOutput::setAudioDevice(const QAudioDevice &info) { if (info == m_audioOutput) return; qCDebug(qLcMediaAudioOutput) << "setAudioOutput" << info.description() << info.isNull(); + m_audioOutput = info; - QGstElement newSink; -#if QT_CONFIG(pulseaudio) - auto id = m_audioOutput.id(); - newSink = QGstElement("pulsesink", "audiosink"); - if (!newSink.isNull()) - newSink.set("device", id.constData()); - else - qCWarning(qLcMediaAudioOutput) << "Invalid audio device"; -#else - auto *deviceInfo = static_cast<const QGStreamerAudioDeviceInfo *>(m_audioOutput.handle()); - if (deviceInfo && deviceInfo->gstDevice) - newSink = gst_device_create_element(deviceInfo->gstDevice , "audiosink"); - else - qCWarning(qLcMediaAudioOutput) << "Invalid audio device"; -#endif - - if (newSink.isNull()) { - qCWarning(qLcMediaAudioOutput) << "Failed to create a gst element for the audio device, using a default audio sink"; - newSink = QGstElement("autoaudiosink", "audiosink"); - } + QGstElement newSink = createGstElement(); - audioVolume.staticPad("src").doInIdleProbe([&](){ - audioVolume.unlink(audioSink); - gstAudioOutput.remove(audioSink); - gstAudioOutput.add(newSink); - newSink.syncStateWithParent(); - audioVolume.link(newSink); + QGstPipeline::modifyPipelineWhileNotRunning(gstAudioOutput.getPipeline(), [&] { + qUnlinkGstElements(audioVolume, audioSink); + gstAudioOutput.stopAndRemoveElements(audioSink); + audioSink = std::move(newSink); + gstAudioOutput.add(audioSink); + audioSink.syncStateWithParent(); + qLinkGstElements(audioVolume, audioSink); }); - - audioSink.setStateSync(GST_STATE_NULL); - audioSink = newSink; } QT_END_NAMESPACE |