Somewhat fancy voice command recognition software
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

mpris.py 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. # This is part of Kaylee
  2. # -- this code is licensed GPLv3
  3. # Copyright 2015-2017 Clayton G. Hobbs
  4. # Portions Copyright 2013 Jezra
  5. """MPRIS media player control plugin
  6. This plugin allows control of a media player supporting the Media
  7. Player Remote Interfacing Specification (MPRIS) D-Bus interface. To
  8. use this plugin, you must first install `pydbus
  9. <https://github.com/LEW21/pydbus>`__ for Python 3. This plugin takes
  10. no configuration, so load it as follows::
  11. ".mpris": {}
  12. Note: if your microphone can hear the audio produced by your speakers,
  13. it is recommended to load PulseAudio's module-echo-cancel when using
  14. this plugin. Recognition while music is playing may still be mediocre,
  15. but without module-echo-cancel it has almost no chance of working.
  16. """
  17. from gi.repository import GLib
  18. from pydbus import SessionBus
  19. from . import PluginBase, Handler, HandlerFailure
  20. class Plugin(PluginBase):
  21. """Main class for the MPRIS plugin"""
  22. def __init__(self, config, name):
  23. """Initialize the MPRIS plugin"""
  24. super().__init__(config, name)
  25. # Get the D-Bus proxy object
  26. self._bus = SessionBus()
  27. self._dbus_proxy = self._bus.get('.DBus')
  28. self.commands = {
  29. 'next song': MPRISNextHandler,
  30. 'next video': MPRISNextHandler,
  31. 'pause music': MPRISPauseHandler,
  32. 'pause video': MPRISPauseHandler,
  33. 'play music': MPRISPlayHandler,
  34. 'play video': MPRISPlayHandler,
  35. 'previous song': MPRISPreviousHandler,
  36. 'previous video': MPRISPreviousHandler,
  37. 'whats playing': MPRISTrackInfoHandler
  38. }
  39. self.corpus_strings.update(self.commands)
  40. def _mpris_proxy(self):
  41. """Get a proxy for the first MPRIS media player, or None"""
  42. try:
  43. # Get the bus name of the first MPRIS media player
  44. bus_name = [name for name in self._dbus_proxy.ListNames()
  45. if name.startswith('org.mpris.MediaPlayer2')][0]
  46. # Get the proxy
  47. return self._bus.get(bus_name, '/org/mpris/MediaPlayer2')
  48. except IndexError:
  49. return None
  50. def get_handler(self, text):
  51. """Return a handler if a recognized command is heard"""
  52. if text not in self.corpus_strings:
  53. return None
  54. p = self._mpris_proxy()
  55. if p is None:
  56. return None
  57. # Make a handler for the command we heard
  58. return self.commands[text](1, p)
  59. class MPRISHandler(Handler):
  60. """Base class for MPRIS plugin handlers"""
  61. def __init__(self, confidence, proxy):
  62. """Store the MPRIS proxy object"""
  63. super().__init__(confidence)
  64. self.proxy = proxy
  65. class MPRISNextHandler(MPRISHandler):
  66. """Handler for the MPRIS Next method"""
  67. def __call__(self, tts):
  68. """Call the MPRIS Next method"""
  69. try:
  70. self.proxy.Next()
  71. except GLib.Error:
  72. raise HandlerFailure()
  73. class MPRISPauseHandler(MPRISHandler):
  74. """Handler for the MPRIS Pause method"""
  75. def __call__(self, tts):
  76. """Call the MPRIS Pause method"""
  77. try:
  78. self.proxy.Pause()
  79. except GLib.Error:
  80. raise HandlerFailure()
  81. class MPRISPlayHandler(MPRISHandler):
  82. """Handler for the MPRIS Play method"""
  83. def __call__(self, tts):
  84. """Call the MPRIS Play method"""
  85. try:
  86. self.proxy.Play()
  87. except GLib.Error:
  88. raise HandlerFailure()
  89. class MPRISPreviousHandler(MPRISHandler):
  90. """Handler for the MPRIS Previous method"""
  91. def __call__(self, tts):
  92. """Call the MPRIS Previous method"""
  93. try:
  94. self.proxy.Previous()
  95. except GLib.Error:
  96. raise HandlerFailure()
  97. class MPRISTrackInfoHandler(MPRISHandler):
  98. """Handler for getting info about the currently playing track from MPRIS"""
  99. def __call__(self, tts):
  100. """Get and speak info about the currently playing track"""
  101. # Get metadata about the player
  102. try:
  103. metadata = self.proxy.Metadata
  104. except GLib.Error:
  105. raise HandlerFailure()
  106. # Get the title
  107. try:
  108. title = metadata['xesam:title']
  109. except KeyError:
  110. raise HandlerFailure()
  111. # Get the artist list (optional)
  112. try:
  113. artist_list = metadata['xesam:artist']
  114. except KeyError:
  115. artist_text = ''
  116. else:
  117. # Get the artists in a speakable format
  118. artist_text = ' by ' + ', '.join(
  119. artist_list[:-2] + [', and '.join(artist_list[-2:])])
  120. # Speak the information
  121. tts(f"{title}{artist_text}")