|
OK with some hacking I got the 16:9 detection to work reliably. On my
current set of testfiles it works a treat. So I am now sharing the file (to go into video/plugins) for others to play with. So please provide feedback if you find a case where it does not work as expected. Paul On 26-01-10 12:02, John Molohan wrote: Interesting, thanks for the update. -- Paul Sijben tel 0334557522 |
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------
# Freevo video module for MPlayer
# -----------------------------------------------------------------------
# $Id: mplayer.py 11479 2009-05-07 17:34:38Z duncan $
# -----------------------------------------------------------------------
# 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
#
# -----------------------------------------------------------------------
"""
Freevo video module for MPlayer
"""
import os, re
import threading
import popen2
import kaa.metadata as mmpython
import config # Configuration handler. reads config file.
import util # Various utilities
import childapp # Handle child applications
import rc # The RemoteControl class.
import plugin
import dialog
from dialog.display import AppTextDisplay
from event import *
class PluginInterface(plugin.Plugin):
"""
Mplayer plugin for the video player.
With this plugin Freevo can play all video files defined in
VIDEO_MPLAYER_SUFFIX. This is the default video player for Freevo.
"""
def __init__(self):
# create plugin structure
plugin.Plugin.__init__(self)
# register mplayer as the object to play video
plugin.register(MPlayer(), plugin.VIDEO_PLAYER, True)
class MPlayer:
"""
the main class to control mplayer
"""
def __init__(self):
"""
init the mplayer object
"""
self.name = 'mplayer'
self.app_mode = 'video'
self.seek = 0
self.seek_timer = threading.Timer(0, self.reset_seek)
self.app = None
self.plugins = []
self.paused = False
self.stored_time_info = None
self.audio_media = None
self.subtitle_media = None
def rate(self, item):
"""
How good can this player play the file:
2 = good
1 = possible, but not good
0 = unplayable
"""
if not item.url:
return 0
# this seems strange that it is 'possible' for dvd:// and 'good' for dvd
# possible because dvd:// should be played with xine when available!
if item.url[:6] in ('dvd://', 'vcd://') and item.url.endswith('/'):
_debug_('mplayer rating: %r possible' % (item.url), 2)
return 1
if item.mode in ('dvd', 'vcd'):
_debug_('mplayer rating: %r good' % (item.url), 2)
return 2
if item.mode in ('http') and not item.filename and not item.media:
_debug_('mplayer rating: %r good' % (item.url), 2)
return 2
if item.mimetype in config.VIDEO_MPLAYER_SUFFIX:
_debug_('mplayer rating: %r good' % (item.url), 2)
return 2
if item.network_play:
_debug_('mplayer rating: %r possible' % (item.url), 2)
return 1
_debug_('mplayer rating: %r unplayable' % (item.url), 2)
return 0
def play(self, options, item):
"""
play a videoitem with mplayer
"""
_debug_('options=%r' % (options,), 2)
for k, v in item.__dict__.items():
_debug_('item[%s]=%r' % (k, v), 2)
mode = item.mode
url = item.url
self.options = options
self.item = item
self.item_info = None
self.item_length = -1
self.item.elapsed = 0
if mode == 'file':
url = item.url[6:]
self.item_info = mmpython.parse(url)
if hasattr(self.item_info, 'get_length'):
self.item_length = self.item_info.get_endpos()
self.dynamic_seek_control = True
if url.startswith('dvd://') and url[-1] == '/':
url += '1'
if url == 'vcd://':
c_len = 0
for i in range(len(item.info.tracks)):
if item.info.tracks[i].length > c_len:
c_len = item.info.tracks[i].length
url = item.url + str(i+1)
url=Unicode(url)
try:
_debug_('MPlayer.play(): mode=%s, url=%s' % (mode, url))
except UnicodeError:
_debug_('MPlayer.play(): [non-ASCII data]')
if mode == 'file' and not os.path.isfile(url):
# This event allows the videoitem which contains subitems to
# try to play the next subitem
return '%s\nnot found' % os.path.basename(url)
set_vcodec = False
if item['xvmc'] and item['type'][:6] in ['MPEG-1', 'MPEG-2', 'MPEG-T']:
set_vcodec = True
mode = item.mimetype
if not config.MPLAYER_ARGS.has_key(mode):
_debug_('MPLAYER_ARGS not defined for %r, using default' % mode,
DINFO)
mode = 'default'
_debug_('mode=%s args=%s'% (mode, config.MPLAYER_ARGS[mode]))
# Build the MPlayer command
args = {
'nice': config.MPLAYER_NICE,
'cmd': config.MPLAYER_CMD,
'vo': '-vo %s' % config.MPLAYER_VO_DEV,
'vo_opts': config.MPLAYER_VO_DEV_OPTS,
'vc': '',
'ao': '-ao %s' % config.MPLAYER_AO_DEV,
'ao_opts': config.MPLAYER_AO_DEV_OPTS,
'default_args': config.MPLAYER_ARGS_DEF,
'mode_args': config.MPLAYER_ARGS[mode],
'fxd_args': ' '.join(options),
'geometry': '',
'verbose': '',
'dvd-device': '',
'cdrom-device': '',
'alang': '',
'aid': '',
'slang': '',
'sid': '',
'playlist': '',
'field-dominance': '',
'edl': '',
'mc': '',
'delay': '',
'sub': '',
'audiofile': '',
'af': [],
'vf': [],
'url': url,
'disable_osd': False,
}
if config.CONF.x or config.CONF.y:
args['geometry'] = '-geometry %d:%d' % (config.CONF.x,
config.CONF.y)
if config.DEBUG_CHILDAPP:
args['verbose'] = '-v'
if mode == 'dvd':
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:
args['alang'] = '-alang %s' % config.DVD_LANG_PREF
if config.DVD_SUBTITLE_PREF:
# Only use if defined since it will always turn on subtitles
when defined
args['slang'] = '-slang %s' % config.DVD_SUBTITLE_PREF
if mode == 'dvd':
# dvd on harddisc
args['dvd-device'] = '%s' % item.filename
args['url'] = url[:6] + url[url.rfind('/')+1:]
elif mode != 'file' and hasattr(item.media, 'devicename'):
args['dvd-device'] = '%s' % item.media.devicename
if item.media and hasattr(item.media, 'devicename'):
args['cdrom-device'] = '%s' % item.media.devicename
if item.selected_subtitle == -1:
args['sid'] = '-noautosub'
elif item.selected_subtitle is not None:
if mode == 'file':
if os.path.isfile(os.path.splitext(item.filename)[0]+'.idx'):
args['sid'] = '-vobsubid %s' % str(item.selected_subtitle)
else:
args['sid'] = '-sid %s' % str(item.selected_subtitle)
else:
args['sid'] = '-sid %s' % str(item.selected_subtitle)
if item.selected_audio is not None:
args['aid'] = '-aid %s' % str(item.selected_audio)
# This comes from the bilingual language selection menu
if hasattr(item, 'selected_language') and item.selected_language:
if item.selected_language == 'left':
args['af'].append('pan=2:1:1:0:0')
elif item.selected_language == 'right':
args['af'].append('pan=2:0:0:1:1')
if not set_vcodec:
if item['deinterlace'] and config.MPLAYER_VF_INTERLACED:
args['vf'].append(config.MPLAYER_VF_INTERLACED)
elif config.MPLAYER_VF_PROGRESSIVE:
args['vf'].append(config.MPLAYER_VF_PROGRESSIVE)
if config.VIDEO_FIELD_DOMINANCE is not None:
args['field-dominance'] = '-field-dominance %d' %
int(item['field-dominance'])
if os.path.isfile(os.path.splitext(item.filename)[0]+'.edl'):
args['edl'] = '-edl %s' %
str(os.path.splitext(item.filename)[0]+'.edl')
if dialog.overlay_display_supports_dialogs:
# Disable the mplayer OSD if we have a better option.
args['disable_osd'] = True
# Mplayer command and standard arguments
if set_vcodec:
if item['deinterlace']:
bobdeint='bobdeint'
else:
bobdeint='nobobdeint'
args['vo'] = '-vo xvmc:%s' % bobdeint
args['vc'] = '-vc ffmpeg12mc'
if hasattr(item, 'is_playlist') and item.is_playlist:
args['playlist'] = '-playlist'
# correct avi delay based on kaa.metadata settings
if config.MPLAYER_SET_AUDIO_DELAY and item.info.has_key('delay') and
item.info['delay'] > 0:
args['mc'] = '-mc %s' % str(int(item.info['delay'])+1)
args['delay'] = '-delay -%s' % str(item.info['delay'])
# autocrop
if config.MPLAYER_AUTOCROP and not item.network_play and
args['fxd_args'].find('crop=') == -1:
_debug_('starting autocrop points=%s'%config.MPLAYER_AUTOCROP_START)
(x1, y1, x2, y2) = (1000, 1000, 0, 0)
#new approach; detect if this is 16:9 or 4:3
crop_point=config.TV_RECORD_PADDING_PRE+60
(x1, y1, x2, y2) = self.get_crop(crop_point, x1, y1, x2, y2)
_debug_('set=%s'%(str((x1, y1, x2, y2))))
if y1==0 and float(x2-x1)/max(float(y2-y1),1)<1.5:
#ah 4:3, let's investigate further
#now we have the max size (720x576 for tv recordings)
#however the upper and lower bars of a TV recording are not
black enough
count_16by9 = 0
count_4by3 = 0
for ii in range(0,4):
if ii:
crop_point+=3*60
#jump through the movie with 3 min intervals
(x11, y11, x21, y21) = (1000, 1000, 0, 0)
isit,x11,y11,x21,y21=
self.is16by9(crop_point,x11,y11,x21,y21)
if isit:
count_16by9+=1
else:
count_4by3+=1
if count_16by9>count_4by3:
#ah adapt the crop params
height=y2-y1
w=x2-x1
if w==720: w=768
factor = float(config.CONF.width)/float(w)
cropheight = int(.5+(config.CONF.height/factor))
_debug_('height=%s w=%s factor=%s
cropheight=%s'%(height,w,factor,cropheight))
#OK cut top and bottom in equal amounts
y1=int((height-cropheight)/2)
y2=y1+cropheight
_debug_('y1=%s y2=%s'%(y1,y2))
if x1 < 1000 and x2 < 1000:
args['vf'].append('crop=%s:%s:%s:%s' % (x2-x1, y2-y1, x1, y1))
_debug_('crop=%s:%s:%s:%s' % (x2-x1, y2-y1, x1, y1))
if item.subtitle_file:
self.subtitle_media, f =
util.resolve_media_mountdir(item.subtitle_file)
if self.subtitle_media:
self.subtitle_media.mount()
args['sub'] = '-sub %s' % f
if item.audio_file:
self.audio_media, f = util.resolve_media_mountdir(item.audio_file)
if self.audio_media:
self.audio_media.mount()
args['audiofile'] = '-audiofile %s' % f
self.plugins = plugin.get('mplayer_video')
for p in self.plugins:
command = p.play(command, self)
vo = ['%(vo)s' % args, '%(vo_opts)s' % args]
vo = filter(len, vo)
vo = ':'.join(vo)
ao = ['%(ao)s' % args, '%(ao_opts)s' % args]
ao = filter(len, ao)
ao = ':'.join(ao)
# process the mplayer options extracting video and audio filters
args['default_args'], args = self.find_filters(args['default_args'],
args)
args['mode_args'], args = self.find_filters(args['mode_args'], args)
args['fxd_args'], args = self.find_filters(args['fxd_args'], args)
command = ['--prio=%(nice)s' % args]
command += ['%(cmd)s' % args]
command += ['-slave']
command += str('%(verbose)s' % args).split()
command += str('%(geometry)s' % args).split()
command += vo.split()
command += str('%(vc)s' % args).split()
command += ao.split()
command += args['dvd-device'] and ['-dvd-device', '%(dvd-device)s' %
args] or []
command += args['cdrom-device'] and ['-cdrom-device',
'%(cdrom-device)s' % args] or []
command += str('%(alang)s' % args).split()
command += str('%(aid)s' % args).split()
command += str('%(audiofile)s' % args).split()
command += str('%(slang)s' % args).split()
command += str('%(sid)s' % args).split()
command += str('%(sub)s' % args).split()
command += str('%(field-dominance)s' % args).split()
command += str('%(edl)s' % args).split()
command += str('%(mc)s' % args).split()
command += str('%(delay)s' % args).split()
command += args['default_args'].split()
command += args['mode_args'].split()
command += args['fxd_args'].split()
command += args['af'] and ['-af', '%s' % ','.join(args['af'])] or []
command += args['vf'] and ['-vf', '%s' % ','.join(args['vf'])] or []
command += args['disable_osd'] and ['-osdlevel', '0'] or []
# use software scaler?
#XXX these need to be in the arg list as the scaler will add vf args
if '-nosws' in command:
command.remove('-nosws')
elif '-framedrop' not in command:
command += config.MPLAYER_SOFTWARE_SCALER.split()
command = filter(len, command)
command += str('%(playlist)s' % args).split()
command += ['%(url)s' % args]
_debug_(' '.join(command[1:]))
#if plugin.getbyname('MIXER'):
#plugin.getbyname('MIXER').reset()
self.paused = False
rc.app(self)
self.app = MPlayerApp(command, self)
dialog.enable_overlay_display(AppTextDisplay(self.show_message))
return None
def stop(self):
"""
Stop mplayer
"""
for p in self.plugins:
command = p.stop()
if not self.app:
return
self.app.stop('quit\n')
rc.app(None)
dialog.disable_overlay_display()
self.app = None
if self.subtitle_media:
self.subtitle_media.mount()
self.subtitle_media = None
if self.audio_media:
self.audio_media.mount()
self.audio_media = None
def eventhandler(self, event, menuw=None):
"""
eventhandler for mplayer control. If an event is not bound in this
function it will be passed over to the items eventhandler
"""
if not self.app:
return self.item.eventhandler(event)
for p in self.plugins:
if p.eventhandler(event):
return True
if event == VIDEO_MANUAL_SEEK:
self.seek = 0
rc.set_context('input')
dialog.show_message("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.app.write('seek ' + str(self.seek) + ' 2\n')
_debug_("seek "+str(self.seek)+" 2\n")
self.seek = 0
rc.set_context('video')
return True
elif event == INPUT_EXIT:
_debug_('seek stopped')
#self.app.write('seek stopped\n')
self.seek_timer.cancel()
self.seek = 0
rc.set_context('video')
return True
if event == STOP:
self.stop()
return self.item.eventhandler(event)
if event == 'AUDIO_ERROR_START_AGAIN':
self.stop()
self.play(self.options, self.item)
return True
if event in (PLAY_END, USER_END):
self.stop()
return self.item.eventhandler(event)
if event == VIDEO_SEND_MPLAYER_CMD:
self.app.write('%s\n' % event.arg)
return True
if event == TOGGLE_OSD:
if dialog.is_dialog_supported():
if self.paused:
dialog.show_play_state(dialog.PLAY_STATE_PAUSE ,
self.get_stored_time_info)
else:
dialog.show_play_state(dialog.PLAY_STATE_PLAY,
self.get_time_info)
else:
self.app.write('osd\n')
return True
if event == PAUSE or event == PLAY:
self.paused = not self.paused
# We have to store the current time before displaying the dialog
# otherwise the act of requesting the current position resumes
playback!
if self.paused:
self.stored_time_info = self.get_time_info()
dialog.show_play_state(dialog.PLAY_STATE_PAUSE,
self.get_time_info)
self.app.write('pause\n')
else:
self.app.write('pause\n')
dialog.show_play_state(dialog.PLAY_STATE_PLAY,
self.get_time_info)
return True
if event == SEEK:
if event.arg > 0 and self.item_length != -1 and
self.dynamic_seek_control:
# check if the file is growing
if self.item_info.get_endpos() == self.item_length:
# not growing, deactivate this
self.item_length = -1
self.dynamic_seek_control = False
if event.arg > 0 and self.item_length != -1:
# safety time for bad mplayer seeking
seek_safety_time = 20
if self.item_info['type'] in ('MPEG-PES', 'MPEG-TS'):
seek_safety_time = 500
# check if seek is allowed
if self.item_length <= self.item.elapsed + event.arg +
seek_safety_time:
# get new length
self.item_length = self.item_info.get_endpos()
# check again if seek is allowed
if self.item_length <= self.item.elapsed + event.arg +
seek_safety_time:
_debug_('unable to seek %s secs at time %s, length %s' % \
(event.arg, self.item.elapsed, self.item_length))
dialog.show_message(_('Seeking not possible'))
return False
if event.arg > 0:
dialog.show_play_state(dialog.PLAY_STATE_SEEK_FORWARD,
self.get_time_info)
else:
dialog.show_play_state(dialog.PLAY_STATE_SEEK_BACK,
self.get_time_info)
self.app.write('seek %s\n' % event.arg)
return True
if event == VIDEO_AVSYNC:
self.app.write('audio_delay %g\n' % event.arg);
return True
if event == VIDEO_NEXT_AUDIOLANG:
self.app.write('switch_audio\n')
return True
if event == VIDEO_NEXT_SUBTITLE:
self.app.write('sub_select\n')
return True
if event == OSD_MESSAGE:
self.show_message(event.arg)
return True
# nothing found? Try the eventhandler of the object who called us
return self.item.eventhandler(event)
def show_message(self, message):
self.app.write('osd_show_text "%s"\n' % message);
def reset_seek(self):
_debug_('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()
def find_filters(self, arg, args):
old_options = arg.split('-')
new_options = []
for i in range(len(old_options)):
pair = old_options[i].split()
if len(pair) == 2:
if pair[0] == 'vf':
args['vf'].append(pair[1])
continue
elif pair[0] == 'af':
args['af'].append(pair[1])
continue
new_options.append(old_options[i])
arg = '-'.join(new_options)
return arg, args
def sort_filter(self, command):
"""
Change a mplayer command to support more than one -vf parameter. This
function will grep all -vf parameter from the command and add it at the
end as one vf argument
"""
ret = []
vf = ''
next_is_vf = False
for arg in command:
if next_is_vf:
vf += ',%s' % arg
next_is_vf = False
elif (arg == '-vf'):
next_is_vf=True
else:
ret += [arg]
if vf:
return ret + ['-vf', vf[1:]]
return ret
def get_crop(self, pos, x1, y1, x2, y2, threshold=None):
if threshold:
crop_cmd = [config.MPLAYER_CMD, '-ao', 'null', '-vo', 'null',
'-slave', '-nolirc',
'-ss', '%s' % pos, '-frames', '6', '-vf',
'cropdetect=%s'%threshold]
else:
crop_cmd = [config.MPLAYER_CMD, '-ao', 'null', '-vo', 'null',
'-slave', '-nolirc',
'-ss', '%s' % pos, '-frames', '6', '-vf', 'cropdetect']
crop_cmd.append(self.item.url)
child = popen2.Popen3(self.sort_filter(crop_cmd), 1, 100)
exp = re.compile('^.*-vf crop=([0-9]*):([0-9]*):([0-9]*):([0-9]*).*')
gotone=False
while(1):
data = child.fromchild.readline()
if not data:
if not gotone:
return self.get_crop(0,x1,y1,x2,y2,threshold)
break
m = exp.match(data)
if m:
x1 = min(x1, int(m.group(3)))
y1 = min(y1, int(m.group(4)))
x2 = max(x2, int(m.group(1)) + int(m.group(3)))
y2 = max(y2, int(m.group(2)) + int(m.group(4)))
_debug_('x1=%s x2=%s y1=%s y2=%s' % (x1, x2, y1, y2))
gotone=True
child.wait()
return (x1, y1, x2, y2)
def is16by9(self,crop_point,x1,y1,x2,y2,threshold=54):
_debug_('croppoint=%s thresh=%s ' % (crop_point,threshold))
(x12, y12, x22, y22) = self.get_crop(crop_point, x1,y1,x2,y2,threshold)
if y22==0: y22=1
_debug_('x1=%s x2=%s y1=%s y2=%s x2/y2=%s' % (x12, x22, y12,
y22,float(x22)/float(y22)))
return float(x22)/float(y22)>1.27,x12,y12,x22,y22
def get_stored_time_info(self):
return self.stored_time_info
def get_time_info(self):
time_pos = self.app.get_property('time_pos')
length = self.app.get_property('length')
percent_pos = self.app.get_property('percent_pos')
return (int(float(time_pos)), int(float(length)), int(percent_pos) /
100.0)
# ======================================================================
class MPlayerApp(childapp.ChildApp2):
"""
class controlling the in and output from the mplayer process
"""
def __init__(self, command, mplayer):
self.RE_TIME = re.compile("^[AV]: *([0-9]+)").match
self.RE_START = re.compile("^Starting playback\.\.\.").match
self.RE_EXIT = re.compile("^Exiting\.\.\. \((.*)\)$").match
self.item = mplayer.item
self.mplayer = mplayer
self.exit_type = None
# DVD items also store mplayer_audio_broken to check if you can
# start them with -alang or not
if hasattr(self.item, 'mplayer_audio_broken') or self.item.mode !=
'dvd':
self.check_audio = 0
else:
self.check_audio = 1
import osd
self.osd = osd.get_singleton()
self.osdfont = self.osd.getfont(config.OSD_DEFAULT_FONTNAME,
config.OSD_DEFAULT_FONTSIZE)
# check for mplayer plugins
self.stdout_plugins = []
self.elapsed_plugins = []
for p in plugin.get('mplayer_video'):
if hasattr(p, 'stdout'):
self.stdout_plugins.append(p)
if hasattr(p, 'elapsed'):
self.elapsed_plugins.append(p)
self.output_event = threading.Event()
self.get_property_ans = None
# init the child (== start the threads)
childapp.ChildApp2.__init__(self, command, callback_use_rc=False)
def get_property(self, property):
self.get_property_ans = None
self.output_event.clear()
self.write('get_property %s\n' % property)
self.output_event.wait()
return self.get_property_ans
def stop_event(self):
"""
return the stop event send through the eventhandler
"""
if self.exit_type == "End of file":
return PLAY_END
elif self.exit_type == "Quit":
return USER_END
else:
return PLAY_END
def stdout_cb(self, line):
"""
parse the stdout of the mplayer process
"""
# show connection status for network play
if self.item.network_play:
if line.find('Opening audio decoder') == 0:
self.osd.clearscreen(self.osd.COL_BLACK)
self.osd.update()
elif (line.startswith('Resolving ') or \
line.startswith('Connecting to server') or \
line.startswith('Cache fill:')) and \
line.find('Resolving reference to') == -1:
if line.startswith('Connecting to server'):
line = 'Connecting to server'
self.osd.clearscreen(self.osd.COL_BLACK)
self.osd.drawstringframed(line, config.OSD_OVERSCAN_LEFT+10,
config.OSD_OVERSCAN_TOP+10,
self.osd.width - (config.OSD_OVERSCAN_LEFT+10 +
config.OSD_OVERSCAN_RIGHT+10),
-1, self.osdfont, self.osd.COL_WHITE)
self.osd.update()
# current elapsed time
if line.startswith("A:") or line.startswith("V:"):
m = self.RE_TIME(line)
if hasattr(m, 'group') and self.item.elapsed != int(m.group(1))+1:
self.item.elapsed = int(m.group(1))+1
for p in self.elapsed_plugins:
p.elapsed(self.item.elapsed)
# exit status
elif line.find("Exiting...") == 0:
m = self.RE_EXIT(line)
if m:
self.exit_type = m.group(1)
if self.output_event.isSet():
self.output_event.set()
elif line.startswith('ANS_'):
prop,ans = line.split('=')
self.get_property_ans = ans.strip()
self.output_event.set()
# this is the first start of the movie, parse info
elif not self.item.elapsed:
for p in self.stdout_plugins:
p.stdout(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):
if self.check_audio == 1:
# audio seems to be ok
self.item.mplayer_audio_broken = False
self.check_audio = 0
def stderr_cb(self, line):
"""
parse the stderr of the mplayer process
"""
if line.startswith('Failed to get value of property '):
self.output_event.set()
for p in self.stdout_plugins:
p.stdout(line)
------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com
_______________________________________________ Freevo-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/freevo-users
