AnyEvent-MPV

 view release on metacpan or  search on metacpan

MPV.pm  view on Meta::CPAN

=over

=item uses AnyEvent, so integrates well into most event-based programs

=item supports asynchronous and synchronous operation

=item allows you to properly pass binary filenames

=item accepts data encoded in any way (does not crash when mpv replies with non UTF-8 data)

=item features a simple keybind/event system

=back

=head2 OVERVIEW OF OPERATION

This module forks an F<mpv> process and uses F<--input-ipc-client> (or
equivalent) to create a bidirectional communication channel between it and
the F<mpv> process.

It then speaks the somewhat JSON-looking (but not really being JSON)

MPV.pm  view on Meta::CPAN


=item F<--pause>, to keep F<mpv> from instantly starting to play a file, in case you want to
inspect/change properties first.

=item F<--force-window=no> (or similar), to keep F<mpv> from instantly opening a window, or to force it to do so.

=item F<--audio-client-name=yourappname>, to make sure audio streams are associated witht eh right program.

=item F<--wid=id>, to embed F<mpv> into another application.

=item F<--no-terminal>, F<--no-input-default-bindings>, F<--no-input-cursor>, F<--input-conf=/dev/null>, F<--input-vo-keyboard=no> - to ensure only you control input.

=back

The return value can be used to decide whether F<mpv> needs initializing:

   if ($mpv->start) {
      $mpv->bind_key (...);
      $mpv->cmd (set => property => value);
      ...
   }

You can immediately starting sending commands when this method returns,
even if F<mpv> has not yet started.

=cut

sub start {

MPV.pm  view on Meta::CPAN

=cut

sub on_event {
   my ($self, $event, $data) = @_;

   $self->{on_event}($self, $event, $data) if $self->{on_event};
}

=item $mpv->on_key ($string)

Invoked when a key declared by C<< ->bind_key >> is pressed. The default
invokes the C<on_key> code reference specified in the constructor with the
C<$mpv> object and the key name as arguments, or do nothing if none was
given.

For more details and examples, see the C<bind_key> method.

For subclassing, see I<SUBCLASSING>, below.

=cut

sub on_key {
   my ($self, $key) = @_;

   $self->{on_key}($self, $key) if $self->{on_key};
}

MPV.pm  view on Meta::CPAN


   $mpv->cmd_recv ("stop");
   $position = $mpv->cmd_recv ("get_property", "playback-time");

=cut

sub cmd_recv {
   &cmd->recv
}

=item $mpv->bind_key ($INPUT => $string)

This is an extension implement by this module to make it easy to get key
events. The way this is implemented is to bind a C<client-message> witha
first argument of C<AnyEvent::MPV> and the C<$string> you passed. This
C<$string> is then passed to the C<on_key> handle when the key is
proessed, e.g.:

   my $mpv = AnyEvent::MPV->new (
      on_key => sub {
         my ($mpv, $key) = @_;

         if ($key eq "letmeout") {
            print "user pressed escape\n";
         }
      },
   );

   $mpv_>bind_key (ESC => "letmeout");

You cna find a list of key names L<in the mpv
documentation|https://mpv.io/manual/stable/#key-names>.

The key configuration is lost when F<mpv> is stopped and must be (re-)done
after every C<start>.

=cut

sub bind_key {
   my ($self, $key, $event) = @_;

   $event =~ s/([^A-Za-z0-9\-_])/sprintf "\\x%02x", ord $1/ge;
   $self->cmd (keybind => $key => "no-osd script-message AnyEvent::MPV key $event");
}

=item [$guard] = $mpv->register_event ($event => $coderef->($mpv, $event, $data))

This method registers a callback to be invoked for a specific
event. Whenever the event occurs, it calls the coderef with the C<$mpv>
object, the C<$event> name and the event object, just like the C<on_event>
method.

For a lst of events, see L<the mpv

MPV.pm  view on Meta::CPAN

   --osd-on-seek=msg-bar --osd-bar-align-y=-0.85 --osd-bar-w=95
   --sub-auto=exact --audio-file-auto=exact

Since it runs on a TV without a desktop environemnt, it tries to keep complications such as dbus
away and the screensaver happy:

   # prevent xscreensaver from doing something stupid, such as starting dbus
   $ENV{DBUS_SESSION_BUS_ADDRESS} = "/"; # prevent dbus autostart for sure
   $ENV{XDG_CURRENT_DESKTOP} = "generic";

It does bind a number of keys to internal (to doomfrontend) commands:

   for (
      List::Util::pairs qw(
         ESC   return
         q     return
         ENTER enter
         SPACE pause
         [     steprev
         ]     stepfwd
         j     subtitle

MPV.pm  view on Meta::CPAN

         b     blue
         D     triangle
         UP    up
         DOWN  down
         RIGHT right
         LEFT  left
      ),
      (map { ("KP$_" => "num$_") } 0..9),
      KP_INS => 0, # KP0, but different
   ) {
      $mpv->bind_key ($_->[0] => $_->[1]);
   }

It also reacts to sponsorblock chapters, so it needs to know when vidoe
chapters change. Preadting C<AnyEvent::MPV>, it handles observers
manually:

   $mpv->cmd (observe_property => 1, "chapter-metadata");

It also tries to apply an F<mpv> profile, if it exists:

MPV.pm  view on Meta::CPAN

   $self->show_all;
   $window->realize;
   my $xid = $window->window->get_xid;

Then it starts F<mpv> using this setup:

   local $ENV{LC_ALL} = "POSIX";
   $self->{mpv}->start (
      "--no-terminal",
      "--no-input-terminal",
      "--no-input-default-bindings",
      "--no-input-cursor",
      "--input-conf=/dev/null",
      "--input-vo-keyboard=no",

      "--loop-file=inf",
      "--force-window=yes",
      "--idle=yes",

      "--audio-client-name=CV",

README  view on Meta::CPAN

    <https://mpv.io/manual/stable/#command-interface> is required to use
    this module.

    Features of this module are:

    uses AnyEvent, so integrates well into most event-based programs
    supports asynchronous and synchronous operation
    allows you to properly pass binary filenames
    accepts data encoded in any way (does not crash when mpv replies with
    non UTF-8 data)
    features a simple keybind/event system

  OVERVIEW OF OPERATION
    This module forks an mpv process and uses --input-ipc-client (or
    equivalent) to create a bidirectional communication channel between it
    and the mpv process.

    It then speaks the somewhat JSON-looking (but not really being JSON)
    protocol that mpv implements to both send it commands, decode and handle
    replies, and handle asynchronous events.

README  view on Meta::CPAN


        --idle=yes or --idle=once to keep mpv from quitting when you don't
        specify a file to play.
        --pause, to keep mpv from instantly starting to play a file, in case
        you want to inspect/change properties first.
        --force-window=no (or similar), to keep mpv from instantly opening a
        window, or to force it to do so.
        --audio-client-name=yourappname, to make sure audio streams are
        associated witht eh right program.
        --wid=id, to embed mpv into another application.
        --no-terminal, --no-input-default-bindings, --no-input-cursor,
        --input-conf=/dev/null, --input-vo-keyboard=no - to ensure only you
        control input.

        The return value can be used to decide whether mpv needs
        initializing:

           if ($mpv->start) {
              $mpv->bind_key (...);
              $mpv->cmd (set => property => value);
              ...
           }

        You can immediately starting sending commands when this method
        returns, even if mpv has not yet started.

    $mpv->stop
        Ensures that mpv is being stopped, by killing mpv with a "TERM"
        signal if needed. After this, you can "->start" a new instance

README  view on Meta::CPAN


        The first/implicit argument is the $mpv object, the second is the
        event name (same as "$data->{event}", purely for convenience), and
        the third argument is the event object as sent by mpv (sans "event"
        key). See List of events
        <https://mpv.io/manual/stable/#list-of-events> in its documentation.

        For subclassing, see *SUBCLASSING*, below.

    $mpv->on_key ($string)
        Invoked when a key declared by "->bind_key" is pressed. The default
        invokes the "on_key" code reference specified in the constructor
        with the $mpv object and the key name as arguments, or do nothing if
        none was given.

        For more details and examples, see the "bind_key" method.

        For subclassing, see *SUBCLASSING*, below.

    $mpv->cmd ($command => $arg, $arg...)
        Queues a command to be sent to mpv, using the given arguments, and
        immediately return a condvar.

        See the mpv documentation
        <https://mpv.io/manual/stable/#list-of-input-commands> for details
        on individual commands.

README  view on Meta::CPAN

        On error, the condvar will croak when "recv" is called.

    $result = $mpv->cmd_recv ($command => $arg, $arg...)
        The same as calling "cmd" and immediately "recv" on its return
        value. Useful when you don't want to mess with mpv asynchronously or
        simply needs to have the result:

           $mpv->cmd_recv ("stop");
           $position = $mpv->cmd_recv ("get_property", "playback-time");

    $mpv->bind_key ($INPUT => $string)
        This is an extension implement by this module to make it easy to get
        key events. The way this is implemented is to bind a
        "client-message" witha first argument of "AnyEvent::MPV" and the
        $string you passed. This $string is then passed to the "on_key"
        handle when the key is proessed, e.g.:

           my $mpv = AnyEvent::MPV->new (
              on_key => sub {
                 my ($mpv, $key) = @_;

                 if ($key eq "letmeout") {
                    print "user pressed escape\n";
                 }
              },
           );

           $mpv_>bind_key (ESC => "letmeout");

        You cna find a list of key names in the mpv documentation
        <https://mpv.io/manual/stable/#key-names>.

        The key configuration is lost when mpv is stopped and must be
        (re-)done after every "start".

    [$guard] = $mpv->register_event ($event => $coderef->($mpv, $event,
    $data))
        This method registers a callback to be invoked for a specific event.

README  view on Meta::CPAN

       --osd-on-seek=msg-bar --osd-bar-align-y=-0.85 --osd-bar-w=95
       --sub-auto=exact --audio-file-auto=exact

    Since it runs on a TV without a desktop environemnt, it tries to keep
    complications such as dbus away and the screensaver happy:

       # prevent xscreensaver from doing something stupid, such as starting dbus
       $ENV{DBUS_SESSION_BUS_ADDRESS} = "/"; # prevent dbus autostart for sure
       $ENV{XDG_CURRENT_DESKTOP} = "generic";

    It does bind a number of keys to internal (to doomfrontend) commands:

       for (
          List::Util::pairs qw(
             ESC   return
             q     return
             ENTER enter
             SPACE pause
             [     steprev
             ]     stepfwd
             j     subtitle

README  view on Meta::CPAN

             b     blue
             D     triangle
             UP    up
             DOWN  down
             RIGHT right
             LEFT  left
          ),
          (map { ("KP$_" => "num$_") } 0..9),
          KP_INS => 0, # KP0, but different
       ) {
          $mpv->bind_key ($_->[0] => $_->[1]);
       }

    It also reacts to sponsorblock chapters, so it needs to know when vidoe
    chapters change. Preadting "AnyEvent::MPV", it handles observers
    manually:

       $mpv->cmd (observe_property => 1, "chapter-metadata");

    It also tries to apply an mpv profile, if it exists:

README  view on Meta::CPAN

       $self->show_all;
       $window->realize;
       my $xid = $window->window->get_xid;

    Then it starts mpv using this setup:

       local $ENV{LC_ALL} = "POSIX";
       $self->{mpv}->start (
          "--no-terminal",
          "--no-input-terminal",
          "--no-input-default-bindings",
          "--no-input-cursor",
          "--input-conf=/dev/null",
          "--input-vo-keyboard=no",

          "--loop-file=inf",
          "--force-window=yes",
          "--idle=yes",

          "--audio-client-name=CV",



( run in 0.928 second using v1.01-cache-2.11-cpan-2398b32b56e )