Update of /cvsroot/freevo/freevo/src/video/plugins In directory sc8-pr-cvs1:/tmp/cvs-serv27796/plugins
Modified Files: imdb.py Added Files: mplayer.py Log Message: o mmpython support o mplayer is now a plugin --- NEW FILE: mplayer.py --- #if 0 /* # ----------------------------------------------------------------------- # mplayer.py - the Freevo MPlayer module for video # ----------------------------------------------------------------------- # $Id: mplayer.py,v 1.1 2003/06/29 20:43:30 dischi Exp $ # # Notes: # Perhaps we should move the filetype specific stuff (like the one for vob) # into the config files... # # i.e. # # MP_CUSTOM = { # '.vob' = '-ac hwac3 ...', # '.rm' = '-forceidx', # ... # } # # Todo: # # ----------------------------------------------------------------------- # $Log: mplayer.py,v $ # Revision 1.1 2003/06/29 20:43:30 dischi # o mmpython support # o mplayer is now a plugin # # Revision 1.43 2003/06/23 00:16:04 outlyer # Fixed the regular expression. It wasn't making bookmarks when less than # 1000 seconds has elapsed. I don't know who made this one, but just in case, # # here is the old one: # # self.RE_TIME = re.compile("^A:?([0-9]+)").match # # The '?' means, match ':' zero or one times, which doesn't make sense in this context. # # The new one: # # self.RE_TIME = re.compile("^A: *([0-9]+)").match # # In this case '*' means match ' ' zero or more times. # # I also removed the comment about multiple bookmarks since you can have as many bookmarks # as you want. The limitation with bookmarks is that mplayer isn't great at seeking in files # other than avi; DVD, and mpg files will have varying results. # # Revision 1.42 2003/06/10 18:02:57 dischi # Bad alang hack for mplayer and badly mastered DVDs. Restart mplayer if we # have audio tracks in the ifo that aren't there. # # Revision 1.41 2003/05/28 15:34:43 dischi # fixed seeking bug # # Revision 1.40 2003/05/28 15:02:02 dischi # reactivated seeking by first pressing 0 # # Revision 1.39 2003/05/27 17:53:35 dischi # Added new event handler module # # Revision 1.38 2003/05/06 03:11:20 outlyer # Whoops... commited something specific to my machine... # # Revision 1.37 2003/05/05 21:11:15 dischi # save video width and height # # Revision 1.36 2003/05/05 15:14:55 outlyer # Fixed a crash in the bookmarks submenu, and fixed the long standing bug # where times greater than 999 seconds (16m39s) wouldn't be recorded, because # mplayer logs time like this: # # A: XXX # # but after it reaches 1000, # # A:XXXX # # and the regular expression that got the time used a space. # # Revision 1.35 2003/04/26 20:55:44 dischi # Removed MPLAYER_ARGS_* and added a hash MPLAYER_ARGS to set args for # all different kinds of files. Also added MPLAYER_SOFTWARE_SCALER to use # the software scaler for fast CPUs. Also fixed a small bug in mplayer.py # for video. # # Revision 1.34 2003/04/20 15:54:32 dischi # do not stop on select # # Revision 1.33 2003/04/20 12:43:34 dischi # make the rc events global in rc.py to avoid get_singleton. There is now # a function app() to get/set the app. Also the events should be passed to # the daemon plugins when there is no handler for them before. Please test # it, especialy the mixer functions. # # Revision 1.32 2003/04/20 10:55:41 dischi # mixer is now a plugin, too # # Revision 1.31 2003/04/12 18:30:04 dischi # add support for audio/subtitle selection for avis, too # # Revision 1.30 2003/04/06 21:13:04 dischi # o Switched to the new main skin # o some cleanups (removed unneeded inports) # # Revision 1.29 2003/03/23 20:00:26 dischi # Added patch from Matthieu Weber for better mplayer_options and subitem # handling # # Revision 1.28 2003/03/23 15:19:39 gsbarbieri # Fixed a bug when ESC was pressed while watching a movie. Freevo used to crash. # Fixed key conflict, rc.SELECT was used to exit and seek to a specifc position, # now rc.ENTER (e) is used to seek. # # Revision 1.27 2003/03/17 18:54:44 outlyer # Some changes for the bookmarks # o videoitem.py - Added bookmark menu, bookmark "parser" and menu generation, # haven't figured out how to pass the timecode to mplayer though. I tried # setting mplayer_options, but self.play seems to just ignore them. I don't # know how to pass anything to self.play either. ARGH. # o mplayer.py - commented out two extraneous prints. # # Revision 1.26 2003/03/17 16:34:33 outlyer # Added preliminary movie bookmarks (i.e. places to jump to on next play) # Currently only writing the bookmarks does anything; I'm going to have to # add a menu of bookmarks to the menu afterwards. # # Note that the get_bookmarkfile thing should be replaced with something less # flaky than the path+filename of the movie, but this is good for a initial # go. # # Revision 1.25 2003/03/17 15:47:16 outlyer # Merged patch from Angel <[EMAIL PROTECTED]> for "Jump to" # functionality. # # # ----------------------------------------------------------------------- # Freevo - A Home Theater PC framework # Copyright (C) 2002 Krister Lagerstrom, et al. # Please see the file freevo/Docs/CREDITS for a complete list of authors. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MER- # CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ----------------------------------------------------------------------- */ #endif import time, os import threading, signal import config # Configuration handler. reads config file. import util # Various utilities import childapp # Handle child applications import osd # The OSD class, used to communicate with the OSD daemon import rc # The RemoteControl class. from event import * import plugin # RegExp import re DEBUG = config.DEBUG TRUE = 1 FALSE = 0 # Setting up the default objects: osd = osd.get_singleton() # contains an initialized MPlayer() object mplayer = None class PluginInterface(plugin.Plugin): """ Mplayer plugin for the video player. Use mplayer to play all video files. """ def __init__(self): global mplayer # create the mplayer object plugin.Plugin.__init__(self) mplayer = util.SynchronizedObject(MPlayer()) # register it as the object to play audio plugin.register(mplayer, plugin.VIDEO_PLAYER) def vop_append(command): """ Change a mplayer command to support more than one -vop parameter. This function will grep all -vop parameter from the command and add it at the end as one vop argument """ ret = '' vop = '' next_is_vop = FALSE for arg in command.split(' '): if next_is_vop: vop += ',%s' % arg next_is_vop = FALSE elif arg == '-vop': next_is_vop=TRUE else: ret += '%s ' % arg if vop: return '%s -vop %s' % (ret,vop[1:]) return ret class MPlayer: """ the main class to control mplayer """ def __init__(self): self.thread = MPlayer_Thread() self.thread.setDaemon(1) self.thread.start() self.mode = None self.filename = None self.app_mode = 'video' self.seek = 0 self.seek_timer = threading.Timer(0, self.reset_seek) def play(self, filename, options, item, mode = None): """ play a audioitem with mplayer """ self.parameter = (filename, options, item, mode) if not mode: mode = item.mode # Is the file streamed over the network? if filename.find('://') != -1: # Yes, trust the given mode network_play = 1 else: network_play = 0 self.filename = filename self.mode = mode # setting global var to mode. if DEBUG: print 'MPlayer.play(): mode=%s, filename=%s' % (mode, filename) if mode == 'file' and not os.path.isfile(filename) and not network_play: # This event allows the videoitem which contains subitems to # try to play the next subitem return '%s\nnot found' % os.path.basename(filename) # Build the MPlayer command mpl = '--prio=%s %s %s -slave -ao %s' % (config.MPLAYER_NICE, config.MPLAYER_CMD, config.MPLAYER_ARGS_DEF, config.MPLAYER_AO_DEV) additional_args = '' if mode == 'file': try: mode = os.path.splitext(filename)[1] except: pass elif mode == 'dvdnav': additional_args = '-alang %s' % config.DVD_LANG_PREF elif mode == 'vcd': # Filename is VCD title filename = 'vcd://%s' % filename elif mode == 'dvd': # Filename is DVD title filename = 'dvd://%s' % filename if config.DVD_LANG_PREF: # There are some bad mastered DVDs out there. E.g. the specials on # the German Babylon 5 Season 2 disc claim they have more than one # audio track, even more then on en. But only the second en works, # mplayer needs to be started without -alang to find the track if hasattr(item, 'mplayer_audio_broken') and item.mplayer_audio_broken: print '*** dvd audio broken, try without alang ***' else: additional_args = '-alang %s' % config.DVD_LANG_PREF if config.DVD_SUBTITLE_PREF: # Only use if defined since it will always turn on subtitles # if defined additional_args += ' -slang %s' % config.DVD_SUBTITLE_PREF else: print "Don't know what do play!" print "What is: " + str(filename) print "What is mode: " + mode print "What is: " + mpl return 'Unknown media: %s' % os.path.basename(filename) if not config.MPLAYER_ARGS.has_key(mode): mode = 'default' # Mplayer command and standard arguments mpl += (' ' + config.MPLAYER_ARGS[mode] + ' ' + additional_args + \ ' -v -vo ' + config.MPLAYER_VO_DEV + config.MPLAYER_VO_DEV_OPTS) if options: mpl += (' ' + options) # use software scaler? if mpl.find(' -nosws ') > 0: mpl = (mpl[:mpl.find(' -nosws ')] + mpl[mpl.find(' -nosws ')+7:]) elif mpl.find(' -framedrop ') == -1 and mpl.find(' -framedrop ') == -1: mpl += (' ' + config.MPLAYER_SOFTWARE_SCALER ) # XXX Some testcode by Krister: if (os.path.isfile('./freevo_xwin') and osd.sdl_driver == 'x11' and config.MPLAYER_USE_WID): if DEBUG: print 'Got freevo_xwin and x11' os.system('rm -f /tmp/freevo.wid') os.system('./runapp ./freevo_xwin 0 0 %s %s > /tmp/freevo.wid &' % (osd.width, osd.height)) time.sleep(1) if os.path.isfile('/tmp/freevo.wid'): if DEBUG: print 'Got freevo.wid' try: wid = int(open('/tmp/freevo.wid').read().strip(), 16) mpl += ' -wid 0x%08x -xy %s -monitoraspect 4:3' % \ (wid, osd.width) if DEBUG: print 'Got WID = 0x%08x' % wid except: pass command = mpl + ' "' + filename + '"' command=vop_append(command) if plugin.getbyname('MIXER'): plugin.getbyname('MIXER').reset() self.file = item self.thread.play_mode = self.mode self.thread.item = item self.item = item if DEBUG: print 'MPlayer.play(): Starting thread, cmd=%s' % command rc.app(self) self.thread.mode = 'play' self.thread.command = command self.thread.mode_flag.set() return None def stop(self): """ Stop mplayer and set thread to idle """ self.thread.mode = 'stop' self.thread.mode_flag.set() self.thread.item = None rc.app(None) while self.thread.mode == 'stop': time.sleep(0.3) def eventhandler(self, event): """ eventhandler for mplayer control. If an event is not bound in this function it will be passed over to the items eventhandler """ if event == VIDEO_MANUAL_SEEK: self.seek = 0 rc.set_context('input') return TRUE if event.context == 'input': if event in INPUT_ALL_NUMBERS: self.reset_seek_timeout() self.seek = self.seek * 10 + int(event); return TRUE elif event == INPUT_ENTER: self.seek_timer.cancel() self.seek *= 60 self.thread.app.write('seek ' + str(self.seek) + ' 2\n') print "seek "+str(self.seek)+" 2\n" self.seek = 0 return TRUE elif event == INPUT_QUIT: print 'seek stopped' self.seek_timer.cancel() self.seek = 0 return TRUE if event == STOP: if self.mode == 'dvdnav': self.thread.app.write('dvdnav 6\n') return TRUE else: self.stop() return self.item.eventhandler(event) if event == 'AUDIO_ERROR_START_AGAIN': self.stop() self.play(self.parameter[0], self.parameter[1], self.parameter[2], self.parameter[3]) return TRUE if event == STORE_BOOKMARK: # Bookmark the current time into a file bookmarkfile = util.get_bookmarkfile(self.filename) handle = open(bookmarkfile,'a+') handle.write(str(self.item.elapsed)) handle.write('\n') handle.close() print "Added bookmark at position " + str(self.item.elapsed) return TRUE if event in ( STOP, PLAY_END, USER_END, DVD_PROTECTED ): self.stop() return self.item.eventhandler(event) if event == VIDEO_SEND_MPLAYER_CMD: self.thread.app.write('%s\n' % event.arg) return TRUE if event == MENU: if self.mode == 'dvdnav': self.thread.app.write('dvdnav 5\n') return TRUE if event == TOGGLE_OSD: self.thread.app.write('osd\n') return TRUE if event == PAUSE or event == PLAY: self.thread.app.write('pause\n') return TRUE if event == SEEK: self.thread.app.write('seek %s\n' % event.arg) return TRUE #if event == rc.UP and self.mode == 'dvdnav': # self.thread.app.write('dvdnav 1\n') # return TRUE #if event == rc.DOWN: # if self.mode == 'dvdnav': # self.thread.app.write('dvdnav 2\n') # return TRUE #if event == rc.LEFT: # if self.mode == 'dvdnav': # self.thread.app.write('dvdnav 3\n') # else: # self.thread.app.write('seek -60\n') # return TRUE #if event == rc.RIGHT: # if self.mode == 'dvdnav': # self.thread.app.write('dvdnav 4\n') # else: # self.thread.app.write('seek 60\n') # return TRUE # nothing found? Try the eventhandler of the object who called us return self.item.eventhandler(event) def reset_seek(self): print 'seek timeout' self.seek = 0 rc.set_context('video') def reset_seek_timeout(self): self.seek_timer.cancel() self.seek_timer = threading.Timer(config.MPLAYER_SEEK_TIMEOUT, self.reset_seek) self.seek_timer.start() # ====================================================================== class MPlayerParser: """ class to parse the mplayer output and store some information in the videoitem """ def __init__(self, item): self.item = item self.RE_EXIT = re.compile("^Exiting\.\.\. \((.*)\)$").match self.RE_START = re.compile("^Starting playback\.\.\.").match # DVD items also store mplayer_audio_broken to check if you can # start them with -alang or not if hasattr(item, 'mplayer_audio_broken') or item.mode != 'dvd': self.check_audio = 0 else: self.check_audio = 1 def parse(self, line): if self.check_audio: if line.find('MPEG: No audio stream found -> no sound') == 0: # OK, audio is broken, restart without -alang self.check_audio = 2 self.item.mplayer_audio_broken = TRUE rc.post_event(Event('AUDIO_ERROR_START_AGAIN')) if self.RE_START(line): print 'data parsing done' if self.check_audio == 1: # audio seems to be ok self.item.mplayer_audio_broken = FALSE self.check_audio = 0 def end_type(self, str): m = self.RE_EXIT(str) if m: return m.group(1) class MPlayerApp(childapp.ChildApp): """ class controlling the in and output from the mplayer process """ def __init__(self, app, item): if config.MPLAYER_DEBUG: startdir = os.environ['FREEVO_STARTDIR'] fname_out = os.path.join(startdir, 'mplayer_stdout.log') fname_err = os.path.join(startdir, 'mplayer_stderr.log') try: self.log_stdout = open(fname_out, 'a') self.log_stderr = open(fname_err, 'a') except IOError: print print (('ERROR: Cannot open "%s" and "%s" for ' + 'MPlayer logging!') % (fname_out, fname_err)) print 'Please set MPLAYER_DEBUG=0 in local_conf.py, or ' print 'start Freevo from a directory that is writeable!' print else: print 'MPlayer logging to "%s" and "%s"' % (fname_out, fname_err) self.RE_TIME = re.compile("^A: *([0-9]+)").match self.item = item self.parser = MPlayerParser(item) childapp.ChildApp.__init__(self, app) self.exit_type = None def kill(self): # Use SIGINT instead of SIGKILL to make sure MPlayer shuts # down properly and releases all resources before it gets # reaped by childapp.kill().wait() childapp.ChildApp.kill(self, signal.SIGINT) # XXX Krister testcode for proper X11 video if DEBUG: print 'Killing mplayer' util.killall('freevo_xwin') os.system('rm -f /tmp/freevo.wid') if config.MPLAYER_DEBUG: self.log_stdout.close() self.log_stderr.close() def stdout_cb(self, line): if config.MPLAYER_DEBUG: try: self.log_stdout.write(line + '\n') except ValueError: pass # File closed if line.find("A:") == 0: m = self.RE_TIME(line) # Convert decimal if hasattr(m,'group'): self.item.elapsed = int(m.group(1))+1 elif line.find("Exiting...") == 0: self.exit_type = self.parser.end_type(line) # this is the first start of the movie, parse infos elif not self.item.elapsed: self.parser.parse(line) def stderr_cb(self, line): if line.find('The DVD is protected') != -1: print print 'WARNING: You are trying to play a protected (CSS) DVD!' print 'DVD protection is normally enabled, please see the docs' print 'for more information.' print rc.post_event(DVD_PROTECTED) if config.MPLAYER_DEBUG: try: self.log_stderr.write(line + '\n') except ValueError: pass # File closed # ====================================================================== class MPlayer_Thread(threading.Thread): """ Thread to wait for a mplayer command to play """ def __init__(self): threading.Thread.__init__(self) self.play_mode = '' self.mode = 'idle' self.mode_flag = threading.Event() self.command = '' self.app = None self.item = None def run(self): while 1: if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'play': # The DXR3 device cannot be shared between our SDL session # and MPlayer. if (osd.sdl_driver == 'dxr3' or \ config.CONF.display == 'dfbmga'): print "Stopping Display for Video Playback" osd.stopdisplay() if DEBUG: print 'MPlayer_Thread.run(): Started, cmd=%s' % self.command self.app = MPlayerApp(self.command, self.item) while self.mode == 'play' and self.app.isAlive(): time.sleep(0.1) self.app.kill() if self.mode == 'play': if self.app.exit_type == "End of file": rc.post_event(PLAY_END) elif self.app.exit_type == "Quit": rc.post_event(USER_END) else: print 'error while playing file' rc.post_event(PLAY_END) # Ok, we can use the OSD again. if osd.sdl_driver == 'dxr3' or config.CONF.display == 'dfbmga': osd.restartdisplay() osd.update() print "Display back online" self.mode = 'idle' else: self.mode = 'idle' Index: imdb.py =================================================================== RCS file: /cvsroot/freevo/freevo/src/video/plugins/imdb.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** imdb.py 27 Jun 2003 11:34:09 -0000 1.12 --- imdb.py 29 Jun 2003 20:43:30 -0000 1.13 *************** *** 16,19 **** --- 16,23 ---- # ----------------------------------------------------------------------- # $Log$ + # Revision 1.13 2003/06/29 20:43:30 dischi + # o mmpython support + # o mplayer is now a plugin + # # Revision 1.12 2003/06/27 11:34:09 dischi # some small fixes for movies on rom drive *************** *** 104,108 **** self.item = item ! if item.type == 'video' and not item.info: if item.mode == 'file': return [ ( self.imdb_search_file, 'Search IMDB for this file', --- 108,112 ---- self.item = item ! if item.type == 'video' and not hasattr(item, 'fxd_file'): if item.mode == 'file': return [ ( self.imdb_search_file, 'Search IMDB for this file', *************** *** 176,180 **** box.show() ! name = self.item.filename name = os.path.basename(os.path.splitext(name)[0]) --- 180,184 ---- box.show() ! name = self.item.name name = os.path.basename(os.path.splitext(name)[0]) ------------------------------------------------------- This SF.Net email sponsored by: Free pre-built ASP.NET sites including Data Reports, E-commerce, Portals, and Forums are available now. Download today and enter to win an XBOX or Visual Studio .NET. http://aspnet.click-url.com/go/psa00100006ave/direct;at.asp_061203_01/01 _______________________________________________ Freevo-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/freevo-cvslog