This is an old revision of the document!
mplayer-resume
mplayer-resume is a PHP shell script I wrote to resume playback of files through mplayer. It works using slave mode and LIRC with mplayer, which outputs the variables to stdout. The wrapper script then keeps these values, and uses them to jump to that last point.
Note that this code is an archived copy of the source code. It's unmaintained, but probably works.
mplayer-resume 2.0
#!/usr/bin/env php <? // By default, save files in ~/.mplayer/playback/ $home = getenv('HOME'); $save_files_to = "$home/.mplayer/playback/"; /** * * @author Steve Dibb <steve dot dibb at gmail dot com> * @copyright public-domain * @date 2009-08-11 * @version 2.0 * @homepage http://spaceparanoids.org/trac/bend/wiki/mplayer-resume * * Run time dependencies: * PHP >= 4.3.0 with CLI and PCRE - http://php.net/ * MPlayer - http://mplayerhq.hu/ * * See README for documentation on usage * Quick example: mplayer-resume --filename "movie.mkv" * */ /** * Sends a string to stdout with a terminating line break * * @param string * @param boolean display "mplayer-resume:" before each string * */ function stdout($str, $leading_string = true) { if(is_string($str)) { $str = rtrim($str); if($leading_string) $str = "mplayer-resume: $str"; fwrite(STDOUT, "$str\n"); return true; } else return false; } /** * Sends a string to stderr with a terminating line break * * @param string * */ function stderr($str) { if(is_string($str)) { $str = rtrim($str); fwrite(STDERR, "mplayer-resume: $str\n"); return true; } else return false; } /** * Parse CLI arguments * * If a value is unset, it will be set to true * * @param $argc argument count (system variable) * @param $argv argument array (system variable) * @return array */ function parseArguments($argc, $argv) { $arr = array(); if($argc > 1) { // Drop the binary command array_shift($argv); for($x = 0; $x < count($argv); $x++) { if(preg_match('/^--\w+/', $argv[$x]) > 0) { $argv[$x] = preg_replace('/^--/', '', $argv[$x]); $arr[$argv[$x]] = true; } elseif(in_array($argv[($x-1)], array_keys($arr))) { $arr[$argv[($x-1)]] = $argv[$x]; } } return $arr; } else return array(); } // Get the mplayer-resume arguments (not mplayer's) $args = parseArguments($argc, $argv); if($args['help'] || !count($args) || is_bool($movie) || $argc === 1) { stdout("Usage:\tmplayer-resume --filename <filename> [options] [mplayer options]", false); stdout("", false); stdout("Basic options:", false); stdout("", false); stdout(" --filename <filename>\tFilename to play with MPlayer", false); stdout(" --help \t\tThis help output", false); stdout("", false); stdout("Extended options:", false); stdout("", false); stdout(" --use-dir-conf\t\tPass \"-include <dirname of filename>/mplayer.conf\" to", false); stdout("\t\t\tmplayer if config file exists in same directory of", false); stdout("\t\t\tmedia file. Similar to -use-filedir-conf.", false); stdout("", false); stdout("Example: $ mplayer-resume --filename \"A Man For All Seasons.mkv\" -fs -ao alsa", false); stdout("", false); stdout("mplayer-resume works by capturing events sent to MPlayer's slave mode", false); stdout("when exiting. You will need to setup your MPlayer configuration files", false); stdout("to send the correct events in slave mode before this script will work.", false); stdout("", false); stdout("See the webpage for documentation:", false); stdout("http://spaceparanoids.org/trac/bend/wiki/mplayer-resume", false); die; } // Movie filename (used internally) $movie = $filename = $args['filename']; // PHP doesn't parse ~ as $HOME, so fix it ourselves if(substr($movie, 0, 1) === "~") $movie = $home.substr($movie, 1); // Filename (escaped, ready to send to mplayer) $mplayer_filename = escapeshellarg($movie); stdout($movie); stdout($mplayer_filename); // Check to see the config directory exists. If not, try and create it. if(!is_dir($save_files_to)) { if(!mkdir($save_files_to)) { stderr("Please make sure the directory $save_files_to exists and is both readable and writable by this user"); exit(1); } } // Make sure I can save playback files if(!is_writable($save_files_to) || !is_readable($save_files_to)) { stderr("I can't read from and/or write to $save_files_to"); exit(1); } // Correct *some* human error ;) if(substr($save_files_to, -1, 1) != '/') $save_files_to .= '/'; // Drop the binary from list of arguments array_shift($argv); // Put the arguments back together again $str_args = implode(' ', $argv); // Drop the filename command $str_args = str_replace('--filename', '', $str_args); // Keep the movie filename separate from args $str_args = str_replace($filename, '', $str_args); // Remove arguments which will break the script // -really-quiet means no output to our slave commands $str_args = str_replace('-really-quiet', '', $str_args); // Where the seek position will be saved $basename = basename($movie); $txt = $save_files_to.$basename.".txt"; // If there is already a playback file, read it and start // from that position. if(file_exists($txt)) { $ss = trim(file_get_contents($txt)); // One more check for garbage if(is_numeric($ss) && $ss > 0) $flags = " -ss $ss "; } /** Custom MPlayer workarounds */ $custom_flags = array(); $str_custom_flags = ""; // --use-dir-conf // This is similar to -use-filedir-conf in mplayer. It checks // to see if an "mplayer.conf" file exists in the directory of the // media file, and includes that. if($args['use-dir-conf']) { $str_args = str_replace("--use-dir-conf", "", $str_args); $conf = dirname($movie)."/mplayer.conf"; if(file_exists($conf)) $custom_flags[] = "-include ".escapeshellarg("$conf"); } if(count($custom_flags)) $str_custom_flags = implode(" ", $custom_flags); // Build the execution string $exec = "mplayer $mplayer_filename -quiet ".escapeshellcmd("$flags $str_args")." $str_custom_flags"; stdout($exec); // Execute the command, save output to an array, and grab // return code to see if mplayer throws an error. exec($exec, $arr, $return); // If mplayer dies with a positive exit code, then it failed. // Don't write to or delete the saved position, and die // with the same exit code. if($return !== 0) { stderr("mplayer died unexpectedly"); exit($return); } // If the file didn't even exist, mplayer will die, and so will me if(!file_exists($movie)) { stderr("Couldn't find the filename $movie"); exit(1); } // Grep out the details we need from output $key_position = current(preg_grep('/^ANS_TIME_POSITION\b/', $arr)); $key_filename = current(preg_grep('/^ANS_FILENAME\b/', $arr)); // Get the position (in seconds) of the movie // Original format is ANS_TIME_POSITION=123.45 $endpos = preg_replace('/^ANS_TIME_POSITION\=/', '', $key_position); // Get the filename of the movie we were playing // Original format is ANS_FILENAME='Your_Movie.avi' $slave_filename = preg_replace( array('/^ANS_FILENAME\=\'/', '/\'$/'), array('', ''), $key_filename); // If we are playing from a playlist, then the two filenames // will not match. Change the filename to be what we were // actually playing versus what we started out playing. if($slave_filename != $movie && !empty($slave_filename)) { $movie =& $slave_filename; $txt = $save_files_to.basename($movie).".txt"; } // If it's a negative value, that means you've seeked // past/to the end of the file, so just remove the old one. if($endpos < 1 && file_exists($txt)) unlink($txt); // No end position passed to mplayer-resume, so exit quietly elseif(empty($endpos)) { stderr("No end position sent to save."); exit(0); } // Save the (positive) playback position to the file else { // Generic error message, fix your stupid permissions $error_msg = "Cannot save file, please check write permissions for this user in $save_files_to"; fwrite(fopen($txt, 'w'), $endpos) or stderr($error_msg); } ?>
ChangeLog
2.0 (2009-08-11) - Add --filename argument to specify filename directly, instead of trying to guess what it is. - Add optional argument --use-filedir-conf, to include mplayer.conf in local directory, and pass -include mplayer.conf to mplayer. 1.6 (2008-12-16) - Check exit codes on mplayer, so that if mplayer quits unexpectedly, mplayer-resume won't kill the resume point. - Send exit codes 1.5 (2008-01-12) - Allow spaces in filenames. Use mplayer-resume "filename" - Get the filename from MPlayer on exit, and use that to save the file to. Useful for playlists. See README. 1.3 (2006-09-15) - Call env instead of php directly - Get $HOME environment variable to save files to 1.2 - Documentation updates