From 6da5f1039ed113dcf11b0347e6d2dbd5432c3d33 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Sun, 19 Apr 2015 18:17:02 +0200 Subject: Support option for system volume control Add support for direct PulseAudio volume control instead of through MPRIS, which doesn't currently work. Default enabled, added setting to disable. --- daemon/musicmanager.cpp | 184 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 133 insertions(+), 51 deletions(-) (limited to 'daemon/musicmanager.cpp') diff --git a/daemon/musicmanager.cpp b/daemon/musicmanager.cpp index 385abbf..11ff6fd 100644 --- a/daemon/musicmanager.cpp +++ b/daemon/musicmanager.cpp @@ -1,10 +1,11 @@ #include #include #include "musicmanager.h" +#include "settings.h" -MusicManager::MusicManager(WatchConnector *watch, QObject *parent) +MusicManager::MusicManager(WatchConnector *watch, Settings *settings, QObject *parent) : QObject(parent), l(metaObject()->className()), - watch(watch), _watcher(new QDBusServiceWatcher(this)) + watch(watch), _watcher(new QDBusServiceWatcher(this)), _pulseBus(NULL), settings(settings),_maxVolume(0) { QDBusConnection bus = QDBusConnection::sessionBus(); QDBusConnectionInterface *bus_iface = bus.interface(); @@ -33,6 +34,33 @@ MusicManager::MusicManager(WatchConnector *watch, QObject *parent) bus.connect("", "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(handleMprisPropertiesChanged(QString,QMap,QStringList))); + // Locate and connect to the PulseAudio DBus to control system volume + // Look up PulseAudio P2P Bus address + QDBusMessage call = QDBusMessage::createMethodCall("org.PulseAudio1", "/org/pulseaudio/server_lookup1", "org.freedesktop.DBus.Properties", "Get" ); + call << "org.PulseAudio.ServerLookup1" << "Address"; + QDBusReply lookupReply = bus.call(call); + if (lookupReply.isValid()) { + // + qCDebug(l) << "PulseAudio Bus address: " << lookupReply.value().variant().toString(); + _pulseBus = new QDBusConnection(QDBusConnection::connectToPeer(lookupReply.value().variant().toString(), "org.PulseAudio1")); + } + else { + qCDebug(l) << "Cannot find PulseAudio Bus address, cannot control system volume."; + } + + // Query max volume + call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Get"); + call << "com.Meego.MainVolume2" << "StepCount"; + QDBusReply volumeMaxReply = _pulseBus->call(call); + if (volumeMaxReply.isValid()) { + _maxVolume = volumeMaxReply.value().variant().toUInt(); + qCDebug(l) << "Max volume: " << _maxVolume; + } + else { + qCWarning(l) << "Could not read volume max, cannot adjust volume: " << volumeMaxReply.error().message(); + } + // Now set up the Pebble endpoint handler for music control commands watch->setEndpointHandler(WatchConnector::watchMUSIC_CONTROL, [this](const QByteArray& data) { handleMusicControl(WatchConnector::MusicControl(data.at(0))); @@ -44,6 +72,15 @@ MusicManager::MusicManager(WatchConnector *watch, QObject *parent) this, &MusicManager::handleWatchConnected); } +MusicManager::~MusicManager() +{ + if (_pulseBus != NULL) { + qCDebug(l) << "Disconnecting from PulseAudio P2P DBus"; + QDBusConnection::disconnectFromBus("org.PulseAudio1"); + delete(_pulseBus); + } +} + void MusicManager::switchToService(const QString &service) { if (_curService != service) { @@ -111,66 +148,111 @@ void MusicManager::callMprisMethod(const QString &method) void MusicManager::handleMusicControl(WatchConnector::MusicControl operation) { qCDebug(l) << "operation from watch:" << operation; - - if (_curService.isEmpty()) { - qCDebug(l) << "can't do any music operation, no mpris interface active"; - return; - } - - switch (operation) { - case WatchConnector::musicPLAY_PAUSE: - callMprisMethod("PlayPause"); - break; - case WatchConnector::musicPAUSE: - callMprisMethod("Pause"); - break; - case WatchConnector::musicPLAY: - callMprisMethod("Play"); - break; - case WatchConnector::musicNEXT: - callMprisMethod("Next"); - break; - case WatchConnector::musicPREVIOUS: - callMprisMethod("Previous"); - break; - - case WatchConnector::musicVOLUME_UP: - case WatchConnector::musicVOLUME_DOWN: { - QDBusConnection bus = QDBusConnection::sessionBus(); - QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", - "org.freedesktop.DBus.Properties", "Get"); - call << "org.mpris.MediaPlayer2.Player" << "Volume"; - QDBusReply volumeReply = bus.call(call); + QVariant useSystemVolumeVar = settings->property("useSystemVolume"); + bool useSystemVolume = (useSystemVolumeVar.isValid() && useSystemVolumeVar.toBool()); + + // System volume controls + if (useSystemVolume && _pulseBus != NULL && + (operation == WatchConnector::musicVOLUME_UP || operation == WatchConnector::musicVOLUME_DOWN)) { + // Query current volume + QDBusMessage call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Get"); + call << "com.Meego.MainVolume2" << "CurrentStep"; + + QDBusReply volumeReply = _pulseBus->call(call); if (volumeReply.isValid()) { - double volume = volumeReply.value().variant().toDouble(); - if (operation == WatchConnector::musicVOLUME_UP) { - volume += 0.1; + // Decide the new value for volume, taking limits into account + uint volume = volumeReply.value().variant().toUInt(); + uint newVolume; + qCDebug(l) << "Current volume: " << volumeReply.value().variant().toUInt(); + if (operation == WatchConnector::musicVOLUME_UP && volume < _maxVolume-1 ) { + newVolume = volume + 1; + } + else if (operation == WatchConnector::musicVOLUME_DOWN && volume > 0) { + newVolume = volume - 1; } else { - volume -= 0.1; + qCDebug(l) << "Volume already at limit"; + newVolume = volume; } - qCDebug(l) << "Setting volume" << volume; - call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Set"); - call << "org.mpris.MediaPlayer2.Player" << "Volume" << QVariant::fromValue(QDBusVariant(volume)); + // If we have a new volume level, change it + if (newVolume != volume) { + qCDebug(l) << "Setting volume: " << newVolume; - QDBusError err = QDBusConnection::sessionBus().call(call); - if (err.isValid()) { - qCWarning(l) << err.message(); + call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Set"); + call << "com.Meego.MainVolume2" << "CurrentStep" << QVariant::fromValue(QDBusVariant(newVolume)); + + QDBusError err = _pulseBus->call(call); + if (err.isValid()) { + qCWarning(l) << err.message(); + } } - } else { - qCWarning(l) << volumeReply.error().message(); } + } + + //Don't allow any music operations if there's no MPRIS player, unless we are allowed to control the system volume and it's a volume command + else if (_curService.isEmpty()) { + qCDebug(l) << "can't do any music operation, no mpris interface active"; + return; + } + else { + switch (operation) { + case WatchConnector::musicPLAY_PAUSE: + callMprisMethod("PlayPause"); + break; + case WatchConnector::musicPAUSE: + callMprisMethod("Pause"); + break; + case WatchConnector::musicPLAY: + callMprisMethod("Play"); + break; + case WatchConnector::musicNEXT: + callMprisMethod("Next"); + break; + case WatchConnector::musicPREVIOUS: + callMprisMethod("Previous"); + break; + + case WatchConnector::musicVOLUME_UP: + case WatchConnector::musicVOLUME_DOWN: { + QDBusConnection bus = QDBusConnection::sessionBus(); + QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", + "org.freedesktop.DBus.Properties", "Get"); + call << "org.mpris.MediaPlayer2.Player" << "Volume"; + QDBusReply volumeReply = bus.call(call); + if (volumeReply.isValid()) { + double volume = volumeReply.value().variant().toDouble(); + if (operation == WatchConnector::musicVOLUME_UP) { + volume += 0.1; + } + else { + volume -= 0.1; + } + qCDebug(l) << "Setting volume" << volume; + + call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Set"); + call << "org.mpris.MediaPlayer2.Player" << "Volume" << QVariant::fromValue(QDBusVariant(volume)); + + QDBusError err = QDBusConnection::sessionBus().call(call); + if (err.isValid()) { + qCWarning(l) << err.message(); + } + } else { + qCWarning(l) << volumeReply.error().message(); + } + break; } - break; - case WatchConnector::musicGET_NOW_PLAYING: - sendCurrentMprisMetadata(); - break; + case WatchConnector::musicGET_NOW_PLAYING: + sendCurrentMprisMetadata(); + break; - default: - qCWarning(l) << "Operation" << operation << "not supported"; - break; + default: + qCWarning(l) << "Operation" << operation << "not supported"; + break; + } } } -- cgit v1.2.3