Somewhat fancy voice command recognition software
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mpris.py 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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
  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. }
  38. self.corpus_strings.update(self.commands)
  39. def _mpris_proxy(self):
  40. """Get a proxy for the first MPRIS media player, or None"""
  41. try:
  42. # Get the bus name of the first MPRIS media player
  43. bus_name = [name for name in self._dbus_proxy.ListNames()
  44. if name.startswith('org.mpris.MediaPlayer2')][0]
  45. # Get the proxy
  46. return self._bus.get(bus_name, '/org/mpris/MediaPlayer2')
  47. except IndexError:
  48. return None
  49. def get_handler(self, text):
  50. """Return a handler if a recognized command is heard"""
  51. if text not in self.corpus_strings:
  52. return None
  53. p = self._mpris_proxy()
  54. if p is None:
  55. return None
  56. # Make a handler for the command we heard
  57. return self.commands[text](1, p)
  58. class MPRISHandler(Handler):
  59. """Base class for MPRIS plugin handlers"""
  60. def __init__(self, confidence, proxy):
  61. """Store the MPRIS proxy object"""
  62. super().__init__(confidence)
  63. self.proxy = proxy
  64. class MPRISNextHandler(MPRISHandler):
  65. """Handler for the MPRIS Next method"""
  66. def __call__(self, tts):
  67. """Call the MPRIS Next method"""
  68. try:
  69. self.proxy.Next()
  70. except GLib.Error:
  71. # This error is raised if the media player was closed after we got
  72. # the proxy but before we called next.
  73. # FIXME raise a different exception to tell Kaylee that we failed
  74. pass
  75. class MPRISPauseHandler(MPRISHandler):
  76. """Handler for the MPRIS Pause method"""
  77. def __call__(self, tts):
  78. """Call the MPRIS Pause method"""
  79. try:
  80. self.proxy.Pause()
  81. except GLib.Error:
  82. # This error is raised if the media player was closed after we got
  83. # the proxy but before we called pause.
  84. # FIXME raise a different exception to tell Kaylee that we failed
  85. pass
  86. class MPRISPlayHandler(MPRISHandler):
  87. """Handler for the MPRIS Play method"""
  88. def __call__(self, tts):
  89. """Call the MPRIS Play method"""
  90. try:
  91. self.proxy.Play()
  92. except GLib.Error:
  93. # This error is raised if the media player was closed after we got
  94. # the proxy but before we called play.
  95. # FIXME raise a different exception to tell Kaylee that we failed
  96. pass
  97. class MPRISPreviousHandler(MPRISHandler):
  98. """Handler for the MPRIS Previous method"""
  99. def __call__(self, tts):
  100. """Call the MPRIS Previous method"""
  101. try:
  102. self.proxy.Previous()
  103. except GLib.Error:
  104. # This error is raised if the media player was closed after we got
  105. # the proxy but before we called previous.
  106. # FIXME raise a different exception to tell Kaylee that we failed
  107. pass