mediacontrollertest.py   mediacontrollertest.py 
skipping to change at line 16 skipping to change at line 16
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments
import threading import threading
import unittest import unittest
from os import getcwd, getpid, path from os import getcwd, getpid, path
from typing import Any, Final from typing import Any, Final
from appium import webdriver from appium import webdriver
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy from appium.webdriver.common.appiumby import AppiumBy
from gi.repository import Gio, GLib from gi.repository import Gio, GLib
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
WIDGET_ID: Final = "org.kde.plasma.mediacontroller"
class Mpris2: class Mpris2:
""" """
MPRIS2 interface implemented in GDBus, since dbus-python does not suppo rt property MPRIS2 interface implemented in GDBus, since dbus-python does not suppo rt property
""" """
BASE_IFACE: Final = "org.mpris.MediaPlayer2" BASE_IFACE: Final = "org.mpris.MediaPlayer2"
OBJECT_PATH: Final = "/org/mpris/MediaPlayer2" OBJECT_PATH: Final = "/org/mpris/MediaPlayer2"
PLAYER_IFACE: Final = GLib.Variant('s', "org.mpris.MediaPlayer2.Player" ) PLAYER_IFACE: Final = GLib.Variant('s', "org.mpris.MediaPlayer2.Player" )
APP_INTERFACE: Final = f"org.mpris.MediaPlayer2.appiumtest.instance{str (getpid())}" APP_INTERFACE: Final = f"org.mpris.MediaPlayer2.appiumtest.instance{str (getpid())}"
skipping to change at line 76 skipping to change at line 79
'MaximumRate': GLib.Variant('d', 1.0), 'MaximumRate': GLib.Variant('d', 1.0),
'Volume': GLib.Variant('d', 1.0), 'Volume': GLib.Variant('d', 1.0),
'CanGoNext': GLib.Variant('b', True), 'CanGoNext': GLib.Variant('b', True),
'CanGoPrevious': GLib.Variant('b', True), 'CanGoPrevious': GLib.Variant('b', True),
'CanPlay': GLib.Variant('b', True), 'CanPlay': GLib.Variant('b', True),
'CanPause': GLib.Variant('b', True), 'CanPause': GLib.Variant('b', True),
'CanSeek': GLib.Variant('b', True), 'CanSeek': GLib.Variant('b', True),
'CanControl': GLib.Variant('b', True), 'CanControl': GLib.Variant('b', True),
} }
self.__owner_id: int = Gio.bus_own_name(Gio.BusType.SESSION, self.A self.__owner_id: int = Gio.bus_own_name(Gio.BusType.SESSION, self.A
PP_INTERFACE, Gio.BusNameOwnerFlags.NONE, self.on_bus_acquired, PP_INTERFACE, Gio.BusNameOwnerFlags.NONE, self.on_bus_acquired, self.on_nam
self.on_name_acquired, self e_acquired, self.on_name_lost)
.on_name_lost)
assert self.__owner_id > 0 assert self.__owner_id > 0
def quit(self) -> None: def quit(self) -> None:
self.stop(self.__connection, self.OBJECT_PATH) self.stop(self.__connection, self.OBJECT_PATH)
Gio.bus_unown_name(self.__owner_id) Gio.bus_unown_name(self.__owner_id)
print("Player exit") print("Player exit")
def on_bus_acquired(self, connection: Gio.DBusConnection, name: str, *a rgs) -> None: def on_bus_acquired(self, connection: Gio.DBusConnection, name: str, *a rgs) -> None:
""" """
Interface is ready, now register objects. Interface is ready, now register objects.
""" """
self.__connection = connection self.__connection = connection
properties_introspection_xml: str = '\n'.join(open("../dataengines/ mpris2/org.freedesktop.DBus.Properties.xml", encoding="utf-8").readlines()) properties_introspection_xml: str = '\n'.join(open("../dataengines/ mpris2/org.freedesktop.DBus.Properties.xml", encoding="utf-8").readlines())
introspection_data = Gio.DBusNodeInfo.new_for_xml(properties_intros pection_xml) introspection_data = Gio.DBusNodeInfo.new_for_xml(properties_intros pection_xml)
reg_id = connection.register_object(self.OBJECT_PATH, introspection _data.interfaces[0], self.properties_handle_method_call, None, None) reg_id = connection.register_object(self.OBJECT_PATH, introspection _data.interfaces[0], self.properties_handle_method_call, None, None)
player_introspection_xml: str = '\n'.join(open("../dataengines/mpri s2/org.mpris.MediaPlayer2.Player.xml", encoding="utf-8").readlines()) player_introspection_xml: str = '\n'.join(open("../dataengines/mpri s2/org.mpris.MediaPlayer2.Player.xml", encoding="utf-8").readlines())
introspection_data = Gio.DBusNodeInfo.new_for_xml(player_introspect ion_xml) introspection_data = Gio.DBusNodeInfo.new_for_xml(player_introspect ion_xml)
reg_id = connection.register_object(self.OBJECT_PATH, introspection reg_id = connection.register_object(self.OBJECT_PATH, introspection
_data.interfaces[0], self.player_handle_method_call, self.player_handle_get _data.interfaces[0], self.player_handle_method_call, self.player_handle_get
_property, _property, self.player_handle_set_property)
self.player_handle_set_property
)
assert reg_id != 0 assert reg_id != 0
interface_introspection_xml: str = '\n'.join(open("../dataengines/m pris2/org.mpris.MediaPlayer2.xml", encoding="utf-8").readlines()) interface_introspection_xml: str = '\n'.join(open("../dataengines/m pris2/org.mpris.MediaPlayer2.xml", encoding="utf-8").readlines())
introspection_data = Gio.DBusNodeInfo.new_for_xml(interface_introsp ection_xml) introspection_data = Gio.DBusNodeInfo.new_for_xml(interface_introsp ection_xml)
reg_id = connection.register_object(self.OBJECT_PATH, introspection reg_id = connection.register_object(self.OBJECT_PATH, introspection
_data.interfaces[0], self.interface_handle_method_call, _data.interfaces[0], self.interface_handle_method_call, self.interface_hand
self.interface_handle_get_prope le_get_property, self.interface_handle_set_property)
rty, self.interface_handle_set_property)
assert reg_id != 0 assert reg_id != 0
def on_name_acquired(self, connection, name, *args) -> None: def on_name_acquired(self, connection, name, *args) -> None:
pass pass
def on_name_lost(self, connection, name, *args) -> None: def on_name_lost(self, connection, name, *args) -> None:
pass pass
def properties_handle_method_call(self, connection: Gio.DBusConnection, def properties_handle_method_call(self, connection: Gio.DBusConnection,
sender: str, object_path: str, interface_name: str, method_name: str, sender: str, object_path: str, interface_name: str, method_name: str, para
parameters: GLib.Variant, invocation: meters: GLib.Variant, invocation: Gio.DBusMethodInvocation) -> None:
Gio.DBusMethodInvocation) -> None:
""" """
Handles method calls for org.freedesktop.DBus.Properties Handles method calls for org.freedesktop.DBus.Properties
""" """
assert interface_name == "org.freedesktop.DBus.Properties", f"Wrong interface name {interface_name} from {sender}" assert interface_name == "org.freedesktop.DBus.Properties", f"Wrong interface name {interface_name} from {sender}"
if method_name == "Get": if method_name == "Get":
ret: Any = None ret: Any = None
interface: str = parameters[0] interface: str = parameters[0]
property_name: str = parameters[1] property_name: str = parameters[1]
if interface == self.BASE_IFACE: if interface == self.BASE_IFACE:
skipping to change at line 180 skipping to change at line 179
invocation.return_value(None) invocation.return_value(None)
def set_playing(self, playing: bool, connection: Gio.DBusConnection, ob ject_path: str) -> None: def set_playing(self, playing: bool, connection: Gio.DBusConnection, ob ject_path: str) -> None:
""" """
Changes the playing state Changes the playing state
""" """
self.player_properties["PlaybackStatus"] = GLib.Variant('s', "Playi ng" if playing else "Paused") self.player_properties["PlaybackStatus"] = GLib.Variant('s', "Playi ng" if playing else "Paused")
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
"PlaybackStatus": self.player_properties["PlaybackStatus"], "PlaybackStatus": self.player_properties["PlaybackStatus"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, "org. Gio.DBusConnection.emit_signal(connection, None, object_path, "org.
freedesktop.DBus.Properties", "PropertiesChanged", freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tuple(s
GLib.Variant.new_tuple(self.PLAYER_I elf.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
FACE, changed_properties, GLib.Variant('as', ())))
def stop(self, connection: Gio.DBusConnection, object_path: str) -> Non e: def stop(self, connection: Gio.DBusConnection, object_path: str) -> Non e:
""" """
Changes the playing state Changes the playing state
""" """
self.player_properties["PlaybackStatus"] = GLib.Variant('s', "Stopp ed") self.player_properties["PlaybackStatus"] = GLib.Variant('s', "Stopp ed")
self.player_properties["Metadata"] = GLib.Variant('a{sv}', {}) self.player_properties["Metadata"] = GLib.Variant('a{sv}', {})
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
"PlaybackStatus": self.player_properties["PlaybackStatus"], "PlaybackStatus": self.player_properties["PlaybackStatus"],
"Metadata": self.player_properties["Metadata"], "Metadata": self.player_properties["Metadata"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, "org. Gio.DBusConnection.emit_signal(connection, None, object_path, "org.
freedesktop.DBus.Properties", "PropertiesChanged", freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tuple(s
GLib.Variant.new_tuple(self.PLAYER_I elf.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
FACE, changed_properties, GLib.Variant('as', ())))
def set_rate(self, rate: float, connection: Gio.DBusConnection, object_ path: str) -> None: def set_rate(self, rate: float, connection: Gio.DBusConnection, object_ path: str) -> None:
""" """
Changes the shuffle state Changes the shuffle state
""" """
assert isinstance(rate, float), f"argument is not a float but {type (rate)}" assert isinstance(rate, float), f"argument is not a float but {type (rate)}"
assert self.player_properties["MinimumRate"].get_double() <= rate < = self.player_properties["MaximumRate"].get_double(), f"Rate {rate} is out of bounds" assert self.player_properties["MinimumRate"].get_double() <= rate < = self.player_properties["MaximumRate"].get_double(), f"Rate {rate} is out of bounds"
self.player_properties["Rate"] = GLib.Variant('d', rate) self.player_properties["Rate"] = GLib.Variant('d', rate)
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
"Rate": self.player_properties["Rate"], "Rate": self.player_properties["Rate"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, "org. Gio.DBusConnection.emit_signal(connection, None, object_path, "org.
freedesktop.DBus.Properties", "PropertiesChanged", freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tuple(s
GLib.Variant.new_tuple(self.PLAYER_I elf.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
FACE, changed_properties, GLib.Variant('as', ())))
def set_shuffle(self, shuffle: bool, connection: Gio.DBusConnection, ob ject_path: str) -> None: def set_shuffle(self, shuffle: bool, connection: Gio.DBusConnection, ob ject_path: str) -> None:
""" """
Changes the shuffle state Changes the shuffle state
""" """
assert isinstance(shuffle, bool), f"argument is not a boolean but { type(shuffle)}" assert isinstance(shuffle, bool), f"argument is not a boolean but { type(shuffle)}"
self.player_properties["Shuffle"] = GLib.Variant('b', shuffle) self.player_properties["Shuffle"] = GLib.Variant('b', shuffle)
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
"Shuffle": self.player_properties["Shuffle"], "Shuffle": self.player_properties["Shuffle"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, "org. Gio.DBusConnection.emit_signal(connection, None, object_path, "org.
freedesktop.DBus.Properties", "PropertiesChanged", freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tuple(s
GLib.Variant.new_tuple(self.PLAYER_I elf.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
FACE, changed_properties, GLib.Variant('as', ())))
def set_repeat(self, repeat: str, connection: Gio.DBusConnection, objec t_path: str) -> None: def set_repeat(self, repeat: str, connection: Gio.DBusConnection, objec t_path: str) -> None:
""" """
Changes the loop state Changes the loop state
""" """
assert isinstance(repeat, str), f"argument is not a string but {typ e(repeat)}" assert isinstance(repeat, str), f"argument is not a string but {typ e(repeat)}"
self.player_properties["LoopStatus"] = GLib.Variant('s', repeat) self.player_properties["LoopStatus"] = GLib.Variant('s', repeat)
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
"LoopStatus": self.player_properties["LoopStatus"], "LoopStatus": self.player_properties["LoopStatus"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, "org. Gio.DBusConnection.emit_signal(connection, None, object_path, "org.
freedesktop.DBus.Properties", "PropertiesChanged", freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tuple(s
GLib.Variant.new_tuple(self.PLAYER_I elf.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
FACE, changed_properties, GLib.Variant('as', ())))
def set_volume(self, volume: float, connection: Gio.DBusConnection, obj ect_path: str) -> None: def set_volume(self, volume: float, connection: Gio.DBusConnection, obj ect_path: str) -> None:
""" """
Adjusts the volume Adjusts the volume
""" """
assert isinstance(volume, float) and 0 <= volume <= 1, f"Invalid vo lume {volume} of type {type(volume)}" assert isinstance(volume, float) and 0 <= volume <= 1, f"Invalid vo lume {volume} of type {type(volume)}"
self.player_properties["Volume"] = GLib.Variant('d', volume) self.player_properties["Volume"] = GLib.Variant('d', volume)
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
"Volume": self.player_properties["Volume"], "Volume": self.player_properties["Volume"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, "org. Gio.DBusConnection.emit_signal(connection, None, object_path, "org.
freedesktop.DBus.Properties", "PropertiesChanged", freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tuple(s
GLib.Variant.new_tuple(self.PLAYER_I elf.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
FACE, changed_properties, GLib.Variant('as', ())))
def player_handle_method_call(self, connection: Gio.DBusConnection, sen def player_handle_method_call(self, connection: Gio.DBusConnection, sen
der: str, object_path: str, interface_name: str, method_name: str, der: str, object_path: str, interface_name: str, method_name: str, paramete
parameters: GLib.Variant, invocation: Gio rs: GLib.Variant, invocation: Gio.DBusMethodInvocation) -> None:
.DBusMethodInvocation) -> None:
""" """
Handles method calls for org.mpris.MediaPlayer2.Player Handles method calls for org.mpris.MediaPlayer2.Player
""" """
assert interface_name == "org.mpris.MediaPlayer2.Player", f"Wrong i nterface name {interface_name} from {sender}" assert interface_name == "org.mpris.MediaPlayer2.Player", f"Wrong i nterface name {interface_name} from {sender}"
print(f"player_handle_method_call method_name: {method_name}") print(f"player_handle_method_call method_name: {method_name}")
if method_name == "Next": if method_name == "Next":
self.metadata = { self.metadata = {
'mpris:trackid': GLib.Variant('o', "/appiumtest/2"), 'mpris:trackid': GLib.Variant('o', "/appiumtest/2"),
'xesam:url': GLib.Variant('s', "file://" + path.join(getcwd (), "resources/media2.mp3")), 'xesam:url': GLib.Variant('s', "file://" + path.join(getcwd (), "resources/media2.mp3")),
'mpris:length': GLib.Variant('x', 90 * 10e6), # ms 'mpris:length': GLib.Variant('x', 90 * 10e6), # ms
'xesam:title': GLib.Variant('s', "Konqi's Favorite"), 'xesam:title': GLib.Variant('s', "Konqi's Favorite"),
'xesam:album': GLib.Variant('s', "The Best of Konqi"), 'xesam:album': GLib.Variant('s', "The Best of Konqi"),
'xesam:artist': GLib.Variant('as', ["KDE Community", "KDE 社 区"]), 'xesam:artist': GLib.Variant('as', ["KDE Community", "KDE 社 区"]),
"mpris:artUrl": GLib.Variant('s', "file://" + path.join(get cwd(), "resources/mediacontrollertests_art2.png")) "mpris:artUrl": GLib.Variant('s', "file://" + path.join(get cwd(), "resources/mediacontrollertests_art2.png"))
} }
self.player_properties["Metadata"] = GLib.Variant('a{sv}', self .metadata) self.player_properties["Metadata"] = GLib.Variant('a{sv}', self .metadata)
self.player_properties["CanGoPrevious"] = GLib.Variant('b', Tru e) self.player_properties["CanGoPrevious"] = GLib.Variant('b', Tru e)
self.player_properties["CanGoNext"] = GLib.Variant('b', False) self.player_properties["CanGoNext"] = GLib.Variant('b', False)
changed_properties = GLib.Variant( changed_properties = GLib.Variant('a{sv}', {
'a{sv}', { 'Metadata': self.player_properties["Metadata"],
'Metadata': self.player_properties["Metadata"], "CanGoPrevious": self.player_properties["CanGoPrevious"],
"CanGoPrevious": self.player_properties["CanGoPrevious" "CanGoNext": self.player_properties["CanGoNext"],
], })
"CanGoNext": self.player_properties["CanGoNext"], Gio.DBusConnection.emit_signal(connection, None, object_path, "
}) org.freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tup
Gio.DBusConnection.emit_signal(connection, None, object_path, " le(self.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
org.freedesktop.DBus.Properties", "PropertiesChanged",
GLib.Variant.new_tuple(self.PLAY
ER_IFACE, changed_properties, GLib.Variant('as', ())))
elif method_name == "Previous": elif method_name == "Previous":
self.metadata = { self.metadata = {
'mpris:trackid': GLib.Variant('o', "/appiumtest/2"), 'mpris:trackid': GLib.Variant('o', "/appiumtest/2"),
'xesam:url': GLib.Variant('s', "file://" + path.join(getcwd (), "resources/media0.mp3")), 'xesam:url': GLib.Variant('s', "file://" + path.join(getcwd (), "resources/media0.mp3")),
'mpris:length': GLib.Variant('x', 60 * 10e6), # ms 'mpris:length': GLib.Variant('x', 60 * 10e6), # ms
'xesam:title': GLib.Variant('s', "Katie's Favorite"), 'xesam:title': GLib.Variant('s', "Katie's Favorite"),
'xesam:album': GLib.Variant('s', "The Best of Konqi"), 'xesam:album': GLib.Variant('s', "The Best of Konqi"),
'xesam:artist': GLib.Variant('as', ["KDE Community"]), 'xesam:artist': GLib.Variant('as', ["KDE Community"]),
"mpris:artUrl": GLib.Variant('s', "file://" + path.join(get cwd(), "resources/mediacontrollertests_art0.png")) "mpris:artUrl": GLib.Variant('s', "file://" + path.join(get cwd(), "resources/mediacontrollertests_art0.png"))
} }
self.player_properties["Metadata"] = GLib.Variant('a{sv}', self .metadata) self.player_properties["Metadata"] = GLib.Variant('a{sv}', self .metadata)
self.player_properties["CanGoPrevious"] = GLib.Variant('b', Fal se) self.player_properties["CanGoPrevious"] = GLib.Variant('b', Fal se)
self.player_properties["CanGoNext"] = GLib.Variant('b', True) self.player_properties["CanGoNext"] = GLib.Variant('b', True)
changed_properties = GLib.Variant( changed_properties = GLib.Variant('a{sv}', {
'a{sv}', { 'Metadata': self.player_properties["Metadata"],
'Metadata': self.player_properties["Metadata"], "CanGoPrevious": self.player_properties["CanGoPrevious"],
"CanGoPrevious": self.player_properties["CanGoPrevious" "CanGoNext": self.player_properties["CanGoNext"],
], })
"CanGoNext": self.player_properties["CanGoNext"], Gio.DBusConnection.emit_signal(connection, None, object_path, "
}) org.freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tup
Gio.DBusConnection.emit_signal(connection, None, object_path, " le(self.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
org.freedesktop.DBus.Properties", "PropertiesChanged",
GLib.Variant.new_tuple(self.PLAY
ER_IFACE, changed_properties, GLib.Variant('as', ())))
elif method_name == "Pause": elif method_name == "Pause":
self.set_playing(False, connection, object_path) self.set_playing(False, connection, object_path)
elif method_name == "PlayPause": elif method_name == "PlayPause":
self.set_playing(self.player_properties["PlaybackStatus"] != "P laying", connection, object_path) self.set_playing(self.player_properties["PlaybackStatus"] != "P laying", connection, object_path)
elif method_name == "Stop": elif method_name == "Stop":
self.stop(connection, object_path) self.stop(connection, object_path)
skipping to change at line 319 skipping to change at line 307
elif method_name == "Seek": elif method_name == "Seek":
offset: int = parameters[0] offset: int = parameters[0]
length: int = int(self.metadata["mpris:length"]) length: int = int(self.metadata["mpris:length"])
position: int = int(self.player_properties["Position"]) position: int = int(self.player_properties["Position"])
assert 0 <= position + offset <= length assert 0 <= position + offset <= length
self.player_properties["Position"] = GLib.Variant('x', position + offset) self.player_properties["Position"] = GLib.Variant('x', position + offset)
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
'Position': self.player_properties["Position"], 'Position': self.player_properties["Position"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, s Gio.DBusConnection.emit_signal(connection, None, object_path, s
elf.PLAYER_IFACE.get_string(), "Seeked", elf.PLAYER_IFACE.get_string(), "Seeked", GLib.Variant.new_tuple(self.player
GLib.Variant.new_tuple(self.play _properties["Position"]))
er_properties["Position"])) Gio.DBusConnection.emit_signal(connection, None, object_path, "
Gio.DBusConnection.emit_signal(connection, None, object_path, " org.freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tup
org.freedesktop.DBus.Properties", "PropertiesChanged", le(self.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
GLib.Variant.new_tuple(self.PLAY
ER_IFACE, changed_properties, GLib.Variant('as', ())))
elif method_name == "SetPosition": elif method_name == "SetPosition":
assert parameters[0] == self.metadata["mpris:trackid"].get_stri assert parameters[0] == self.metadata["mpris:trackid"].get_stri
ng( ng(), f"expected trackid: {parameters[0]}, actual trackid: {self.metadata['
), f"expected trackid: {parameters[0]}, actual trackid: {self.m mpris:trackid'].get_string()}"
etadata['mpris:trackid'].get_string()}"
self.player_properties["Position"] = GLib.Variant('x', paramete rs[1]) self.player_properties["Position"] = GLib.Variant('x', paramete rs[1])
changed_properties = GLib.Variant('a{sv}', { changed_properties = GLib.Variant('a{sv}', {
'Position': self.player_properties["Position"], 'Position': self.player_properties["Position"],
}) })
Gio.DBusConnection.emit_signal(connection, None, object_path, " Gio.DBusConnection.emit_signal(connection, None, object_path, "
org.freedesktop.DBus.Properties", "PropertiesChanged", org.freedesktop.DBus.Properties", "PropertiesChanged", GLib.Variant.new_tup
GLib.Variant.new_tuple(self.PLAY le(self.PLAYER_IFACE, changed_properties, GLib.Variant('as', ())))
ER_IFACE, changed_properties, GLib.Variant('as', ())))
elif method_name == "OpenUri": elif method_name == "OpenUri":
print("OpenUri") print("OpenUri")
else: else:
# In case the interface adds new methods, fail here for easier discovery # In case the interface adds new methods, fail here for easier discovery
assert False, f"{method_name} does not exist" assert False, f"{method_name} does not exist"
def player_handle_get_property(self, connection: Gio.DBusConnection, se nder: str, object_path: str, interface_name: str, value: Any): def player_handle_get_property(self, connection: Gio.DBusConnection, se nder: str, object_path: str, interface_name: str, value: Any):
""" """
skipping to change at line 375 skipping to change at line 359
elif key == "Volume": elif key == "Volume":
self.set_volume(value, connection, object_path) self.set_volume(value, connection, object_path)
else: else:
assert False assert False
# What is the correct thing to return here on success? It appears that # What is the correct thing to return here on success? It appears that
# we need to return something other than None or what would be eval uated # we need to return something other than None or what would be eval uated
# to False for this call back to be successful. # to False for this call back to be successful.
return True return True
def interface_handle_method_call(self, connection: Gio.DBusConnection, def interface_handle_method_call(self, connection: Gio.DBusConnection,
sender: str, object_path: str, interface_name: str, method_name: str, sender: str, object_path: str, interface_name: str, method_name: str, param
parameters: GLib.Variant, invocation: eters: GLib.Variant, invocation: Gio.DBusMethodInvocation) -> None:
Gio.DBusMethodInvocation) -> None:
""" """
Handles method calls for org.mpris.MediaPlayer2 Handles method calls for org.mpris.MediaPlayer2
""" """
assert interface_name == "org.mpris.MediaPlayer2", f"Wrong interfac e name {interface_name} from {sender}" assert interface_name == "org.mpris.MediaPlayer2", f"Wrong interfac e name {interface_name} from {sender}"
if method_name == "Raise": if method_name == "Raise":
print("Raise") print("Raise")
elif method_name == "Quit": elif method_name == "Quit":
print("Quit") print("Quit")
else: else:
skipping to change at line 445 skipping to change at line 428
driver: webdriver.Remote driver: webdriver.Remote
mpris_interface: Mpris2 | None mpris_interface: Mpris2 | None
loopThread: GlibMainloopThread loopThread: GlibMainloopThread
@classmethod @classmethod
def setUpClass(cls) -> None: def setUpClass(cls) -> None:
""" """
Opens the widget and initialize the webdriver Opens the widget and initialize the webdriver
""" """
desired_caps: dict[str, Any] = {} options = AppiumOptions()
desired_caps["app"] = "plasmawindowed -p org.kde.plasma.nano org.kd options.set_capability("app", f"plasmawindowed -p org.kde.plasma.na
e.plasma.mediacontroller" no {WIDGET_ID}")
desired_caps["timeouts"] = {'implicit': 5000} options.set_capability("timeouts", {'implicit': 10000})
cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:47 cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:47
23', desired_capabilities=desired_caps) 23', options=options)
cls.driver.implicitly_wait = 10
cls.loopThread = GlibMainloopThread() cls.loopThread = GlibMainloopThread()
cls.loopThread.start() cls.loopThread.start()
@classmethod @classmethod
def tearDownClass(cls) -> None: def tearDownClass(cls) -> None:
cls.loopThread.quit() cls.loopThread.quit()
def setUp(self) -> None: def setUp(self) -> None:
self.mpris_interface = Mpris2() self.mpris_interface = Mpris2()
 End of changes. 20 change blocks. 
94 lines changed or deleted 73 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/