New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mate namespace for MediaKeys not supported by any application #7

Closed
cvtsi2sd opened this Issue May 29, 2012 · 14 comments

Comments

Projects
None yet
8 participants
@cvtsi2sd

(following from this Linux Mint forums thread)

In the fork mate-settings-daemon has been updated to provide all its interfaces under org.mate.SettingsDaemon instead of the old org.gnome.SettingsDaemon.

While this is correct to avoid conflicts and to completely separate MATE and Gnome, this gives us a compability problem with any application that continue to refers to the old org.gnome.SettingsDaemon, in particular multimedia applications that want to receive notifications about multimedia keys presses.

As a temporary workaround I wrote a little Python script that emulates the org.gnome.SettingsDaemon.MediaKeys object, pushing notifications when it receives them from org.mate.SettingsDaemon.MediaKeys; it works fine, but it seems to me just a weak workaround.

Since we don't know if MATE will ever gain enough momentum to make developers of most media players patch their programs to support also MATE explicitly, in my opinion the best fix would be to abandon the media-keys notification mechanism inherited from Gnome (that, at the moment, no media players that I know of support) and move to something more standard: for example, we could use MPRIS2 to communicate with any compatible media player.

AFAIK MPRIS2 works "backwards" compared to the current mechanism (mate-settings-daemon should enumerate the currently running media players and tell them what to do, instead of a plain "media key pressed" notification), but:

  • it's standard (endorsed by FreeDesktop.org);
  • it's quite widely supported;
  • the number of media players that support it out of the box is growing, since many widely used components use it to remote-control media players (e.g. Ubuntu sound indicator menu).
@cvtsi2sd

This comment has been minimized.

Show comment
Hide comment
@cvtsi2sd

cvtsi2sd May 30, 2012

Simpler script that uses MPRIS2 instead of emulating gnome-settings-daemon.

Simpler script that uses MPRIS2 instead of emulating gnome-settings-daemon.

@ghost ghost assigned stefano-k and szesch Jun 14, 2012

@szesch

This comment has been minimized.

Show comment
Hide comment
@szesch

szesch Jun 22, 2012

Contributor

The problem with MPRIS2 is that it seems to assume you know which media player you want to interact with, or in other words, you know which media player is currently playing music/video and should be told what media key was pressed. This is obviously something of an issue.

gnome-settings-daemon essentially requires a media player to register with it via GrabMediaPlayerKeys. Whatever client was registered last gnome-settings-daemon assumes is the client that should be notified of the key press. From what I've seen of MPRIS2, it doesn't seem like there exists any functionality to achieve this.

I do agree that we need an alternative to having clients register with mate-settings-daemon, since I can't imagine VLC, Banshee, Clementine, etc. adding support for it any time soon. We just need to find a nice non-hack solution to determining which media player MPRIS2 needs to notify.

Thoughts?

Contributor

szesch commented Jun 22, 2012

The problem with MPRIS2 is that it seems to assume you know which media player you want to interact with, or in other words, you know which media player is currently playing music/video and should be told what media key was pressed. This is obviously something of an issue.

gnome-settings-daemon essentially requires a media player to register with it via GrabMediaPlayerKeys. Whatever client was registered last gnome-settings-daemon assumes is the client that should be notified of the key press. From what I've seen of MPRIS2, it doesn't seem like there exists any functionality to achieve this.

I do agree that we need an alternative to having clients register with mate-settings-daemon, since I can't imagine VLC, Banshee, Clementine, etc. adding support for it any time soon. We just need to find a nice non-hack solution to determining which media player MPRIS2 needs to notify.

Thoughts?

@cvtsi2sd

This comment has been minimized.

Show comment
Hide comment
@cvtsi2sd

cvtsi2sd Jun 22, 2012

I suppose we could just listen on D-Bus for messages of someone acquiring any name under org.mpris.MediaPlayer2 (I recall that there's some message for that that is sent globally), keep a "most recently started" queue of players and send the message only to the top element of the queue; in the improbable event that more than one player is already running before mate-settings-daemon is started we can just pick one random.

I don't know how demanding is this in terms of resources wasted, but even if we listened to every "new name registered under DBus" it shouldn't be a big deal, I never such incredible traffic of messages with dbus-monitor; still, an alternative would be polling, asking every e.g. 1 second the list of mpris-enabled players, but if you ask me it feels like a cheap hack (and it feels also more demanding on system resources).

... but isn't it a strange corner-case to have multiple media players opened in first place? And also the current method of giving the key signals just to the last opened player IMHO isn't perfect, it introduces some implicit "music player focus" that isn't so clear (although it has the big advantage that, if the user doesn't like the "focused" player it can intuitively close it and give the "music focus" to the previous one).

I suppose we could just listen on D-Bus for messages of someone acquiring any name under org.mpris.MediaPlayer2 (I recall that there's some message for that that is sent globally), keep a "most recently started" queue of players and send the message only to the top element of the queue; in the improbable event that more than one player is already running before mate-settings-daemon is started we can just pick one random.

I don't know how demanding is this in terms of resources wasted, but even if we listened to every "new name registered under DBus" it shouldn't be a big deal, I never such incredible traffic of messages with dbus-monitor; still, an alternative would be polling, asking every e.g. 1 second the list of mpris-enabled players, but if you ask me it feels like a cheap hack (and it feels also more demanding on system resources).

... but isn't it a strange corner-case to have multiple media players opened in first place? And also the current method of giving the key signals just to the last opened player IMHO isn't perfect, it introduces some implicit "music player focus" that isn't so clear (although it has the big advantage that, if the user doesn't like the "focused" player it can intuitively close it and give the "music focus" to the previous one).

@brianjmurrell

This comment has been minimized.

Show comment
Hide comment
@brianjmurrell

brianjmurrell Jul 5, 2012

I wonder how many other org.gnome interfaces are used by non-core gnome (i.e. applications not being covered in the MATE project) and will break because of the aggressive s/gnome/mate/g operation.

Certainly, going to MPRIS2 seems to be a standards based solution to this particular instance of the s/gnome/mate/g operation (and one might hope that GNOME will follow with the adoption of MPRIS2, if they are not already, rather than continuing to use their org.gnome.SettingsDaemon interface) but I wonder how many else are out there.

I wonder how many other org.gnome interfaces are used by non-core gnome (i.e. applications not being covered in the MATE project) and will break because of the aggressive s/gnome/mate/g operation.

Certainly, going to MPRIS2 seems to be a standards based solution to this particular instance of the s/gnome/mate/g operation (and one might hope that GNOME will follow with the adoption of MPRIS2, if they are not already, rather than continuing to use their org.gnome.SettingsDaemon interface) but I wonder how many else are out there.

@szesch

This comment has been minimized.

Show comment
Hide comment
Contributor

szesch commented Jul 27, 2012

@ghost ghost assigned szesch Aug 3, 2012

@tamer-hassan

This comment has been minimized.

Show comment
Hide comment
@tamer-hassan

tamer-hassan Dec 15, 2012

Contributor

@matteo-italia It isn't strange nor corner case to have multiple media players opened. For example, I could have banshee playing music, then pause it (and dock to systray), and open a video file/stream in VLC. Now, if I try to use media keys on keyboard, or an irda remote control, which of the players will get the media-key-press notification(s)?

Contributor

tamer-hassan commented Dec 15, 2012

@matteo-italia It isn't strange nor corner case to have multiple media players opened. For example, I could have banshee playing music, then pause it (and dock to systray), and open a video file/stream in VLC. Now, if I try to use media keys on keyboard, or an irda remote control, which of the players will get the media-key-press notification(s)?

@alirezaimi

This comment has been minimized.

Show comment
Hide comment
@alirezaimi

alirezaimi Feb 14, 2013

Hi
in fedora 18 not worked ,
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/dbus/connection.py", line 230, in maybe_handle_message
self._handler(_args, *_kwargs)
File "mmkeys-mate2mpris2.py", line 39, in onMediaKeyPress
sb.get_object(n, '/org/mpris/MediaPlayer2').getattr(ActionMappings[action])()
File "/usr/lib/python2.7/site-packages/dbus/proxies.py", line 70, in call
return self._proxy_method(_args, *_keywords)
File "/usr/lib/python2.7/site-packages/dbus/proxies.py", line 145, in call
**keywords)
File "/usr/lib/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
DBusException: org.freedesktop.DBus.Error.UnknownMethod: No such interface `(null)' on object at path /org/mpris/MediaPlayer2

Hi
in fedora 18 not worked ,
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/dbus/connection.py", line 230, in maybe_handle_message
self._handler(_args, *_kwargs)
File "mmkeys-mate2mpris2.py", line 39, in onMediaKeyPress
sb.get_object(n, '/org/mpris/MediaPlayer2').getattr(ActionMappings[action])()
File "/usr/lib/python2.7/site-packages/dbus/proxies.py", line 70, in call
return self._proxy_method(_args, *_keywords)
File "/usr/lib/python2.7/site-packages/dbus/proxies.py", line 145, in call
**keywords)
File "/usr/lib/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
DBusException: org.freedesktop.DBus.Error.UnknownMethod: No such interface `(null)' on object at path /org/mpris/MediaPlayer2

@brianjmurrell

This comment has been minimized.

Show comment
Hide comment
@brianjmurrell

brianjmurrell Feb 14, 2013

@alirezaimi,

I had the same problem and contacted matteo-italia. Nothing resulted as of it though. I use this script now.

#!/usr/bin/env python

import dbus
import dbus.mainloop.glib
import gobject

app_name = 'mmkeys-mate2mpris2'
Version=0.1

MediaKeysObjName = 'org.mate.SettingsDaemon'
MediaKeysObjectPath = '/org/mate/SettingsDaemon/MediaKeys'
MediaKeysInterface = 'org.mate.SettingsDaemon.MediaKeys'

MPRIS2Prefix = 'org.mpris.MediaPlayer2'

ActionMappings = {
        'Play': 'PlayPause',
        'Pause': 'Pause',
        'Stop': 'Stop',
        'Next': 'Next',
        'Previous': 'Previous'}


def onMediaKeyPress(app_name, action):
    sb = dbus.SessionBus()
    # Get the compatible players
    players = [n for n in sb.list_names() if n.startswith(MPRIS2Prefix + ".") ]

    # Send them the command
    for n in players:
        targetObject = sb.get_object(n, '/org/mpris/MediaPlayer2')
        mpris = dbus.Interface(targetObject, dbus_interface='org.mpris.MediaPlayer2.Player')
        properties = dbus.Interface(targetObject, dbus_interface='org.freedesktop.DBus.Properties')

        mpris.__getattr__(ActionMappings[action])()

if __name__ == '__main__':

    # DBUS boilerplate
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    sb = dbus.SessionBus()

    # Get the media keys notificator object
    mediaKeysObj = sb.get_object(MediaKeysObjName, MediaKeysObjectPath)

    # Register to receive media keys notifications
    mediaKeysObj.GrabMediaPlayerKeys(app_name, 0, dbus_interface=MediaKeysInterface)
    mediaKeysObj.connect_to_signal('MediaPlayerKeyPressed', onMediaKeyPress)

    # Start the main loop
    mainLoop = gobject.MainLoop()
    mainLoop.run()

@alirezaimi,

I had the same problem and contacted matteo-italia. Nothing resulted as of it though. I use this script now.

#!/usr/bin/env python

import dbus
import dbus.mainloop.glib
import gobject

app_name = 'mmkeys-mate2mpris2'
Version=0.1

MediaKeysObjName = 'org.mate.SettingsDaemon'
MediaKeysObjectPath = '/org/mate/SettingsDaemon/MediaKeys'
MediaKeysInterface = 'org.mate.SettingsDaemon.MediaKeys'

MPRIS2Prefix = 'org.mpris.MediaPlayer2'

ActionMappings = {
        'Play': 'PlayPause',
        'Pause': 'Pause',
        'Stop': 'Stop',
        'Next': 'Next',
        'Previous': 'Previous'}


def onMediaKeyPress(app_name, action):
    sb = dbus.SessionBus()
    # Get the compatible players
    players = [n for n in sb.list_names() if n.startswith(MPRIS2Prefix + ".") ]

    # Send them the command
    for n in players:
        targetObject = sb.get_object(n, '/org/mpris/MediaPlayer2')
        mpris = dbus.Interface(targetObject, dbus_interface='org.mpris.MediaPlayer2.Player')
        properties = dbus.Interface(targetObject, dbus_interface='org.freedesktop.DBus.Properties')

        mpris.__getattr__(ActionMappings[action])()

if __name__ == '__main__':

    # DBUS boilerplate
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    sb = dbus.SessionBus()

    # Get the media keys notificator object
    mediaKeysObj = sb.get_object(MediaKeysObjName, MediaKeysObjectPath)

    # Register to receive media keys notifications
    mediaKeysObj.GrabMediaPlayerKeys(app_name, 0, dbus_interface=MediaKeysInterface)
    mediaKeysObj.connect_to_signal('MediaPlayerKeyPressed', onMediaKeyPress)

    # Start the main loop
    mainLoop = gobject.MainLoop()
    mainLoop.run()
@cvtsi2sd

This comment has been minimized.

Show comment
Hide comment
@cvtsi2sd

cvtsi2sd Feb 14, 2013

@brianjmurrell I'm sorry, I didn't have much time to debug the issue at the time, and it would have been mostly blind tries, I don't grock much DBus; also, I moved to KDE on my main machine, so I would have to set up a VM just to try to fix it. Still, glad you solved! :)

@brianjmurrell I'm sorry, I didn't have much time to debug the issue at the time, and it would have been mostly blind tries, I don't grock much DBus; also, I moved to KDE on my main machine, so I would have to set up a VM just to try to fix it. Still, glad you solved! :)

@brianjmurrell

This comment has been minimized.

Show comment
Hide comment
@brianjmurrell

brianjmurrell Feb 14, 2013

@matteo-italia,

No worries. Made me learn a bit about dbus anyway. :-)

@matteo-italia,

No worries. Made me learn a bit about dbus anyway. :-)

@alirezaimi

This comment has been minimized.

Show comment
Hide comment
@alirezaimi

alirezaimi Feb 14, 2013

@brianjmurrell Thanks a lot, problem solved.

@brianjmurrell Thanks a lot, problem solved.

@ghost ghost assigned stefano-k Mar 21, 2013

@stefano-k

This comment has been minimized.

Show comment
Hide comment
@stefano-k

stefano-k Mar 22, 2013

Member

Implemented as plugin
9384398

Member

stefano-k commented Mar 22, 2013

Implemented as plugin
9384398

@stefano-k stefano-k closed this Mar 22, 2013

@xtknight

This comment has been minimized.

Show comment
Hide comment
@xtknight

xtknight May 9, 2013

There's a slight problem with the fix in the original post. This fixes it and makes (at least) Totem work properly.

What happen is that Totem reregisters itself every time it gets focus, thereby adding 'Totem' to the self.__apps list multiple times. Then, multiple events get sent, so it instantly plays/pauses, skipping a frame each time. Make the change to this area of the code.

@dbus.service.method(dbus_interface=Gnome_DbusInterface, in_signature='sd', out_signature='')
def GrabMediaPlayerKeys(self, app_name, time):
    if not (app_name in self.__apps): ## HERE
        self.__apps.append(app_name) ## HERE

@dbus.service.method(dbus_interface=Gnome_DbusInterface, in_signature='s', out_signature='')
def ReleaseMediaPlayerKeys(self, app_name):
    if app_name in self.__apps: ## HERE
        self.__apps.remove(app_name) ## HERE

xtknight commented May 9, 2013

There's a slight problem with the fix in the original post. This fixes it and makes (at least) Totem work properly.

What happen is that Totem reregisters itself every time it gets focus, thereby adding 'Totem' to the self.__apps list multiple times. Then, multiple events get sent, so it instantly plays/pauses, skipping a frame each time. Make the change to this area of the code.

@dbus.service.method(dbus_interface=Gnome_DbusInterface, in_signature='sd', out_signature='')
def GrabMediaPlayerKeys(self, app_name, time):
    if not (app_name in self.__apps): ## HERE
        self.__apps.append(app_name) ## HERE

@dbus.service.method(dbus_interface=Gnome_DbusInterface, in_signature='s', out_signature='')
def ReleaseMediaPlayerKeys(self, app_name):
    if app_name in self.__apps: ## HERE
        self.__apps.remove(app_name) ## HERE
@michaxm

This comment has been minimized.

Show comment
Hide comment
@michaxm

michaxm Jan 13, 2016

With 1.8.1-0+qiana multimedia keys still do not work for me and totem on at least 3 different machines. What does "as a plugin" mean? Am I supposed to activate it somehow? Could not find anything.

michaxm commented Jan 13, 2016

With 1.8.1-0+qiana multimedia keys still do not work for me and totem on at least 3 different machines. What does "as a plugin" mean? Am I supposed to activate it somehow? Could not find anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment