mps-youtube / yewtube

yewtube, forked from mps-youtube , is a Terminal based YouTube player and downloader. No Youtube API key required.
GNU General Public License v3.0
8.14k stars 642 forks source link

MPRIS "GetStatus" not available #371

Closed ikuraj closed 9 years ago

ikuraj commented 9 years ago

I am using Pidgin musictracker plugin that tries to query mps-youtube for the current playing song, apparently in a wrong way:

(15:39:52) MPRIS: Trying org.mpris.MediaPlayer2.mps-youtube.instance25325
(15:39:52) MPRIS: GetStatus failed Method "GetStatus" with signature "" on interface "org.freedesktop.MediaPlayer" doesn't exist

I guess mps-youtube currently does not support the needed API with MPRIS. What would be the solution to this? Can the missing method be added to mps-youtube in an easy way?

hrnr commented 9 years ago

It is trying to make request on MPRISv1 interface. We support only MPRISv2. (there are large differences)

Can the missing method be added to mps-youtube in an easy way?

No.

What would be the solution to this?

use plugin which support MPRIS2. On arch linux they have mpris2 version of plugin [0]. I suppose you could at least use their patch if you are not on arch.

[0] https://aur.archlinux.org/packages/pidgin-musictracker-mpris2/

ikuraj commented 9 years ago

I see. Excellent, that is the answer that I needed! The mpris2 version of the plugin works nicely.

There is a small issue of not displaying "elapsed track time" correctly. I suspect this is due to the wrong call from the pidgin plugin. Can you point me to the documentation/code for mps-youtube mpris2 API so that I can try to modify and correct the plugin calls?

hrnr commented 9 years ago

That's because mpris2 patch is not setting "elapsed time" at all.

Mpris specs: http://specifications.freedesktop.org/mpris-spec/latest/. We implement only org.mpris.MediaPlayer2 and org.mpris.MediaPlayer2.Player interfaces.

What you are looking for is probably http://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Property:Position

You want to use some thing like:

if (!dbus_g_proxy_call (proxy2, "Get", &error, 
                              G_TYPE_STRING, "org.mpris.MediaPlayer2.Player",
                              G_TYPE_STRING, "Position",
                              G_TYPE_INVALID,
                              G_TYPE_VALUE, &h,
                              G_TYPE_INVALID))
{
        if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
        {
          mpris2_error ("Caught remote method exception %s: %s",
                        dbus_g_error_get_name (error),
                        error->message);
        }
        else
        {
          mpris2_error ("Error: %s\n", error->message);
        }
        g_error_free (error);
        goto cleanup;
}
gint64 position = g_value_get_int64 (&h);

To get position via MPRIS.

ikuraj commented 9 years ago

Excellent, that code is what needed to be added (to the updated code for calling mpris2).

There seems to be another issue which causes plugin to display stale information (e.g. track position from a few seconds ago) -- can we confirm this is a problem with the pidgin plugin, rather than mpris2 provider in mps-youtube?

hrnr commented 9 years ago

On my system I will always get pretty current position. However, Dbus is quite slow. I did some benchmarks and it takes avg. 0.0024 sec (on my system) to execute Get on position. But this gap is probably not what you had on mind.

I suppose plugin just periodicaly executes all those calls in mpris2.c, right? Then what is the rate (probaly main cause of gap)? Also all calls in that file are synchronous, so it will take even more to get position update.

How expensive are they? First there is a ListNames (bus enumeration) call to dbus itself. It returns all names on bus, which may be a lot. Just check

dbus-send --session                     \        
  --dest=org.freedesktop.DBus \
  --type=method_call                   \
  --print-reply=literal                   \
  /org/freedesktop/DBus              \
  org.freedesktop.DBus.ListNames |
tr ' ' '\n' | grep -v "^$"

If it finds a mpris bus in that it then it executes Get for Metadata, PlaybackStatus and Position. Those 3 calls are nothing compared to bus enumeration.

ListNames could certainely be called only once on init and then only when bus it has been using disappears. This btw also deals with some race conditions when running multiple mpris players.

Another thing that should be called only once is suprisingly call to Position. Mpris is designed such that you get Position only once and then updates position only on your side by Rate (see Rationale for Rate property). When Rate changes you will get signal on property change. When player seeked you will get Seeked signal. This approach is strongly recomended by specs. (and only reasonable way to do it for high update rates as dbus is clumsy and you dont want to mess it with many calls)

Probably the proper way to do that: just enumerate bus once, subscribe to signals for Rate, Seeked, Metadata, PlaybackStatus (yes those properties also emit signals on change). This approach requires main loop.

ikuraj commented 9 years ago

I believe you are right, speed of Dbus does not seem to be causing this gap. Also, calls to ListNames seem very fast on my machine.

It seems the calls are indeed periodical (I tested now, new position is increased by a constant, 15 seconds).

I see, so the proper way to do this is to subscribe to those signals. At this point, the question arises whether that is absolutely necessary, if we assume the common case is sporadic sharing of currently playing song in the messenger... I also contacted the other developer (of mpris2 patch), perhaps we might want to implement those calls correctly.

Your answers were on point, thanks for tremendous help. mps-youtube is an awesome piece of software :+1: