AnyEvent-MPV

 view release on metacpan or  search on metacpan

MPV.pm  view on Meta::CPAN


   eval {
      # the profile is optional
      $mpv->cmd ("apply-profile" => "doomfrontend");
   };

Most of the complicated parts deal with saving and restoring per-video
data, such as bookmarks, playing position, selected audio and subtitle
tracks and so on. However, since it uses L<Coro>, it can conveniently
block and wait for replies, which is n ot possible in purely event based
programs, as you are not allowed to block inside event callbacks in most
event loops. This simplifies the code quite a bit.

When the file to be played is a Tv recording done by mythtv, it uses the
C<appending> protocol and deinterlacing:

   if (is_myth $mpv_path) {
      $mpv_path = "appending://$mpv_path";
      $initial_deinterlace = 1;
   }

MPV.pm  view on Meta::CPAN

      $mpv->cmd (set => "bluray-device" => $path);
      $mpv->cmd (loadfile => "bd://");
   } else {
      $mpv->cmd (loadfile => $mpv->escape_binary ($path));
   }

After this, C<Gtk2::CV> waits for the file to be loaded, video to be
configured, and then queries the video size (to resize its own window)
and video format (to decide whether an audio visualizer is needed for
audio playback). The problematic word here is "wait", as this needs to be
imploemented using callbacks.

This made the code much harder to write, as the whole setup is very
asynchronous (C<Gtk2::CV> talks to the command interface in F<mpv>, which
talks to the decode and playback parts, all of which run asynchronously
w.r.t. each other. In practise, this can mean that C<Gtk2::CV> waits for
a file to be loaded by F<mpv> while the command interface of F<mpv> still
deals with the previous file and the decoder still handles an even older
file). Adding to this fact is that Gtk2::CV is bound by the glib event
loop, which means we cannot wait for replies form F<mpv> anywhere, so
everything has to be chained callbacks.

The way this is handled is by creating a new empty hash ref that is unique
for each loaded file, and use it to detect whether the event is old or
not, and also store C<AnyEvent::MPV> guard objects in it:

   # every time we loaded a file, we create a new hash
   my $guards = $self->{mpv_guards} = { };

Then, when we wait for an event to occur, delete the handler, and, if the
C<mpv_guards> object has changed, we ignore it. Something like this:

README  view on Meta::CPAN


       eval {
          # the profile is optional
          $mpv->cmd ("apply-profile" => "doomfrontend");
       };

    Most of the complicated parts deal with saving and restoring per-video
    data, such as bookmarks, playing position, selected audio and subtitle
    tracks and so on. However, since it uses Coro, it can conveniently block
    and wait for replies, which is n ot possible in purely event based
    programs, as you are not allowed to block inside event callbacks in most
    event loops. This simplifies the code quite a bit.

    When the file to be played is a Tv recording done by mythtv, it uses the
    "appending" protocol and deinterlacing:

       if (is_myth $mpv_path) {
          $mpv_path = "appending://$mpv_path";
          $initial_deinterlace = 1;
       }

README  view on Meta::CPAN

          $mpv->cmd (set => "bluray-device" => $path);
          $mpv->cmd (loadfile => "bd://");
       } else {
          $mpv->cmd (loadfile => $mpv->escape_binary ($path));
       }

    After this, "Gtk2::CV" waits for the file to be loaded, video to be
    configured, and then queries the video size (to resize its own window)
    and video format (to decide whether an audio visualizer is needed for
    audio playback). The problematic word here is "wait", as this needs to
    be imploemented using callbacks.

    This made the code much harder to write, as the whole setup is very
    asynchronous ("Gtk2::CV" talks to the command interface in mpv, which
    talks to the decode and playback parts, all of which run asynchronously
    w.r.t. each other. In practise, this can mean that "Gtk2::CV" waits for
    a file to be loaded by mpv while the command interface of mpv still
    deals with the previous file and the decoder still handles an even older
    file). Adding to this fact is that Gtk2::CV is bound by the glib event
    loop, which means we cannot wait for replies form mpv anywhere, so
    everything has to be chained callbacks.

    The way this is handled is by creating a new empty hash ref that is
    unique for each loaded file, and use it to detect whether the event is
    old or not, and also store "AnyEvent::MPV" guard objects in it:

       # every time we loaded a file, we create a new hash
       my $guards = $self->{mpv_guards} = { };

    Then, when we wait for an event to occur, delete the handler, and, if
    the "mpv_guards" object has changed, we ignore it. Something like this:



( run in 0.810 second using v1.01-cache-2.11-cpan-9b1e4054eb1 )