AnyEvent-MPV
view release on metacpan or search on metacpan
});
() # ensure the above method is called in void context
}
=cut
sub AnyEvent::MPV::Unobserve::DESTROY {
my ($mpv, $obscb, $obsid) = @{$_[0]};
delete $obscb->{$obsid};
if ($obscb == $mpv->{obscb}) {
$mpv->cmd (unobserve_property => $obsid+0);
}
}
sub _observe_property {
my ($self, $type, $property, $cb) = @_;
my $obsid = OBSID + ++$self->{obsid};
$self->cmd ($type => $obsid+0, $property);
$self->{obscb}{$obsid} = $cb;
defined wantarray and do {
my $unobserve = bless [$self, $self->{obscb}, $obsid], AnyEvent::MPV::Unobserve::;
Scalar::Util::weaken $unobserve->[0];
$unobserve
}
}
sub observe_property {
my ($self, $property, $cb) = @_;
$self->_observe_property (observe_property => $property, $cb)
}
sub observe_property_string {
my ($self, $property, $cb) = @_;
$self->_observe_property (observe_property_string => $property, $cb)
}
=back
=head2 SUBCLASSING
Like most perl objects, C<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 C<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.
=head1 EXAMPLES
Here are some real-world code snippets, thrown in here mainly to give you
some example code to copy.
=head2 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 F<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 F<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
( run in 0.730 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )