Windows MPRIS: Add a "default player" entry
This sends generic multimedia keyboard events, since the implementation using GlobalSystemMediaTransportControlsSessionManager had some problems: the SessionsChanged event doesn't work on recent Windows versions, plus many players don't implement this API (eg: VLC, Windows Media).
This commit is contained in:
parent
cfde9ced77
commit
5a27c93538
3 changed files with 79 additions and 2 deletions
|
@ -11,7 +11,7 @@ endif()
|
||||||
kdeconnect_add_plugin(kdeconnect_mpriscontrol SOURCES ${kdeconnect_mpriscontrol_SRCS})
|
kdeconnect_add_plugin(kdeconnect_mpriscontrol SOURCES ${kdeconnect_mpriscontrol_SRCS})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(kdeconnect_mpriscontrol kdeconnectcore windowsapp)
|
target_link_libraries(kdeconnect_mpriscontrol kdeconnectcore windowsapp KF${QT_MAJOR_VERSION}::I18n)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(kdeconnect_mpriscontrol Qt::DBus kdeconnectcore kdeconnectinterfaces)
|
target_link_libraries(kdeconnect_mpriscontrol Qt::DBus kdeconnectcore kdeconnectinterfaces)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "plugin_mpriscontrol_debug.h"
|
#include "plugin_mpriscontrol_debug.h"
|
||||||
#include <core/device.h>
|
#include <core/device.h>
|
||||||
|
|
||||||
|
#include <KLocalizedString>
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
@ -17,11 +18,17 @@
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include <ppltasks.h>
|
#include <ppltasks.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
using namespace Windows::Foundation;
|
using namespace Windows::Foundation;
|
||||||
|
|
||||||
K_PLUGIN_CLASS_WITH_JSON(MprisControlPlugin, "kdeconnect_mpriscontrol.json")
|
K_PLUGIN_CLASS_WITH_JSON(MprisControlPlugin, "kdeconnect_mpriscontrol.json")
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const QString DEFAULT_PLAYER = i18nc("@title Users select this to control the current media player when we can't detect a specific player name like VLC", "Current Player");
|
||||||
|
}
|
||||||
|
|
||||||
MprisControlPlugin::MprisControlPlugin(QObject *parent, const QVariantList &args)
|
MprisControlPlugin::MprisControlPlugin(QObject *parent, const QVariantList &args)
|
||||||
: KdeConnectPlugin(parent, args)
|
: KdeConnectPlugin(parent, args)
|
||||||
, sessionManager(GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get())
|
, sessionManager(GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get())
|
||||||
|
@ -238,7 +245,7 @@ void MprisControlPlugin::sendPlayerList()
|
||||||
{
|
{
|
||||||
NetworkPacket np(PACKET_TYPE_MPRIS);
|
NetworkPacket np(PACKET_TYPE_MPRIS);
|
||||||
|
|
||||||
np.set(QStringLiteral("playerList"), playerList.keys());
|
np.set(QStringLiteral("playerList"), playerList.keys() + QStringList(DEFAULT_PLAYER));
|
||||||
np.set(QStringLiteral("supportAlbumArtPayload"), false); // TODO: Sending albumArt doesn't work
|
np.set(QStringLiteral("supportAlbumArtPayload"), false); // TODO: Sending albumArt doesn't work
|
||||||
|
|
||||||
sendPacket(np);
|
sendPacket(np);
|
||||||
|
@ -279,6 +286,67 @@ bool MprisControlPlugin::sendAlbumArt(std::variant<NetworkPacket, QString> const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MprisControlPlugin::handleDefaultPlayer(const NetworkPacket &np)
|
||||||
|
{
|
||||||
|
if (np.has(QStringLiteral("action"))) {
|
||||||
|
|
||||||
|
INPUT input={0};
|
||||||
|
input.type = INPUT_KEYBOARD;
|
||||||
|
|
||||||
|
input.ki.time = 0;
|
||||||
|
input.ki.dwExtraInfo = 0;
|
||||||
|
input.ki.wScan = 0;
|
||||||
|
input.ki.dwFlags = 0;
|
||||||
|
|
||||||
|
const QString &action = np.get<QString>(QStringLiteral("action"));
|
||||||
|
|
||||||
|
if (action == QStringLiteral("PlayPause") || (action == QStringLiteral("Play")) || (action == QStringLiteral("Pause")) ) {
|
||||||
|
input.ki.wVk = VK_MEDIA_PLAY_PAUSE;
|
||||||
|
::SendInput(1,&input,sizeof(INPUT));
|
||||||
|
} else if (action == QStringLiteral("Stop")) {
|
||||||
|
input.ki.wVk = VK_MEDIA_STOP;
|
||||||
|
::SendInput(1,&input,sizeof(INPUT));
|
||||||
|
}
|
||||||
|
else if (action == QStringLiteral("Next")) {
|
||||||
|
input.ki.wVk = VK_MEDIA_NEXT_TRACK;
|
||||||
|
::SendInput(1,&input,sizeof(INPUT));
|
||||||
|
}
|
||||||
|
else if (action == QStringLiteral("Previous")) {
|
||||||
|
input.ki.wVk = VK_MEDIA_PREV_TRACK;
|
||||||
|
::SendInput(1,&input,sizeof(INPUT));
|
||||||
|
}
|
||||||
|
else if (action == QStringLiteral("Stop")) {
|
||||||
|
input.ki.wVk = VK_MEDIA_STOP;
|
||||||
|
::SendInput(1,&input,sizeof(INPUT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send something read from the mpris interface
|
||||||
|
NetworkPacket answer(PACKET_TYPE_MPRIS);
|
||||||
|
answer.set(QStringLiteral("player"), DEFAULT_PLAYER);
|
||||||
|
bool somethingToSend = false;
|
||||||
|
if (np.get<bool>(QStringLiteral("requestNowPlaying"))) {
|
||||||
|
answer.set(QStringLiteral("pos"), 0);
|
||||||
|
answer.set(QStringLiteral("isPlaying"), false);
|
||||||
|
answer.set(QStringLiteral("canPause"), false);
|
||||||
|
answer.set(QStringLiteral("canPlay"), true);
|
||||||
|
answer.set(QStringLiteral("canGoNext"), true);
|
||||||
|
answer.set(QStringLiteral("canGoPrevious"), true);
|
||||||
|
answer.set(QStringLiteral("canSeek"), false);
|
||||||
|
somethingToSend = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (np.get<bool>(QStringLiteral("requestVolume"))) {
|
||||||
|
// we don't support setting per-app volume levels yet
|
||||||
|
answer.set(QStringLiteral("volume"), -1);
|
||||||
|
somethingToSend = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (somethingToSend) {
|
||||||
|
sendPacket(answer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MprisControlPlugin::receivePacket(const NetworkPacket &np)
|
void MprisControlPlugin::receivePacket(const NetworkPacket &np)
|
||||||
{
|
{
|
||||||
if (np.has(QStringLiteral("playerList"))) {
|
if (np.has(QStringLiteral("playerList"))) {
|
||||||
|
@ -287,9 +355,16 @@ void MprisControlPlugin::receivePacket(const NetworkPacket &np)
|
||||||
|
|
||||||
// Send the player list
|
// Send the player list
|
||||||
const QString name = np.get<QString>(QStringLiteral("player"));
|
const QString name = np.get<QString>(QStringLiteral("player"));
|
||||||
|
|
||||||
|
if (name == DEFAULT_PLAYER) {
|
||||||
|
handleDefaultPlayer(np);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto it = playerList.find(name);
|
auto it = playerList.find(name);
|
||||||
bool valid_player = (it != playerList.end());
|
bool valid_player = (it != playerList.end());
|
||||||
if (!valid_player || np.get<bool>(QStringLiteral("requestPlayerList"))) {
|
if (!valid_player || np.get<bool>(QStringLiteral("requestPlayerList"))) {
|
||||||
|
updatePlayerList();
|
||||||
sendPlayerList();
|
sendPlayerList();
|
||||||
if (!valid_player) {
|
if (!valid_player) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -52,5 +52,7 @@ private:
|
||||||
void sendPlayerList();
|
void sendPlayerList();
|
||||||
bool sendAlbumArt(std::variant<NetworkPacket, QString> const &packetOrName, GlobalSystemMediaTransportControlsSession const &player, QString artUrl);
|
bool sendAlbumArt(std::variant<NetworkPacket, QString> const &packetOrName, GlobalSystemMediaTransportControlsSession const &player, QString artUrl);
|
||||||
|
|
||||||
|
void handleDefaultPlayer(const NetworkPacket &np);
|
||||||
|
|
||||||
QString randomUrl();
|
QString randomUrl();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue