2019-12-22 07:49:55 +00:00
/**
2020-08-17 10:48:10 +01:00
* SPDX - FileCopyrightText : 2018 Jun Bo Bi < jambonmcyeah @ gmail . com >
2019-12-22 07:49:55 +00:00
*
2020-08-17 10:48:10 +01:00
* SPDX - License - Identifier : GPL - 2.0 - only OR GPL - 3.0 - only OR LicenseRef - KDE - Accepted - GPL
2019-12-22 07:49:55 +00:00
*/
2018-12-21 18:23:49 +00:00
# include "mpriscontrolplugin-win.h"
2023-08-06 11:00:02 +01:00
# include "plugin_mpriscontrol_debug.h"
2020-05-29 17:49:20 +01:00
# include <core/device.h>
2023-08-28 18:31:26 +01:00
# include <KLocalizedString>
2018-12-21 18:23:49 +00:00
# include <KPluginFactory>
2020-05-29 17:49:20 +01:00
# include <QBuffer>
# include <chrono>
# include <random>
# include <ppltasks.h>
2023-08-28 18:31:26 +01:00
# include <windows.h>
2020-05-29 17:49:20 +01:00
using namespace Windows : : Foundation ;
2018-12-21 18:23:49 +00:00
2019-06-12 21:16:54 +01:00
K_PLUGIN_CLASS_WITH_JSON ( MprisControlPlugin , " kdeconnect_mpriscontrol.json " )
2018-12-21 18:23:49 +00:00
2023-08-28 18:31:26 +01:00
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 " ) ;
}
2022-09-10 22:23:52 +01:00
MprisControlPlugin : : MprisControlPlugin ( QObject * parent , const QVariantList & args )
: KdeConnectPlugin ( parent , args )
2022-12-22 16:24:31 +00:00
, sessionManager ( GlobalSystemMediaTransportControlsSessionManager : : RequestAsync ( ) . get ( ) )
2022-09-10 22:23:52 +01:00
{
2023-07-25 16:22:20 +01:00
sessionManager . SessionsChanged ( [ this ] ( GlobalSystemMediaTransportControlsSessionManager , SessionsChangedEventArgs ) {
2020-05-29 17:49:20 +01:00
this - > updatePlayerList ( ) ;
} ) ;
this - > updatePlayerList ( ) ;
}
2022-09-10 22:23:52 +01:00
std : : optional < QString > MprisControlPlugin : : getPlayerName ( GlobalSystemMediaTransportControlsSession const & player )
{
2020-05-29 17:49:20 +01:00
auto entry = std : : find ( this - > playerList . constBegin ( ) , this - > playerList . constEnd ( ) , player ) ;
2022-09-10 22:23:52 +01:00
if ( entry = = this - > playerList . constEnd ( ) ) {
2023-08-06 11:00:02 +01:00
qCWarning ( KDECONNECT_PLUGIN_MPRISCONTROL ) < < " PlaybackInfoChanged received for no longer tracked session " < < player . SourceAppUserModelId ( ) . c_str ( ) ;
2020-05-29 17:49:20 +01:00
return std : : nullopt ;
}
return entry . key ( ) ;
}
2022-09-10 22:23:52 +01:00
QString MprisControlPlugin : : randomUrl ( )
{
2020-05-29 17:49:20 +01:00
const QString VALID_CHARS = QStringLiteral ( " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ) ;
std : : default_random_engine generator ;
2022-09-10 22:23:52 +01:00
std : : uniform_int_distribution < int > distribution ( 0 , VALID_CHARS . size ( ) - 1 ) ;
2020-05-29 17:49:20 +01:00
const int size = 10 ;
QString fileUrl ( size , QChar ( ) ) ;
2022-09-10 22:23:52 +01:00
for ( int i = 0 ; i < size ; i + + ) {
2020-05-29 17:49:20 +01:00
fileUrl [ i ] = VALID_CHARS [ distribution ( generator ) ] ;
}
return QStringLiteral ( " file:// " ) + fileUrl ;
}
2022-09-10 22:23:52 +01:00
void MprisControlPlugin : : sendMediaProperties ( std : : variant < NetworkPacket , QString > const & packetOrName , GlobalSystemMediaTransportControlsSession const & player )
{
2020-05-29 17:49:20 +01:00
NetworkPacket np = packetOrName . index ( ) = = 0 ? std : : get < 0 > ( packetOrName ) : NetworkPacket ( PACKET_TYPE_MPRIS ) ;
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " player " ) , std : : get < 1 > ( packetOrName ) ) ;
auto mediaProperties = player . TryGetMediaPropertiesAsync ( ) . get ( ) ;
np . set ( QStringLiteral ( " title " ) , QString : : fromWCharArray ( mediaProperties . Title ( ) . c_str ( ) ) ) ;
np . set ( QStringLiteral ( " artist " ) , QString : : fromWCharArray ( mediaProperties . Artist ( ) . c_str ( ) ) ) ;
np . set ( QStringLiteral ( " album " ) , QString : : fromWCharArray ( mediaProperties . AlbumTitle ( ) . c_str ( ) ) ) ;
np . set ( QStringLiteral ( " albumArtUrl " ) , randomUrl ( ) ) ;
2022-09-10 22:23:52 +01:00
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " url " ) , QString ( ) ) ;
sendTimelineProperties ( np , player , true ) ; // "length"
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
sendPacket ( np ) ;
}
2022-09-10 22:23:52 +01:00
void MprisControlPlugin : : sendPlaybackInfo ( std : : variant < NetworkPacket , QString > const & packetOrName , GlobalSystemMediaTransportControlsSession const & player )
{
2020-05-29 17:49:20 +01:00
NetworkPacket np = packetOrName . index ( ) = = 0 ? std : : get < 0 > ( packetOrName ) : NetworkPacket ( PACKET_TYPE_MPRIS ) ;
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " player " ) , std : : get < 1 > ( packetOrName ) ) ;
2022-09-10 22:23:52 +01:00
2020-05-29 17:49:20 +01:00
sendMediaProperties ( np , player ) ;
auto playbackInfo = player . GetPlaybackInfo ( ) ;
auto playbackControls = playbackInfo . Controls ( ) ;
np . set ( QStringLiteral ( " isPlaying " ) , playbackInfo . PlaybackStatus ( ) = = GlobalSystemMediaTransportControlsSessionPlaybackStatus : : Playing ) ;
np . set ( QStringLiteral ( " canPause " ) , playbackControls . IsPauseEnabled ( ) ) ;
np . set ( QStringLiteral ( " canPlay " ) , playbackControls . IsPlayEnabled ( ) ) ;
np . set ( QStringLiteral ( " canGoNext " ) , playbackControls . IsNextEnabled ( ) ) ;
np . set ( QStringLiteral ( " canGoPrevious " ) , playbackControls . IsPreviousEnabled ( ) ) ;
2021-06-22 06:13:34 +01:00
np . set ( QStringLiteral ( " canSeek " ) , playbackControls . IsPlaybackPositionEnabled ( ) ) ;
2021-06-24 10:59:43 +01:00
if ( playbackInfo . IsShuffleActive ( ) ) {
const bool shuffleStatus = playbackInfo . IsShuffleActive ( ) . Value ( ) ;
np . set ( QStringLiteral ( " shuffle " ) , shuffleStatus ) ;
}
if ( playbackInfo . AutoRepeatMode ( ) ) {
QString loopStatus ;
2022-09-10 22:23:52 +01:00
switch ( playbackInfo . AutoRepeatMode ( ) . Value ( ) ) {
case Windows : : Media : : MediaPlaybackAutoRepeatMode : : List : {
loopStatus = QStringLiteral ( " Playlist " ) ;
break ;
}
case Windows : : Media : : MediaPlaybackAutoRepeatMode : : Track : {
loopStatus = QStringLiteral ( " Track " ) ;
break ;
}
default : {
loopStatus = QStringLiteral ( " None " ) ;
break ;
}
2021-06-24 10:59:43 +01:00
}
np . set ( QStringLiteral ( " loopStatus " ) , loopStatus ) ;
}
2020-05-29 17:49:20 +01:00
sendTimelineProperties ( np , player ) ;
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
sendPacket ( np ) ;
}
2022-09-10 22:23:52 +01:00
void MprisControlPlugin : : sendTimelineProperties ( std : : variant < NetworkPacket , QString > const & packetOrName ,
GlobalSystemMediaTransportControlsSession const & player ,
bool lengthOnly )
{
2020-05-29 17:49:20 +01:00
NetworkPacket np = packetOrName . index ( ) = = 0 ? std : : get < 0 > ( packetOrName ) : NetworkPacket ( PACKET_TYPE_MPRIS ) ;
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " player " ) , std : : get < 1 > ( packetOrName ) ) ;
auto timelineProperties = player . GetTimelineProperties ( ) ;
2022-09-10 22:23:52 +01:00
if ( ! lengthOnly ) {
2021-06-22 06:13:34 +01:00
const auto playbackInfo = player . GetPlaybackInfo ( ) ;
const auto playbackControls = playbackInfo . Controls ( ) ;
np . set ( QStringLiteral ( " canSeek " ) , playbackControls . IsPlaybackPositionEnabled ( ) ) ;
2022-09-10 22:23:52 +01:00
np . set ( QStringLiteral ( " pos " ) ,
std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( timelineProperties . Position ( ) - timelineProperties . StartTime ( ) ) . count ( ) ) ;
2020-05-29 17:49:20 +01:00
}
2022-09-10 22:23:52 +01:00
np . set ( QStringLiteral ( " length " ) ,
std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( timelineProperties . EndTime ( ) - timelineProperties . StartTime ( ) ) . count ( ) ) ;
2020-05-29 17:49:20 +01:00
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
sendPacket ( np ) ;
}
2022-09-10 22:23:52 +01:00
void MprisControlPlugin : : updatePlayerList ( )
{
2020-05-29 17:49:20 +01:00
playerList . clear ( ) ;
playbackInfoChangedHandlers . clear ( ) ;
mediaPropertiesChangedHandlers . clear ( ) ;
timelinePropertiesChangedHandlers . clear ( ) ;
2023-07-25 16:22:20 +01:00
auto sessions = sessionManager . GetSessions ( ) ;
2020-05-29 17:49:20 +01:00
playbackInfoChangedHandlers . resize ( sessions . Size ( ) ) ;
mediaPropertiesChangedHandlers . resize ( sessions . Size ( ) ) ;
timelinePropertiesChangedHandlers . resize ( sessions . Size ( ) ) ;
2022-09-10 22:23:52 +01:00
for ( uint32_t i = 0 ; i < sessions . Size ( ) ; i + + ) {
2020-05-29 17:49:20 +01:00
const auto player = sessions . GetAt ( i ) ;
2021-06-15 12:47:52 +01:00
auto playerName = player . SourceAppUserModelId ( ) ;
2020-05-29 17:49:20 +01:00
2021-06-15 13:36:03 +01:00
# if WIN_SDK_VERSION >= 19041
2021-06-15 12:47:52 +01:00
// try to resolve the AUMID to a user-friendly name
try {
playerName = AppInfo : : GetFromAppUserModelId ( playerName ) . DisplayInfo ( ) . DisplayName ( ) ;
} catch ( winrt : : hresult_error e ) {
2023-08-06 11:00:02 +01:00
qCDebug ( KDECONNECT_PLUGIN_MPRISCONTROL ) < < QString : : fromWCharArray ( playerName . c_str ( ) ) < < " doesn \' t have a valid AppUserModelID! Sending as-is.. " ;
2021-06-15 12:47:52 +01:00
}
2021-06-15 13:36:03 +01:00
# endif
2021-06-15 12:47:52 +01:00
QString uniqueName = QString : : fromWCharArray ( playerName . c_str ( ) ) ;
2020-05-29 17:49:20 +01:00
for ( int i = 2 ; playerList . contains ( uniqueName ) ; + + i ) {
2021-06-15 12:47:52 +01:00
uniqueName + = QStringLiteral ( " [ " ) + QString : : number ( i ) + QStringLiteral ( " ] " ) ;
2020-05-29 17:49:20 +01:00
}
playerList . insert ( uniqueName , player ) ;
2022-09-10 22:23:52 +01:00
player
. PlaybackInfoChanged ( auto_revoke ,
[ this ] ( GlobalSystemMediaTransportControlsSession player , PlaybackInfoChangedEventArgs args ) {
if ( auto name = getPlayerName ( player ) )
this - > sendPlaybackInfo ( name . value ( ) , player ) ;
} )
. swap ( playbackInfoChangedHandlers [ i ] ) ;
concurrency : : create_task ( [ this , player ] {
2020-05-29 17:49:20 +01:00
std : : chrono : : milliseconds timespan ( 50 ) ;
std : : this_thread : : sleep_for ( timespan ) ;
2022-09-10 22:23:52 +01:00
if ( auto name = getPlayerName ( player ) )
2020-05-29 17:49:20 +01:00
this - > sendPlaybackInfo ( name . value ( ) , player ) ;
} ) ;
2022-09-10 22:23:52 +01:00
if ( auto name = getPlayerName ( player ) )
2020-05-29 17:49:20 +01:00
sendPlaybackInfo ( name . value ( ) , player ) ;
2022-09-10 22:23:52 +01:00
player
. MediaPropertiesChanged ( auto_revoke ,
[ this ] ( GlobalSystemMediaTransportControlsSession player , MediaPropertiesChangedEventArgs args ) {
if ( auto name = getPlayerName ( player ) )
this - > sendMediaProperties ( name . value ( ) , player ) ;
} )
. swap ( mediaPropertiesChangedHandlers [ i ] ) ;
concurrency : : create_task ( [ this , player ] {
2020-05-29 17:49:20 +01:00
std : : chrono : : milliseconds timespan ( 50 ) ;
std : : this_thread : : sleep_for ( timespan ) ;
2022-09-10 22:23:52 +01:00
if ( auto name = getPlayerName ( player ) )
2020-05-29 17:49:20 +01:00
this - > sendMediaProperties ( name . value ( ) , player ) ;
} ) ;
2022-09-10 22:23:52 +01:00
player
. TimelinePropertiesChanged ( auto_revoke ,
[ this ] ( GlobalSystemMediaTransportControlsSession player , TimelinePropertiesChangedEventArgs args ) {
if ( auto name = getPlayerName ( player ) )
this - > sendTimelineProperties ( name . value ( ) , player ) ;
} )
. swap ( timelinePropertiesChangedHandlers [ i ] ) ;
concurrency : : create_task ( [ this , player ] {
2020-05-29 17:49:20 +01:00
std : : chrono : : milliseconds timespan ( 50 ) ;
std : : this_thread : : sleep_for ( timespan ) ;
2022-09-10 22:23:52 +01:00
if ( auto name = getPlayerName ( player ) )
2020-05-29 17:49:20 +01:00
this - > sendTimelineProperties ( name . value ( ) , player ) ;
} ) ;
}
sendPlayerList ( ) ;
}
2022-09-10 22:23:52 +01:00
void MprisControlPlugin : : sendPlayerList ( )
{
2020-05-29 17:49:20 +01:00
NetworkPacket np ( PACKET_TYPE_MPRIS ) ;
2023-08-28 18:31:26 +01:00
np . set ( QStringLiteral ( " playerList " ) , playerList . keys ( ) + QStringList ( DEFAULT_PLAYER ) ) ;
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " supportAlbumArtPayload " ) , false ) ; // TODO: Sending albumArt doesn't work
sendPacket ( np ) ;
}
2022-09-10 22:23:52 +01:00
bool MprisControlPlugin : : sendAlbumArt ( std : : variant < NetworkPacket , QString > const & packetOrName ,
GlobalSystemMediaTransportControlsSession const & player ,
QString artUrl )
{
2023-08-06 11:00:02 +01:00
qWarning ( KDECONNECT_PLUGIN_MPRISCONTROL ) < < " Sending Album Art " ;
2020-05-29 17:49:20 +01:00
NetworkPacket np = packetOrName . index ( ) = = 0 ? std : : get < 0 > ( packetOrName ) : NetworkPacket ( PACKET_TYPE_MPRIS ) ;
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " player " ) , std : : get < 1 > ( packetOrName ) ) ;
2022-09-10 22:23:52 +01:00
2020-05-29 17:49:20 +01:00
auto thumbnail = player . TryGetMediaPropertiesAsync ( ) . get ( ) . Thumbnail ( ) ;
2022-09-10 22:23:52 +01:00
if ( thumbnail ) {
2020-05-29 17:49:20 +01:00
auto stream = thumbnail . OpenReadAsync ( ) . get ( ) ;
2022-09-10 22:23:52 +01:00
if ( stream & & stream . CanRead ( ) ) {
2020-05-29 17:49:20 +01:00
IBuffer data = Buffer ( stream . Size ( ) ) ;
data = stream . ReadAsync ( data , stream . Size ( ) , InputStreamOptions : : None ) . get ( ) ;
QSharedPointer < QBuffer > qdata = QSharedPointer < QBuffer > ( new QBuffer ( ) ) ;
2022-09-10 22:23:52 +01:00
qdata - > setData ( ( char * ) data . data ( ) , data . Capacity ( ) ) ;
2020-05-29 17:49:20 +01:00
np . set ( QStringLiteral ( " transferringAlbumArt " ) , true ) ;
np . set ( QStringLiteral ( " albumArtUrl " ) , artUrl ) ;
np . setPayload ( qdata , qdata - > size ( ) ) ;
2022-09-10 22:23:52 +01:00
if ( packetOrName . index ( ) = = 1 )
2020-05-29 17:49:20 +01:00
sendPacket ( np ) ;
return true ;
}
return false ;
2022-09-10 22:23:52 +01:00
} else {
2020-05-29 17:49:20 +01:00
return false ;
}
}
2018-12-21 18:23:49 +00:00
2023-08-28 18:31:26 +01:00
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 ) ;
}
}
2023-07-31 08:25:45 +01:00
void MprisControlPlugin : : receivePacket ( const NetworkPacket & np )
2018-12-21 18:23:49 +00:00
{
if ( np . has ( QStringLiteral ( " playerList " ) ) ) {
2023-07-31 08:25:45 +01:00
return ; // Whoever sent this is an mpris client and not an mpris control!
2018-12-21 18:23:49 +00:00
}
2022-09-10 22:23:52 +01:00
// Send the player list
2020-05-29 17:49:20 +01:00
const QString name = np . get < QString > ( QStringLiteral ( " player " ) ) ;
2023-08-28 18:31:26 +01:00
if ( name = = DEFAULT_PLAYER ) {
handleDefaultPlayer ( np ) ;
return ;
}
2020-05-29 17:49:20 +01:00
auto it = playerList . find ( name ) ;
bool valid_player = ( it ! = playerList . end ( ) ) ;
2018-12-21 18:23:49 +00:00
if ( ! valid_player | | np . get < bool > ( QStringLiteral ( " requestPlayerList " ) ) ) {
2023-08-28 18:31:26 +01:00
updatePlayerList ( ) ;
2020-05-29 17:49:20 +01:00
sendPlayerList ( ) ;
2018-12-21 18:23:49 +00:00
if ( ! valid_player ) {
2023-07-31 08:25:45 +01:00
return ;
2018-12-21 18:23:49 +00:00
}
}
2020-05-29 17:49:20 +01:00
auto player = it . value ( ) ;
if ( np . has ( QStringLiteral ( " albumArtUrl " ) ) ) {
2023-07-31 08:25:45 +01:00
sendAlbumArt ( name , player , np . get < QString > ( QStringLiteral ( " albumArtUrl " ) ) ) ;
return ;
2020-05-29 17:49:20 +01:00
}
2018-12-21 18:23:49 +00:00
if ( np . has ( QStringLiteral ( " action " ) ) ) {
2022-09-10 22:23:52 +01:00
const QString & action = np . get < QString > ( QStringLiteral ( " action " ) ) ;
if ( action = = QStringLiteral ( " Next " ) ) {
2020-05-29 17:49:20 +01:00
player . TrySkipNextAsync ( ) . get ( ) ;
2022-09-10 22:23:52 +01:00
} else if ( action = = QStringLiteral ( " Previous " ) ) {
2020-05-29 17:49:20 +01:00
player . TrySkipPreviousAsync ( ) . get ( ) ;
2022-09-10 22:23:52 +01:00
} else if ( action = = QStringLiteral ( " Pause " ) ) {
2020-05-29 17:49:20 +01:00
player . TryPauseAsync ( ) . get ( ) ;
2022-09-10 22:23:52 +01:00
} else if ( action = = QStringLiteral ( " PlayPause " ) ) {
2020-05-29 17:49:20 +01:00
player . TryTogglePlayPauseAsync ( ) . get ( ) ;
2022-09-10 22:23:52 +01:00
} else if ( action = = QStringLiteral ( " Stop " ) ) {
2020-05-29 17:49:20 +01:00
player . TryStopAsync ( ) . get ( ) ;
2022-09-10 22:23:52 +01:00
} else if ( action = = QStringLiteral ( " Play " ) ) {
2020-05-29 17:49:20 +01:00
player . TryPlayAsync ( ) . get ( ) ;
}
}
if ( np . has ( QStringLiteral ( " setVolume " ) ) ) {
2023-08-06 11:00:02 +01:00
qWarning ( KDECONNECT_PLUGIN_MPRISCONTROL ) < < " Setting volume is not supported " ;
2020-05-29 17:49:20 +01:00
}
if ( np . has ( QStringLiteral ( " Seek " ) ) ) {
TimeSpan offset = std : : chrono : : microseconds ( np . get < int > ( QStringLiteral ( " Seek " ) ) ) ;
2023-08-06 11:00:02 +01:00
qWarning ( KDECONNECT_PLUGIN_MPRISCONTROL ) < < " Seeking " < < offset . count ( ) < < " ns to " < < name ;
2020-05-29 17:49:20 +01:00
player . TryChangePlaybackPositionAsync ( ( player . GetTimelineProperties ( ) . Position ( ) + offset ) . count ( ) ) . get ( ) ;
}
2019-06-12 21:17:16 +01:00
2022-09-10 22:23:52 +01:00
if ( np . has ( QStringLiteral ( " SetPosition " ) ) ) {
2020-05-29 17:49:20 +01:00
TimeSpan position = std : : chrono : : milliseconds ( np . get < qlonglong > ( QStringLiteral ( " SetPosition " ) , 0 ) ) ;
player . TryChangePlaybackPositionAsync ( ( player . GetTimelineProperties ( ) . StartTime ( ) + position ) . count ( ) ) . get ( ) ;
2018-12-21 18:23:49 +00:00
}
2022-09-10 22:23:52 +01:00
if ( np . has ( QStringLiteral ( " setShuffle " ) ) ) {
2021-06-22 06:13:34 +01:00
player . TryChangeShuffleActiveAsync ( np . get < bool > ( QStringLiteral ( " setShuffle " ) ) ) ;
}
2022-09-10 22:23:52 +01:00
if ( np . has ( QStringLiteral ( " setLoopStatus " ) ) ) {
2021-06-22 06:13:34 +01:00
QString loopStatus = np . get < QString > ( QStringLiteral ( " setLoopStatus " ) ) ;
enum class winrt : : Windows : : Media : : MediaPlaybackAutoRepeatMode loopStatusEnumVal ;
if ( loopStatus = = QStringLiteral ( " Track " ) ) {
loopStatusEnumVal = Windows : : Media : : MediaPlaybackAutoRepeatMode : : Track ;
} else if ( loopStatus = = QStringLiteral ( " Playlist " ) ) {
loopStatusEnumVal = Windows : : Media : : MediaPlaybackAutoRepeatMode : : List ;
} else {
loopStatusEnumVal = Windows : : Media : : MediaPlaybackAutoRepeatMode : : None ;
}
player . TryChangeAutoRepeatModeAsync ( loopStatusEnumVal ) ;
}
2022-09-10 22:23:52 +01:00
// Send something read from the mpris interface
2018-12-21 18:23:49 +00:00
NetworkPacket answer ( PACKET_TYPE_MPRIS ) ;
2020-05-29 17:49:20 +01:00
answer . set ( QStringLiteral ( " player " ) , name ) ;
2018-12-21 18:23:49 +00:00
bool somethingToSend = false ;
if ( np . get < bool > ( QStringLiteral ( " requestNowPlaying " ) ) ) {
2020-05-29 17:49:20 +01:00
sendPlaybackInfo ( answer , player ) ;
2018-12-21 18:23:49 +00:00
somethingToSend = true ;
}
if ( np . get < bool > ( QStringLiteral ( " requestVolume " ) ) ) {
2021-06-22 03:47:16 +01:00
// we don't support setting per-app volume levels yet
answer . set ( QStringLiteral ( " volume " ) , - 1 ) ;
2018-12-21 18:23:49 +00:00
somethingToSend = true ;
}
if ( somethingToSend ) {
sendPacket ( answer ) ;
}
}
2023-07-26 09:15:11 +01:00
# include "moc_mpriscontrolplugin-win.cpp"
2019-06-12 21:17:16 +01:00
# include "mpriscontrolplugin-win.moc"