AnyEvent-MPV

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

    the "loadfile" command itself will run successfully.

    To unpause, we send another command, "set", to set the "pause" property
    to "no", this time using the "cmd" method, which queues the command, but
    instead of waiting for a reply, it immediately returns a condvar that
    cna be used to receive results.

    This should then cause mpv to start playing the video.

    It then again waits two seconds and quits.

    Now, just waiting two seconds is rather, eh, unuseful, so let's look at
    receiving events (using a somewhat embellished example):

       use AnyEvent;
       use AnyEvent::MPV;
   
       my $videofile = "xyzzy.mkv";

       my $quit = AE::cv;

       my $mpv = AnyEvent::MPV->new (
          trace => 1,
          args  => ["--pause", "--idle=yes"],
       );

       $mpv->start;

       $mpv->register_event (start_file => sub {
          $mpv->cmd ("set", "pause", "no");
       });

       $mpv->register_event (end_file => sub {
          my ($mpv, $event, $data) = @_;

          print "end-file<$data->{reason}>\n";
          $quit->send;
       });

       $mpv->cmd (loadfile => $mpv->escape_binary ($videofile));

       $quit->recv;

    This example uses a global condvar $quit to wait for the file to finish
    playing. Also, most of the logic is now implement in event handlers.

    The two events handlers we register are "start-file", which is emitted
    by mpv once it has loaded a new file, and "end-file", which signals the
    end of a file (underscores are internally replaced by minus signs, so
    you cna speicfy event names with either).

    In the "start-file" event, we again set the "pause" property to "no" so
    the movie starts playing. For the "end-file" event, we tell the main
    program to quit by invoking $quit.

    This should conclude the basics of operation. There are a few more
    examples later in the documentation.

  ENCODING CONVENTIONS
    As a rule of thumb, all data you pass to this module to be sent to mpv
    is expected to be in unicode. To pass something that isn't, you need to
    escape it using "escape_binary".

    Data received from mpv, however, is *not* decoded to unicode, as data
    returned by mpv is not generally encoded in unicode, and the encoding is
    usually unspecified. So if you receive data and expect it to be in
    unicode, you need to first decode it from UTF-8, but note that this
    might fail. This is not a limitation of this module - mpv simply does
    not specify nor guarantee a specific encoding, or any encoding at all,
    in its protocol.

  METHODS
    $mpv = AnyEvent::MPV->new (key => value...)
        Creates a new "mpv" object, but does not yet do anything. The
        support key-value pairs are:

        mpv => $path
            The path to the mpv binary to use - by default, "mpv" is used
            and therefore, uses your "PATH" to find it.

        args => [...]
            Arguments to pass to mpv. These arguments are passed after the
            hardcoded arguments used by this module, but before the
            arguments passed ot "start". It does not matter whether you
            specify your arguments using this key, or in the "start" call,
            but when you invoke mpv multiple times, typically the arguments
            used for all invocations go here, while arguments used for
            specific invocations (e..g filenames) are passed to "start".

        trace => false|true|coderef
            Enables tracing if true. In trace mode, output from mpv is
            printed to standard error using a "mpv>" prefix, and commands
            sent to mpv are printed with a ">mpv" prefix.

            If a code reference is passed, then instead of printing to
            standard errort, this coderef is invoked with a first arfgument
            being either "mpv>" or ">mpv", and the second argument being a
            string to display. The default implementation simply does this:

               sub {
                  warn "$_[0] $_[1]\n";
               }

        on_eof => $coderef->($mpv)
        on_event => $coderef->($mpv, $event, $data)
        on_key => $coderef->($mpv, $string)
            These are invoked by the default method implementation of the
            same name - see below.

    $string = $mpv->escape_binary ($string)
        This module excects all command data sent to mpv to be in unicode.
        Some things are not, such as filenames. To pass binary data such as
        filenames through a comamnd, you need to escape it using this
        method.

        The simplest example is a "loadfile" command:

           $mpv->cmd_recv (loadfile => $mpv->escape_binary ($path));

    $started = $mpv->start (argument...)
        Starts mpv, passing the given arguemnts as extra arguments to mpv.
        If mpv is already running, it returns false, otherwise it returns a
        true value, so you can easily start mpv on demand by calling "start"
        just before using it, and if it is already running, it will not be
        started again.

        The arguments passwd to mpv are a set of hardcoded built-in
        arguments, followed by the arguments specified in the constructor,
        followed by the arguments passwd to this method. The built-in
        arguments currently are --no-input-terminal, --really-quiet (or
        --quiet in "trace" mode), and "--input-ipc-client" (or equivalent).

        Some commonly used and/or even useful arguments you might want to
        pass are:

        --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
        again.

    $mpv->on_eof
        This method is called when mpv quits - usually unexpectedly. The
        default implementation will call the "on_eof" code reference
        specified in the constructor, or do nothing if none was given.

        For subclassing, see *SUBCLASSING*, below.

README  view on Meta::CPAN

        name of the property and the new value.

        For a list of properties that you can observe, see the mpv
        documentation <https://mpv.io/manual/stable/#property-list>.

        Due to the (sane :) way mpv handles these requests, you will always
        get a property cxhange event right after registering an observer
        (meaning you don't have to query the current value), and it is also
        possible to register multiple observers for the same property - they
        will all be handled properly.

        When called in void context, the observer stays in place until mpv
        is stopped. In any otrher context, these methods return a guard
        object that, when it goes out of scope, unregisters the observe
        using "unobserve_property".

        Internally, this method uses observer ids of 2**52
        (0x10000000000000) or higher - it will not interfere with lower
        ovserver ids, so it is possible to completely ignore this system and
        execute "observe_property" commands yourself, whilst listening to
        "property-change" events - as long as your ids stay below 2**52.

        Example: register observers for changtes in "aid" and "sid". Note
        that a dummy statement is added to make sure the method is called in
        void context.

           sub register_observers {
              my ($mpv) = @_;

              $mpv->observe_property (aid => sub {
                 my ($mpv, $name, $value) = @_;
                 print "property aid (=$name) has changed to $value\n";
              });

              $mpv->observe_property (sid => sub {
                 my ($mpv, $name, $value) = @_;
                 print "property sid (=$name) has changed to $value\n";
              });

              () # ensure the above method is called in void context
           }

  SUBCLASSING
    Like most perl objects, "AnyEvent::MPV" objects are implemented as
    hashes, with the constructor simply storing all passed key-value pairs
    in the object. If you want to subclass to provide your own "on_*"
    methods, be my guest and rummage around in the internals as much as you
    wish - the only guarantee that this module dcoes is that it will not use
    keys with double colons in the name, so youc an use those, or chose to
    simply not care and deal with the breakage.

    If you don't want to go to the effort of subclassing this module, you
    can also specify all event handlers as constructor keys.

EXAMPLES
    Here are some real-world code snippets, thrown in here mainly to give
    you some example code to copy.

  doomfrontend
    At one point I replaced mythtv-frontend by my own terminal-based video
    player (based on rxvt-unicode). I toyed with the diea of using mpv's
    subtitle engine to create the user interface, but that is hard to use
    since you don't know how big your letters are. It is also where most of
    this modules code has originally been developed in.

    It uses a unified input queue to handle various remote controls, so its
    event handling needs are very simple - it simply feeds all events into
    the input queue:

       my $mpv = AnyEvent::MPV->new (
          mpv   => $MPV,
          args  => \@MPV_ARGS,
          on_event => sub {
             input_feed "mpv/$_[1]", $_[2];
          },
          on_key => sub {
             input_feed $_[1];
          },
          on_eof => sub {
             input_feed "mpv/quit";
          },
       );

       ...

       $mpv->start ("--idle=yes", "--pause", "--force-window=no");

    It also doesn't use complicated command line arguments - the file search
    options have the most impact, as they prevent mpv from scanning
    directories with tens of thousands of files for subtitles and more:

       --audio-client-name=doomfrontend
       --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
             BS    red
             i     green
             o     yellow
             b     blue
             D     triangle
             UP    up
             DOWN  down
             RIGHT right



( run in 0.796 second using v1.01-cache-2.11-cpan-39bf76dae61 )