/* Copyright (C) 2007-2008 Tanguy Krotoff Copyright (C) 2008 Lukas Durfina Copyright (C) 2009 Fathi Boudra Copyright (C) 2013-2018 Harald Sitter This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "audiooutput.h" #include #include #include "backend.h" #include "utils/debug.h" #include "devicemanager.h" #include "mediaobject.h" #include "media.h" namespace Phonon { namespace VLC { AudioOutput::AudioOutput(QObject *parent) : QObject(parent) , m_volume(0.75) , m_explicitVolume(false) , m_muted(false) , m_category(Phonon::NoCategory) { } AudioOutput::~AudioOutput() { } static libvlc_media_player_role categoryToRole(Category category) { switch(category) { case NoCategory: return libvlc_role_None; case NotificationCategory: return libvlc_role_Notification; case MusicCategory: return libvlc_role_Music; case VideoCategory: return libvlc_role_Video; case CommunicationCategory: return libvlc_role_Communication; case GameCategory: return libvlc_role_Game; case AccessibilityCategory: return libvlc_role_Accessibility; } return libvlc_role_None; } void AudioOutput::handleConnectToMediaObject(MediaObject *mediaObject) { Q_UNUSED(mediaObject); setOutputDeviceImplementation(); if (!PulseSupport::getInstance()->isActive()) { // Rely on libvlc for updates if PASupport is not active connect(m_player, SIGNAL(mutedChanged(bool)), this, SLOT(onMutedChanged(bool))); connect(m_player, SIGNAL(volumeChanged(float)), this, SLOT(onVolumeChanged(float))); applyVolume(); } libvlc_media_player_set_role(*m_player, categoryToRole(m_category)); } void AudioOutput::handleAddToMedia(Media *media) { media->addOption(":audio"); PulseSupport *pulse = PulseSupport::getInstance(); if (pulse && pulse->isActive()) { pulse->setupStreamEnvironment(m_streamUuid); } } qreal AudioOutput::volume() const { return m_volume; } void AudioOutput::setVolume(qreal volume) { if (m_player) { debug() << "async setting of volume to" << volume; m_volume = volume; m_explicitVolume = true; applyVolume(); } } void AudioOutput::setMuted(bool mute) { if (mute == m_player->mute()) { // Make sure we actually have propagated the mutness into the frontend. onMutedChanged(mute); return; } m_player->setMute(mute); } void AudioOutput::setCategory(Category category) { m_category = category; } int AudioOutput::outputDevice() const { return m_device.index(); } bool AudioOutput::setOutputDevice(int deviceIndex) { const AudioOutputDevice device = AudioOutputDevice::fromIndex(deviceIndex); if (!device.isValid()) { error() << Q_FUNC_INFO << "Unable to find the output device with index" << deviceIndex; return false; } return setOutputDevice(device); } bool AudioOutput::setOutputDevice(const AudioOutputDevice &newDevice) { debug() << Q_FUNC_INFO; if (!newDevice.isValid()) { error() << "Invalid audio output device"; return false; } if (newDevice == m_device) return true; m_device = newDevice; if (m_player) { setOutputDeviceImplementation(); } return true; } void AudioOutput::setStreamUuid(QString uuid) { DEBUG_BLOCK; debug() << uuid; m_streamUuid = uuid; } void AudioOutput::setOutputDeviceImplementation() { Q_ASSERT(m_player); // VLC 2.2 has the PulseSupport overrides always disabled because of // incompatibility. Also see backend.cpp for more detals. // To get access to the correct activity state we need to temporarily // enable pulse and then disable it again. This is necessary because isActive // is in fact isActive&isEnabled............. PulseSupport::getInstance()->enable(true); const bool pulseActive = PulseSupport::getInstance()->isActive(); PulseSupport::getInstance()->enable(false); if (pulseActive) { m_player->setAudioOutput("pulse"); debug() << "Setting aout to pulse"; return; } const QVariant dalProperty = m_device.property("deviceAccessList"); if (!dalProperty.isValid()) { error() << "Device" << m_device.property("name") << "has no access list"; return; } const DeviceAccessList deviceAccessList = dalProperty.value(); if (deviceAccessList.isEmpty()) { error() << "Device" << m_device.property("name") << "has an empty access list"; return; } // ### we're not trying the whole access list (could mean same device on different soundsystems) const DeviceAccess &firstDeviceAccess = deviceAccessList.first(); QByteArray soundSystem = firstDeviceAccess.first; debug() << "Setting output soundsystem to" << soundSystem; m_player->setAudioOutput(soundSystem); QByteArray deviceName = firstDeviceAccess.second.toLatin1(); if (!deviceName.isEmpty()) { // print the name as possibly messed up by toLatin1() to see conversion problems debug() << "Setting output device to" << deviceName << '(' << m_device.property("name") << ')'; m_player->setAudioOutputDevice(soundSystem, deviceName); } } void AudioOutput::applyVolume() { if (m_player && m_explicitVolume) { const int preVolume = m_player->audioVolume(); const int newVolume = m_volume * 100; m_player->setAudioVolume(newVolume); debug() << "Volume changed from" << preVolume << "to" << newVolume; } } void AudioOutput::onMutedChanged(bool mute) { m_muted = mute; emit mutedChanged(mute); } void AudioOutput::onVolumeChanged(float volume) { m_volume = volume; emit volumeChanged(volume); } } } // Namespace Phonon::VLC