… | |
… | |
99 | my $timer = AE::timer 2, 0, my $quit = AE::cv; |
99 | my $timer = AE::timer 2, 0, my $quit = AE::cv; |
100 | $quit->recv; |
100 | $quit->recv; |
101 | |
101 | |
102 | This specifies extra arguments in the constructor - these arguments are |
102 | This specifies extra arguments in the constructor - these arguments are |
103 | used every time you "->start" mpv, while the arguments to "->start" are |
103 | used every time you "->start" mpv, while the arguments to "->start" are |
104 | only used for this specific clal to0 "start". The argument --pause keeps |
104 | only used for this specific call to "start". The argument --pause keeps |
105 | mpv in pause mode (i.e. it does not play the file after loading it), and |
105 | mpv in pause mode (i.e. it does not play the file after loading it), and |
106 | "--idle=yes" tells mpv to not quit when it does not have a playlist - as |
106 | "--idle=yes" tells mpv to not quit when it does not have a playlist - as |
107 | no files are specified on the command line. |
107 | no files are specified on the command line. |
108 | |
108 | |
109 | To load a file, we then send it a "loadfile" command, which accepts, as |
109 | To load a file, we then send it a "loadfile" command, which accepts, as |
110 | first argument, the URL or path to a video file. To make sure mpv does |
110 | first argument, the URL or path to a video file. To make sure mpv does |
111 | not misinterpret the path as a URL, it was prefixed with ./ (similarly |
111 | not misinterpret the path as a URL, it was prefixed with ./ (similarly |
112 | to "protecting" paths in perls "open"). |
112 | to "protecting" paths in perls "open"). |
113 | |
113 | |
114 | Since commands send *to* mpv are send in UTF-8, we need to escape the |
114 | Since commands send *to* mpv are send in UTF-8, we need to escape the |
115 | filename (which might be in any encoding) using the "esscape_binary" |
115 | filename (which might be in any encoding) using the "escape_binary" |
116 | method - this is not needed if your filenames are just ascii, or |
116 | method - this is not needed if your filenames are just ASCII, or |
117 | magically get interpreted correctly, but if you accept arbitrary |
117 | magically get interpreted correctly, but if you accept arbitrary |
118 | filenamews (e.g. from the user), you need to do this. |
118 | filenames (e.g. from the user), you need to do this. |
119 | |
119 | |
120 | The "cmd_recv" method then queues the command, waits for a reply and |
120 | The "cmd_recv" method then queues the command, waits for a reply and |
121 | returns the reply data (or croaks on error). mpv would, at this point, |
121 | returns the reply data (or croaks on error). mpv would, at this point, |
122 | load the file and, if everything was successful, show the first frame |
122 | load the file and, if everything was successful, show the first frame |
123 | and pause. Note that, since mpv is implement rather synchronously |
123 | and pause. Note that, since mpv is implement rather synchronously |
… | |
… | |
126 | the "loadfile" command itself will run successfully. |
126 | the "loadfile" command itself will run successfully. |
127 | |
127 | |
128 | To unpause, we send another command, "set", to set the "pause" property |
128 | To unpause, we send another command, "set", to set the "pause" property |
129 | to "no", this time using the "cmd" method, which queues the command, but |
129 | to "no", this time using the "cmd" method, which queues the command, but |
130 | instead of waiting for a reply, it immediately returns a condvar that |
130 | instead of waiting for a reply, it immediately returns a condvar that |
131 | cna be used to receive results. |
131 | can be used to receive results. |
132 | |
132 | |
133 | This should then cause mpv to start playing the video. |
133 | This should then cause mpv to start playing the video. |
134 | |
134 | |
135 | It then again waits two seconds and quits. |
135 | It then again waits two seconds and quits. |
136 | |
136 | |
… | |
… | |
170 | playing. Also, most of the logic is now implement in event handlers. |
170 | playing. Also, most of the logic is now implement in event handlers. |
171 | |
171 | |
172 | The two events handlers we register are "start-file", which is emitted |
172 | The two events handlers we register are "start-file", which is emitted |
173 | by mpv once it has loaded a new file, and "end-file", which signals the |
173 | by mpv once it has loaded a new file, and "end-file", which signals the |
174 | end of a file (underscores are internally replaced by minus signs, so |
174 | end of a file (underscores are internally replaced by minus signs, so |
175 | you cna speicfy event names with either). |
175 | you can specify event names with either). |
176 | |
176 | |
177 | In the "start-file" event, we again set the "pause" property to "no" so |
177 | In the "start-file" event, we again set the "pause" property to "no" so |
178 | the movie starts playing. For the "end-file" event, we tell the main |
178 | the movie starts playing. For the "end-file" event, we tell the main |
179 | program to quit by invoking $quit. |
179 | program to quit by invoking $quit. |
180 | |
180 | |
… | |
… | |
216 | Enables tracing if true. In trace mode, output from mpv is |
216 | Enables tracing if true. In trace mode, output from mpv is |
217 | printed to standard error using a "mpv>" prefix, and commands |
217 | printed to standard error using a "mpv>" prefix, and commands |
218 | sent to mpv are printed with a ">mpv" prefix. |
218 | sent to mpv are printed with a ">mpv" prefix. |
219 | |
219 | |
220 | If a code reference is passed, then instead of printing to |
220 | If a code reference is passed, then instead of printing to |
221 | standard errort, this coderef is invoked with a first arfgument |
221 | standard error, this coderef is invoked with a first argument |
222 | being either "mpv>" or ">mpv", and the second argument being a |
222 | being either "mpv>" or ">mpv", and the second argument being a |
223 | string to display. The default implementation simply does this: |
223 | string to display. The default implementation simply does this: |
224 | |
224 | |
225 | sub { |
225 | sub { |
226 | warn "$_[0] $_[1]\n"; |
226 | warn "$_[0] $_[1]\n"; |
… | |
… | |
231 | on_key => $coderef->($mpv, $string) |
231 | on_key => $coderef->($mpv, $string) |
232 | These are invoked by the default method implementation of the |
232 | These are invoked by the default method implementation of the |
233 | same name - see below. |
233 | same name - see below. |
234 | |
234 | |
235 | $string = $mpv->escape_binary ($string) |
235 | $string = $mpv->escape_binary ($string) |
236 | This module excects all command data sent to mpv to be in unicode. |
236 | This module expects all command data sent to mpv to be in unicode. |
237 | Some things are not, such as filenames. To pass binary data such as |
237 | Some things are not, such as filenames. To pass binary data such as |
238 | filenames through a comamnd, you need to escape it using this |
238 | filenames through a command, you need to escape it using this |
239 | method. |
239 | method. |
240 | |
240 | |
241 | The simplest example is a "loadfile" command: |
241 | The simplest example is a "loadfile" command: |
242 | |
242 | |
243 | $mpv->cmd_recv (loadfile => $mpv->escape_binary ($path)); |
243 | $mpv->cmd_recv (loadfile => $mpv->escape_binary ($path)); |
244 | |
244 | |
245 | $started = $mpv->start (argument...) |
245 | $started = $mpv->start (argument...) |
246 | Starts mpv, passing the given arguemnts as extra arguments to mpv. |
246 | Starts mpv, passing the given arguments as extra arguments to mpv. |
247 | If mpv is already running, it returns false, otherwise it returns a |
247 | If mpv is already running, it returns false, otherwise it returns a |
248 | true value, so you can easily start mpv on demand by calling "start" |
248 | true value, so you can easily start mpv on demand by calling "start" |
249 | just before using it, and if it is already running, it will not be |
249 | just before using it, and if it is already running, it will not be |
250 | started again. |
250 | started again. |
251 | |
251 | |
252 | The arguments passwd to mpv are a set of hardcoded built-in |
252 | The arguments passed to mpv are a set of hard-coded built-in |
253 | arguments, followed by the arguments specified in the constructor, |
253 | arguments, followed by the arguments specified in the constructor, |
254 | followed by the arguments passwd to this method. The built-in |
254 | followed by the arguments passed to this method. The built-in |
255 | arguments currently are --no-input-terminal, --really-quiet (or |
255 | arguments currently are --no-input-terminal, --really-quiet (or |
256 | --quiet in "trace" mode), and "--input-ipc-client" (or equivalent). |
256 | --quiet in "trace" mode), and "--input-ipc-client" (or equivalent). |
257 | |
257 | |
258 | Some commonly used and/or even useful arguments you might want to |
258 | Some commonly used and/or even useful arguments you might want to |
259 | pass are: |
259 | pass are: |
… | |
… | |
361 | $position = $mpv->cmd_recv ("get_property", "playback-time"); |
361 | $position = $mpv->cmd_recv ("get_property", "playback-time"); |
362 | |
362 | |
363 | $mpv->bind_key ($INPUT => $string) |
363 | $mpv->bind_key ($INPUT => $string) |
364 | This is an extension implement by this module to make it easy to get |
364 | This is an extension implement by this module to make it easy to get |
365 | key events. The way this is implemented is to bind a |
365 | key events. The way this is implemented is to bind a |
366 | "client-message" witha first argument of "AnyEvent::MPV" and the |
366 | "client-message" with a first argument of "AnyEvent::MPV" and the |
367 | $string you passed. This $string is then passed to the "on_key" |
367 | $string you passed. This $string is then passed to the "on_key" |
368 | handle when the key is proessed, e.g.: |
368 | handle when the key is processed, e.g.: |
369 | |
369 | |
370 | my $mpv = AnyEvent::MPV->new ( |
370 | my $mpv = AnyEvent::MPV->new ( |
371 | on_key => sub { |
371 | on_key => sub { |
372 | my ($mpv, $key) = @_; |
372 | my ($mpv, $key) = @_; |
373 | |
373 | |
… | |
… | |
377 | }, |
377 | }, |
378 | ); |
378 | ); |
379 | |
379 | |
380 | $mpv_>bind_key (ESC => "letmeout"); |
380 | $mpv_>bind_key (ESC => "letmeout"); |
381 | |
381 | |
382 | You cna find a list of key names in the mpv documentation |
382 | You can find a list of key names in the mpv documentation |
383 | <https://mpv.io/manual/stable/#key-names>. |
383 | <https://mpv.io/manual/stable/#key-names>. |
384 | |
384 | |
385 | The key configuration is lost when mpv is stopped and must be |
385 | The key configuration is lost when mpv is stopped and must be |
386 | (re-)done after every "start". |
386 | (re-)done after every "start". |
387 | |
387 | |
… | |
… | |
390 | This method registers a callback to be invoked for a specific event. |
390 | This method registers a callback to be invoked for a specific event. |
391 | Whenever the event occurs, it calls the coderef with the $mpv |
391 | Whenever the event occurs, it calls the coderef with the $mpv |
392 | object, the $event name and the event object, just like the |
392 | object, the $event name and the event object, just like the |
393 | "on_event" method. |
393 | "on_event" method. |
394 | |
394 | |
395 | For a lst of events, see the mpv documentation |
395 | For a list of events, see the mpv documentation |
396 | <https://mpv.io/manual/stable/#list-of-events>. Any underscore in |
396 | <https://mpv.io/manual/stable/#list-of-events>. Any underscore in |
397 | the event name is replaced by a minus sign, so you can specify event |
397 | the event name is replaced by a minus sign, so you can specify event |
398 | names using underscores for easier quoting in Perl. |
398 | names using underscores for easier quoting in Perl. |
399 | |
399 | |
400 | In void context, the handler stays registered until "stop" is |
400 | In void context, the handler stays registered until "stop" is |
… | |
… | |
424 | |
424 | |
425 | For a list of properties that you can observe, see the mpv |
425 | For a list of properties that you can observe, see the mpv |
426 | documentation <https://mpv.io/manual/stable/#property-list>. |
426 | documentation <https://mpv.io/manual/stable/#property-list>. |
427 | |
427 | |
428 | Due to the (sane :) way mpv handles these requests, you will always |
428 | Due to the (sane :) way mpv handles these requests, you will always |
429 | get a property cxhange event right after registering an observer |
429 | get a property change event right after registering an observer |
430 | (meaning you don't have to query the current value), and it is also |
430 | (meaning you don't have to query the current value), and it is also |
431 | possible to register multiple observers for the same property - they |
431 | possible to register multiple observers for the same property - they |
432 | will all be handled properly. |
432 | will all be handled properly. |
433 | |
433 | |
434 | When called in void context, the observer stays in place until mpv |
434 | When called in void context, the observer stays in place until mpv |
435 | is stopped. In any otrher context, these methods return a guard |
435 | is stopped. In any other context, these methods return a guard |
436 | object that, when it goes out of scope, unregisters the observe |
436 | object that, when it goes out of scope, unregisters the observe |
437 | using "unobserve_property". |
437 | using "unobserve_property". |
438 | |
438 | |
439 | Internally, this method uses observer ids of 2**52 |
439 | Internally, this method uses observer ids of 2**52 |
440 | (0x10000000000000) or higher - it will not interfere with lower |
440 | (0x10000000000000) or higher - it will not interfere with lower |
441 | ovserver ids, so it is possible to completely ignore this system and |
441 | observer ids, so it is possible to completely ignore this system and |
442 | execute "observe_property" commands yourself, whilst listening to |
442 | execute "observe_property" commands yourself, whilst listening to |
443 | "property-change" events - as long as your ids stay below 2**52. |
443 | "property-change" events - as long as your ids stay below 2**52. |
444 | |
444 | |
445 | Example: register observers for changtes in "aid" and "sid". Note |
445 | Example: register observers for changes in "aid" and "sid". Note |
446 | that a dummy statement is added to make sure the method is called in |
446 | that a dummy statement is added to make sure the method is called in |
447 | void context. |
447 | void context. |
448 | |
448 | |
449 | sub register_observers { |
449 | sub register_observers { |
450 | my ($mpv) = @_; |
450 | my ($mpv) = @_; |
… | |
… | |
465 | SUBCLASSING |
465 | SUBCLASSING |
466 | Like most perl objects, "AnyEvent::MPV" objects are implemented as |
466 | Like most perl objects, "AnyEvent::MPV" objects are implemented as |
467 | hashes, with the constructor simply storing all passed key-value pairs |
467 | hashes, with the constructor simply storing all passed key-value pairs |
468 | in the object. If you want to subclass to provide your own "on_*" |
468 | in the object. If you want to subclass to provide your own "on_*" |
469 | methods, be my guest and rummage around in the internals as much as you |
469 | methods, be my guest and rummage around in the internals as much as you |
470 | wish - the only guarantee that this module dcoes is that it will not use |
470 | wish - the only guarantee that this module does is that it will not use |
471 | keys with double colons in the name, so youc an use those, or chose to |
471 | keys with double colons in the name, so you can use those, or chose to |
472 | simply not care and deal with the breakage. |
472 | simply not care and deal with the breakage. |
473 | |
473 | |
474 | If you don't want to go to the effort of subclassing this module, you |
474 | If you don't want to go to the effort of subclassing this module, you |
475 | can also specify all event handlers as constructor keys. |
475 | can also specify all event handlers as constructor keys. |
476 | |
476 | |
… | |
… | |
478 | Here are some real-world code snippets, thrown in here mainly to give |
478 | Here are some real-world code snippets, thrown in here mainly to give |
479 | you some example code to copy. |
479 | you some example code to copy. |
480 | |
480 | |
481 | doomfrontend |
481 | doomfrontend |
482 | At one point I replaced mythtv-frontend by my own terminal-based video |
482 | At one point I replaced mythtv-frontend by my own terminal-based video |
483 | player (based on rxvt-unicode). I toyed with the diea of using mpv's |
483 | player (based on rxvt-unicode). I toyed with the idea of using mpv's |
484 | subtitle engine to create the user interface, but that is hard to use |
484 | subtitle engine to create the user interface, but that is hard to use |
485 | since you don't know how big your letters are. It is also where most of |
485 | since you don't know how big your letters are. It is also where most of |
486 | this modules code has originally been developed in. |
486 | this modules code has originally been developed in. |
487 | |
487 | |
488 | It uses a unified input queue to handle various remote controls, so its |
488 | It uses a unified input queue to handle various remote controls, so its |
… | |
… | |
513 | |
513 | |
514 | --audio-client-name=doomfrontend |
514 | --audio-client-name=doomfrontend |
515 | --osd-on-seek=msg-bar --osd-bar-align-y=-0.85 --osd-bar-w=95 |
515 | --osd-on-seek=msg-bar --osd-bar-align-y=-0.85 --osd-bar-w=95 |
516 | --sub-auto=exact --audio-file-auto=exact |
516 | --sub-auto=exact --audio-file-auto=exact |
517 | |
517 | |
518 | Since it runs on a TV without a desktop environemnt, it tries to keep |
518 | Since it runs on a TV without a desktop environment, it tries to keep |
519 | complications such as dbus away and the screensaver happy: |
519 | complications such as dbus away and the screensaver happy: |
520 | |
520 | |
521 | # prevent xscreensaver from doing something stupid, such as starting dbus |
521 | # prevent xscreensaver from doing something stupid, such as starting dbus |
522 | $ENV{DBUS_SESSION_BUS_ADDRESS} = "/"; # prevent dbus autostart for sure |
522 | $ENV{DBUS_SESSION_BUS_ADDRESS} = "/"; # prevent dbus autostart for sure |
523 | $ENV{XDG_CURRENT_DESKTOP} = "generic"; |
523 | $ENV{XDG_CURRENT_DESKTOP} = "generic"; |
… | |
… | |
547 | KP_INS => 0, # KP0, but different |
547 | KP_INS => 0, # KP0, but different |
548 | ) { |
548 | ) { |
549 | $mpv->bind_key ($_->[0] => $_->[1]); |
549 | $mpv->bind_key ($_->[0] => $_->[1]); |
550 | } |
550 | } |
551 | |
551 | |
552 | It also reacts to sponsorblock chapters, so it needs to know when vidoe |
552 | It also reacts to sponsorblock chapters, so it needs to know when video |
553 | chapters change. Preadting "AnyEvent::MPV", it handles observers |
553 | chapters change. Predating "AnyEvent::MPV", it handles observers |
554 | manually: |
554 | manually instead of using "observe_property": |
555 | |
555 | |
556 | $mpv->cmd (observe_property => 1, "chapter-metadata"); |
556 | $mpv->cmd (observe_property => 1, "chapter-metadata"); |
557 | |
557 | |
558 | It also tries to apply an mpv profile, if it exists: |
558 | It also tries to apply an mpv profile, if it exists: |
559 | |
559 | |
… | |
… | |
563 | }; |
563 | }; |
564 | |
564 | |
565 | Most of the complicated parts deal with saving and restoring per-video |
565 | Most of the complicated parts deal with saving and restoring per-video |
566 | data, such as bookmarks, playing position, selected audio and subtitle |
566 | data, such as bookmarks, playing position, selected audio and subtitle |
567 | tracks and so on. However, since it uses Coro, it can conveniently block |
567 | tracks and so on. However, since it uses Coro, it can conveniently block |
568 | and wait for replies, which is n ot possible in purely event based |
568 | and wait for replies, which is not possible in purely event based |
569 | programs, as you are not allowed to block inside event callbacks in most |
569 | programs, as you are not allowed to block inside event callbacks in most |
570 | event loops. This simplifies the code quite a bit. |
570 | event loops. This simplifies the code quite a bit. |
571 | |
571 | |
572 | When the file to be played is a Tv recording done by mythtv, it uses the |
572 | When the file to be played is a TV recording done by mythtv, it uses the |
573 | "appending" protocol and deinterlacing: |
573 | "appending" protocol and deinterlacing: |
574 | |
574 | |
575 | if (is_myth $mpv_path) { |
575 | if (is_myth $mpv_path) { |
576 | $mpv_path = "appending://$mpv_path"; |
576 | $mpv_path = "appending://$mpv_path"; |
577 | $initial_deinterlace = 1; |
577 | $initial_deinterlace = 1; |
… | |
… | |
638 | |
638 | |
639 | $mpv->cmd ("set_property", "deinterlace", "yes") |
639 | $mpv->cmd ("set_property", "deinterlace", "yes") |
640 | if $initial_deinterlace; |
640 | if $initial_deinterlace; |
641 | |
641 | |
642 | There is a lot going on here. First it seeks to the actual playback |
642 | There is a lot going on here. First it seeks to the actual playback |
643 | position, if it is not at the start of the file (it would probaby be |
643 | position, if it is not at the start of the file (it would probably be |
644 | more efficient to set the starting position before loading the file, |
644 | more efficient to set the starting position before loading the file, |
645 | though, but this is good enough). |
645 | though, but this is good enough). |
646 | |
646 | |
647 | Then it plays with the display fps, to set it to something harmonious |
647 | Then it plays with the display fps, to set it to something harmonious |
648 | w.r.t. the video framerate. |
648 | w.r.t. the video framerate. |
… | |
… | |
650 | If the file does not have a video part, it assumes it is an audio file |
650 | If the file does not have a video part, it assumes it is an audio file |
651 | and sets a visualizer. |
651 | and sets a visualizer. |
652 | |
652 | |
653 | Also, a number of properties are not global, but per-file. At the |
653 | Also, a number of properties are not global, but per-file. At the |
654 | moment, this is "audio-delay", and the current audio/subtitle track, |
654 | moment, this is "audio-delay", and the current audio/subtitle track, |
655 | which it sets, and also creates an observer. Again, this doesn'T use the |
655 | which it sets, and also creates an observer. Again, this doesn't use the |
656 | observe functionality of this module, but handles it itself, assigning |
656 | observe functionality of this module, but handles it itself, assigning |
657 | obsevrer ids 100+ to temporary/per-file observers. |
657 | observer ids 100+ to temporary/per-file observers. |
658 | |
658 | |
659 | Lastly, it sets some global (or per-youtube-uploader) parameters, such |
659 | Lastly, it sets some global (or per-youtube-uploader) parameters, such |
660 | as speed, and unpauses. Property changes are handled like other input |
660 | as speed, and unpauses. Property changes are handled like other input |
661 | events: |
661 | events: |
662 | |
662 | |
… | |
… | |
735 | $mpv->cmd ("unobserve_property", $oid--); |
735 | $mpv->cmd ("unobserve_property", $oid--); |
736 | } |
736 | } |
737 | |
737 | |
738 | $PLAYING_STATE->{curpos} = $mpv->cmd_recv ("get_property", "playback-time"); |
738 | $PLAYING_STATE->{curpos} = $mpv->cmd_recv ("get_property", "playback-time"); |
739 | |
739 | |
740 | And thats most of the mpv-related code. |
740 | And that's most of the mpv-related code. |
741 | |
741 | |
742 | Gtk2::CV |
742 | Gtk2::CV |
743 | Gtk2::CV is low-feature image viewer that I use many times daily because |
743 | Gtk2::CV is low-feature image viewer that I use many times daily because |
744 | it can handle directories with millions of files without falling over. |
744 | it can handle directories with millions of files without falling over. |
745 | It also had the ability to play videos for ages, but it used an older, |
745 | It also had the ability to play videos for ages, but it used an older, |
746 | crappier protocol to talk to mpv and used ffprobe before playing each |
746 | crappier protocol to talk to mpv and used ffprobe before playing each |
747 | file instead of letting mpv handle format/size detection. |
747 | file instead of letting mpv handle format/size detection. |
748 | |
748 | |
749 | After writing this module, I decided to upgprade Gtk2::CV by making use |
749 | After writing this module, I decided to upgrade Gtk2::CV by making use |
750 | of it, with the goal of getting rid of ffprobe and being ablew to reuse |
750 | of it, with the goal of getting rid of ffprobe and being able to reuse |
751 | mpv processes, which would have a multitude of speed benefits (for |
751 | mpv processes, which would have a multitude of speed benefits (for |
752 | example, fork+exec of mpv caused the kernel to close all file |
752 | example, fork+exec of mpv caused the kernel to close all file |
753 | descriptors, which could take minutes if a large file was being copied |
753 | descriptors, which could take minutes if a large file was being copied |
754 | via NFS, as the kernel waited for thr buffers to be flushed on close - |
754 | via NFS, as the kernel waited for the buffers to be flushed on close - |
755 | not having to start mpv gets rid of this issue). |
755 | not having to start mpv gets rid of this issue). |
756 | |
756 | |
757 | Setting up is only complicated by the fact that mpv needs to be embedded |
757 | Setting up is only complicated by the fact that mpv needs to be embedded |
758 | into an existing window. To keep control of all inputs, Gtk2::CV puts an |
758 | into an existing window. To keep control of all inputs, Gtk2::CV puts an |
759 | eventbox in front of mpv, so mpv receives no input events: |
759 | eventbox in front of mpv, so mpv receives no input events: |
… | |
… | |
805 | ); |
805 | ); |
806 | |
806 | |
807 | $self->{mpv}->cmd ("script-message" => "osc-visibility" => "never", "dummy"); |
807 | $self->{mpv}->cmd ("script-message" => "osc-visibility" => "never", "dummy"); |
808 | $self->{mpv}->cmd ("osc-idlescreen" => "no"); |
808 | $self->{mpv}->cmd ("osc-idlescreen" => "no"); |
809 | |
809 | |
810 | It also prepares a hack to force a ConfigureNotify event on every vidoe |
810 | It also prepares a hack to force a ConfigureNotify event on every video |
811 | reconfig: |
811 | reconfig event: |
812 | |
812 | |
813 | # force a configurenotify on every video-reconfig |
813 | # force a configurenotify on every video-reconfig |
814 | $self->{mpv_reconfig} = $self->{mpv}->register_event (video_reconfig => sub { |
814 | $self->{mpv_reconfig} = $self->{mpv}->register_event (video_reconfig => sub { |
815 | my ($mpv, $event, $data) = @_; |
815 | my ($mpv, $event, $data) = @_; |
816 | |
816 | |
… | |
… | |
832 | $self->{mpv}->cmd (set_property => "pause" => "yes"); |
832 | $self->{mpv}->cmd (set_property => "pause" => "yes"); |
833 | $self->{mpv}->cmd ("playlist_remove", "current"); |
833 | $self->{mpv}->cmd ("playlist_remove", "current"); |
834 | $self->{mpv}->cmd (set_property => "video-rotate" => 0); |
834 | $self->{mpv}->cmd (set_property => "video-rotate" => 0); |
835 | $self->{mpv}->cmd (set_property => "lavfi-complex" => ""); |
835 | $self->{mpv}->cmd (set_property => "lavfi-complex" => ""); |
836 | |
836 | |
837 | Loading a file is a bit more complicated, as bluray and DVD rips are |
837 | Loading a file is a bit more complicated, as blu-ray and DVD rips are |
838 | supported: |
838 | supported: |
839 | |
839 | |
840 | if ($moviedir) { |
840 | if ($moviedir) { |
841 | if ($moviedir eq "br") { |
841 | if ($moviedir eq "br") { |
842 | $mpv->cmd (set => "bluray-device" => $path); |
842 | $mpv->cmd (set => "bluray-device" => $path); |
… | |
… | |
854 | |
854 | |
855 | After this, "Gtk2::CV" waits for the file to be loaded, video to be |
855 | After this, "Gtk2::CV" waits for the file to be loaded, video to be |
856 | configured, and then queries the video size (to resize its own window) |
856 | configured, and then queries the video size (to resize its own window) |
857 | and video format (to decide whether an audio visualizer is needed for |
857 | and video format (to decide whether an audio visualizer is needed for |
858 | audio playback). The problematic word here is "wait", as this needs to |
858 | audio playback). The problematic word here is "wait", as this needs to |
859 | be imploemented using callbacks. |
859 | be implemented using callbacks. |
860 | |
860 | |
861 | This made the code much harder to write, as the whole setup is very |
861 | This made the code much harder to write, as the whole setup is very |
862 | asynchronous ("Gtk2::CV" talks to the command interface in mpv, which |
862 | asynchronous ("Gtk2::CV" talks to the command interface in mpv, which |
863 | talks to the decode and playback parts, all of which run asynchronously |
863 | talks to the decode and playback parts, all of which run asynchronously |
864 | w.r.t. each other. In practise, this can mean that "Gtk2::CV" waits for |
864 | w.r.t. each other. In practise, this can mean that "Gtk2::CV" waits for |
… | |
… | |
880 | |
880 | |
881 | $guards->{file_loaded} = $mpv->register_event (file_loaded => sub { |
881 | $guards->{file_loaded} = $mpv->register_event (file_loaded => sub { |
882 | delete $guards->{file_loaded}; |
882 | delete $guards->{file_loaded}; |
883 | return if $guards != $self->{mpv_guards}; |
883 | return if $guards != $self->{mpv_guards}; |
884 | |
884 | |
885 | Commands do not have guards since they cnanot be cancelled, so we don't |
885 | Commands do not have guards since they cannot be cancelled, so we don't |
886 | have to do this for commands. But what prevents us form misinterpreting |
886 | have to do this for commands. But what prevents us form misinterpreting |
887 | an old event? Since mpv (by default) handles commands synchronously, we |
887 | an old event? Since mpv (by default) handles commands synchronously, we |
888 | can queue a dummy command, whose only purpose is to tell us when all |
888 | can queue a dummy command, whose only purpose is to tell us when all |
889 | previous commands are done. We use "get_version" for this. |
889 | previous commands are done. We use "get_version" for this. |
890 | |
890 | |