simple-player 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #!/usr/bin/python
  2. # SPDX-License-Identifier: LGPL-2.1-or-later
  3. from __future__ import print_function
  4. import os
  5. import sys
  6. import dbus
  7. import dbus.service
  8. import dbus.mainloop.glib
  9. try:
  10. from gi.repository import GObject
  11. except ImportError:
  12. import gobject as GObject
  13. import bluezutils
  14. class Player(dbus.service.Object):
  15. properties = None
  16. metadata = None
  17. def set_object(self, obj = None):
  18. if obj != None:
  19. bus = dbus.SystemBus()
  20. mp = dbus.Interface(bus.get_object("org.bluez", obj),
  21. "org.bluez.MediaPlayer1")
  22. prop = dbus.Interface(bus.get_object("org.bluez", obj),
  23. "org.freedesktop.DBus.Properties")
  24. self.properties = prop.GetAll("org.bluez.MediaPlayer1")
  25. bus.add_signal_receiver(self.properties_changed,
  26. path = obj,
  27. dbus_interface = "org.freedesktop.DBus.Properties",
  28. signal_name = "PropertiesChanged")
  29. else:
  30. track = dbus.Dictionary({
  31. "xesam:title" : "Title",
  32. "xesam:artist" : ["Artist"],
  33. "xesam:album" : "Album",
  34. "xesam:genre" : ["Genre"],
  35. "xesam:trackNumber" : dbus.Int32(1),
  36. "mpris:length" : dbus.Int64(10000) },
  37. signature="sv")
  38. self.properties = dbus.Dictionary({
  39. "PlaybackStatus" : "playing",
  40. "Identity" : "SimplePlayer",
  41. "LoopStatus" : "None",
  42. "Rate" : dbus.Double(1.0),
  43. "Shuffle" : dbus.Boolean(False),
  44. "Metadata" : track,
  45. "Volume" : dbus.Double(1.0),
  46. "Position" : dbus.Int64(0),
  47. "MinimumRate" : dbus.Double(1.0),
  48. "MaximumRate" : dbus.Double(1.0),
  49. "CanGoNext" : dbus.Boolean(False),
  50. "CanGoPrevious" : dbus.Boolean(False),
  51. "CanPlay" : dbus.Boolean(False),
  52. "CanSeek" : dbus.Boolean(False),
  53. "CanControl" : dbus.Boolean(False),
  54. },
  55. signature="sv")
  56. handler = InputHandler(self)
  57. GObject.io_add_watch(sys.stdin, GObject.IO_IN,
  58. handler.handle)
  59. @dbus.service.method("org.freedesktop.DBus.Properties",
  60. in_signature="ssv", out_signature="")
  61. def Set(self, interface, key, value):
  62. print("Set (%s, %s)" % (key, value), file=sys.stderr)
  63. return
  64. @dbus.service.signal("org.freedesktop.DBus.Properties",
  65. signature="sa{sv}as")
  66. def PropertiesChanged(self, interface, properties,
  67. invalidated = dbus.Array()):
  68. """PropertiesChanged(interface, properties, invalidated)
  69. Send a PropertiesChanged signal. 'properties' is a dictionary
  70. containing string parameters as specified in doc/media-api.txt.
  71. """
  72. pass
  73. def help(self, func):
  74. help(self.__class__.__dict__[func])
  75. def properties_changed(self, interface, properties, invalidated):
  76. print("properties_changed(%s, %s)" % (properties, invalidated))
  77. self.PropertiesChanged(interface, properties, invalidated)
  78. class InputHandler:
  79. commands = { 'PropertiesChanged': '(interface, properties)',
  80. 'help': '(cmd)' }
  81. def __init__(self, player):
  82. self.player = player
  83. print('\n\nAvailable commands:')
  84. for cmd in self.commands:
  85. print('\t', cmd, self.commands[cmd], sep='')
  86. print("\nUse python syntax to pass arguments to available methods.\n" \
  87. "E.g.: PropertiesChanged({'Metadata' : {'Title': 'My title', \
  88. 'Album': 'my album' }})")
  89. self.prompt()
  90. def prompt(self):
  91. print('\n>>> ', end='')
  92. sys.stdout.flush()
  93. def handle(self, fd, condition):
  94. s = os.read(fd.fileno(), 1024).strip()
  95. try:
  96. cmd = s[:s.find('(')]
  97. if not cmd in self.commands:
  98. print("Unknown command ", cmd)
  99. except ValueError:
  100. print("Malformed command")
  101. return True
  102. try:
  103. exec "self.player.%s" % s
  104. except Exception as e:
  105. print(e)
  106. pass
  107. self.prompt()
  108. return True
  109. if __name__ == '__main__':
  110. dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
  111. bus = dbus.SystemBus()
  112. if len(sys.argv) > 1:
  113. path = bluezutils.find_adapter(sys.argv[1]).object_path
  114. else:
  115. path = bluezutils.find_adapter().object_path
  116. media = dbus.Interface(bus.get_object("org.bluez", path),
  117. "org.bluez.Media1")
  118. path = "/test/player"
  119. player = Player(bus, path)
  120. mainloop = GObject.MainLoop()
  121. if len(sys.argv) > 2:
  122. player.set_object(sys.argv[2])
  123. else:
  124. player.set_object()
  125. print('Register media player with:\n\tProperties: %s' \
  126. % (player.properties))
  127. media.RegisterPlayer(dbus.ObjectPath(path), player.properties)
  128. mainloop.run()