… | |
… | |
14 | =cut |
14 | =cut |
15 | |
15 | |
16 | package AnyEvent::MPV; |
16 | package AnyEvent::MPV; |
17 | |
17 | |
18 | use common::sense; |
18 | use common::sense; |
|
|
19 | |
|
|
20 | use Fcntl (); |
|
|
21 | use Scalar::Util (); |
19 | |
22 | |
20 | use AnyEvent (); |
23 | use AnyEvent (); |
21 | use AnyEvent::Util (); |
24 | use AnyEvent::Util (); |
22 | |
25 | |
23 | our $JSON = eval { require JSON::XS; JSON::XS:: } |
26 | our $JSON = eval { require JSON::XS; JSON::XS:: } |
… | |
… | |
51 | my ($self, @extra_args) = @_; |
54 | my ($self, @extra_args) = @_; |
52 | |
55 | |
53 | return if $self->{fh}; |
56 | return if $self->{fh}; |
54 | |
57 | |
55 | # cache optionlist for same "path" |
58 | # cache optionlist for same "path" |
56 | ($mpv_path, $mpv_optionlist) = ($self->{mpv}, qx{\Q$self->{$mpv_path}\E --list-options}) |
59 | ($mpv_path, $mpv_optionlist) = ($self->{mpv}, scalar qx{\Q$self->{mpv}\E --list-options}) |
57 | if $self->{mpv} ne $mpv_path; |
60 | if $self->{mpv} ne $mpv_path; |
58 | |
61 | |
59 | my $options = $mpv_optionlist; |
62 | my $options = $mpv_optionlist; |
60 | |
63 | |
61 | my ($fh, $slave) = AnyEvent::Util::portable_socketpair |
64 | my ($fh, $slave) = AnyEvent::Util::portable_socketpair |
62 | or die "socketpair: $!\n"; |
65 | or die "socketpair: $!\n"; |
63 | |
66 | |
64 | fh_nonblocking $fh , 1; |
67 | AnyEvent::Util::fh_nonblocking $fh, 1; |
65 | fh_nonblocking $slave, 0; |
|
|
66 | |
68 | |
67 | my $self->{pid} = fork; |
69 | $self->{pid} = fork; |
68 | |
70 | |
69 | if ($self->{pid} eq 0) { |
71 | if ($self->{pid} eq 0) { |
|
|
72 | AnyEvent::Util::fh_nonblocking $slave, 0; |
|
|
73 | fcntl $slave, Fcntl::F_SETFD, 0; |
|
|
74 | |
70 | my $input_file = $options =~ /\s--input-ipc-client\s/ ? "input-ipc-client" : "input-file"; |
75 | my $input_file = $options =~ /\s--input-ipc-client\s/ ? "input-ipc-client" : "input-file"; |
71 | |
76 | |
72 | exec $self->{mpv}, |
77 | exec $self->{mpv}, |
73 | qw(--no-input-terminal --idle=yes --pause), |
78 | qw(--no-input-terminal --idle=yes --pause), |
74 | ($self->{trace} ? "--quiet" : "--really-quiet"), |
79 | ($self->{trace} ? "--quiet" : "--really-quiet"), |
… | |
… | |
78 | exit 1; |
83 | exit 1; |
79 | } |
84 | } |
80 | |
85 | |
81 | $self->{fh} = $fh; |
86 | $self->{fh} = $fh; |
82 | |
87 | |
83 | my $trace = $self->{trace} || sub { }; |
88 | my $trace = delete $self->{trace} || sub { }; |
84 | |
89 | |
85 | $trace = sub { warn "$_[0] $_[1]\n" } if $trace && !ref $trace; |
90 | $trace = sub { warn "$_[0] $_[1]\n" } if $trace && !ref $trace; |
86 | |
91 | |
87 | my $buf; |
92 | my $buf; |
88 | my $rw; |
|
|
89 | my $ww; |
|
|
90 | my $wbuf; |
93 | my $wbuf; |
91 | my $reqid; |
94 | |
|
|
95 | Scalar::Util::weaken $self; |
92 | |
96 | |
93 | $self->{rw} = AE::io $fh, 0, sub { |
97 | $self->{rw} = AE::io $fh, 0, sub { |
94 | if (sysread $fh, $buf, 8192, length $buf) { |
98 | if (sysread $fh, $buf, 8192, length $buf) { |
95 | while ($buf =~ s/^([^\n]+)\n//) { |
99 | while ($buf =~ s/^([^\n]+)\n//) { |
96 | $trace->("mpv>" => "$1"); |
100 | $trace->("mpv>" => "$1"); |
… | |
… | |
103 | if ( |
107 | if ( |
104 | $reply->{event} eq "client-message" |
108 | $reply->{event} eq "client-message" |
105 | and $reply->{args}[0] eq "AnyEvent::MPV" |
109 | and $reply->{args}[0] eq "AnyEvent::MPV" |
106 | and $reply->{args}[1] eq "keyhack" |
110 | and $reply->{args}[1] eq "keyhack" |
107 | ) { |
111 | ) { |
108 | $self->on_key_event ($reply->{args}[2]); |
112 | $self->on_key ($reply->{args}[2]); |
109 | } else { |
113 | } else { |
110 | $self->on_event ($reply->{event}); |
114 | $self->on_event ($reply->{event}); |
111 | } |
115 | } |
112 | } elsif (exists $reply->{request_id}) { |
116 | } elsif (exists $reply->{request_id}) { |
113 | my $cv = delete $self->{cmd_cv}{$reply->{request_id}}; |
117 | my $cv = delete $self->{cmd_cv}{$reply->{request_id}}; |
… | |
… | |
133 | } else { |
137 | } else { |
134 | $trace->("mpv>" => "$1"); |
138 | $trace->("mpv>" => "$1"); |
135 | } |
139 | } |
136 | } |
140 | } |
137 | } else { |
141 | } else { |
|
|
142 | $self->stop; |
138 | $self->on_eof; |
143 | $self->on_eof; |
139 | } |
144 | } |
140 | }; |
145 | }; |
141 | |
146 | |
142 | $self->{_send} = sub { |
147 | $self->{_send} = sub { |
… | |
… | |
162 | my ($self, $key) = @_; |
167 | my ($self, $key) = @_; |
163 | |
168 | |
164 | $self->{on_event}($self, $key) if $self->{on_event}; |
169 | $self->{on_event}($self, $key) if $self->{on_event}; |
165 | } |
170 | } |
166 | |
171 | |
167 | sub on_key_event { |
172 | sub on_key { |
168 | my ($self, $key) = @_; |
173 | my ($self, $key) = @_; |
169 | |
174 | |
170 | $self->{on_key_event}($self, $key) if $self->{on_key_event}; |
175 | $self->{on_key}($self, $key) if $self->{on_key}; |
171 | } |
176 | } |
172 | |
177 | |
173 | sub cmd { |
178 | sub cmd { |
174 | my ($self, @cmd) = @_; |
179 | my ($self, @cmd) = @_; |
175 | |
180 | |