"""
$Id: mythtvrecordedshowdetails.py,v 1.31 2007/05/18 22:11:06 frooby Exp $
Copyright (C) 2005 Tom Warkentin <tom@ixionstudios.com>
"""
from mythtvgui import Dialog
from singleton import getInstance
import mythtv
import mythtvgui
import mythtvutil
import os
from string import find
import singleton
import sre
import time
import traceback
import xbmc
import xbmcgui, socket
global markup
def debug( str ):
mythtvutil.debug( mythtvutil.DEBUG_GUI, str )
def showWindow( program ):
"""
Function to create the recorded show details window.
Returns:
- 1 if show was deleted
- 0 otherwise
"""
retVal = 0
win = Window()
win.loadskin( "recordedshowdetails.xml" )
win.loadShowDetails( program )
win.doModal()
retVal = win.isDeleted
del win
debug( "< mythtvrecordedshowdetails.showWindow() => [%d]"%retVal )
return retVal
def loadMarkup( chanid, starttime ):
global markup
markup = []
db = getInstance( mythtv.Database )
try:
markup = db.getCommMarkup( chanid, starttime )
except:
pass
return len( markup )
class Player( xbmc.Player ):
COMM_START = 4
COMM_END = 5
DIFF_THRESHOLD = 1.5
MPLAYER_FPS = 29.970
SKIP_REWIND_SECS = 0.0
def __init__( self ):
useDVDPlayer = getInstance( mythtv.Settings ).getSetting( "mythtv_recplayer" )
if useDVDPlayer == "1":
try:
debug("Trying to use DVDPlayer for Recorded Show Playback")
xbmc.Player.__init__( self, xbmc.PLAYER_CORE_DVDPLAYER )
except:
debug("Failed... Falling back to MPlayer")
xbmc.Player.__init__( self )
else:
debug("Using MPlayer for Recorded Show Playback")
xbmc.Player.__init__( self )
self.markup = []
self.doCommSkip = False
def findMarkupIndex( self, pType, pPos ):
global markup
debug( "> findMarkupIndex( pType=%d, pPos=%.1f )"%(pType,pPos) )
found = -1
# find last markup that is less than passed position
lastPos = 0
for n in range(0,len(markup)):
type = int(markup[n]['type'])
pos = int(markup[n]['mark']) / self.MPLAYER_FPS
#debug( "type=%d lastPos=%.1f pos=%.1f"%(type,lastPos,pos) )
if type == pType:
if pPos >= lastPos and pPos < pos:
found = n
#debug( "found=%d"%found )
break
else:
lastPos = pos
debug( "< findMarkupIndex => [%d]"%found )
return found
def onPlayBackStarted( self ):
global markup
debug(" > onPlayBackStarted - doCommSkip: %s Markups: %s"%(str(self.doCommSkip), str(markup)))
try:
if not self.doCommSkip:
return
numMarkups = len(markup)
lastPos = 0
curPos = 0
n = self.findMarkupIndex( self.COMM_START, 0 )
if n < 0:
debug( "no markups - exiting" )
return
# loop until playing finishes
debug( "getTotalTime=%.1f"%self.getTotalTime() )
while self.isPlaying():
time.sleep( 0.5 )
# check that we're still playing after sleeping
if self.isPlaying():
curPos = self.getTime()
posDiff = abs( curPos - lastPos )
debug( "lastPos=[%.1f] curPos=[%.1f]"%(lastPos, curPos) )
lastPos = curPos
# check if a huge difference in position was detected
if posDiff > self.DIFF_THRESHOLD:
# find next commercial start again
n = self.findMarkupIndex( self.COMM_START, curPos )
if n < 0:
break
nextStart = int(markup[n]['mark']) / self.MPLAYER_FPS
# check if we need to skip a commercial
debug( "curPos=[%.1f] nextStart=[%.1f]"%(curPos, nextStart) )
if curPos >= nextStart:
# figure out the end
if n+1 < numMarkups:
nextEnd = int(markup[n+1]['mark']) / \
self.MPLAYER_FPS
else:
break
nextEnd -= self.SKIP_REWIND_SECS
seekTime = nextEnd - curPos
# check if we're over the threshold for skipping
debug( "nextEnd=%.1f"%nextEnd )
if seekTime > self.DIFF_THRESHOLD:
self.pause()
time.sleep(0.25)
self.seekTime( nextEnd )
debug( "seek completed" )
time.sleep(0.25)
self.pause()
# find start of next commercial
n = self.findMarkupIndex( self.COMM_START, curPos )
except Exception, ex:
#self.stop()
#traceback.print_exc()
#xbmcgui.Dialog().ok( "Error", str( ex ) )
pass
debug(" < onPlayBackStarted")
def onPlayBackEnded( self ):
del self
def onPlayBackStopped( self ):
del self
def setCommSkip( self, isEnabled=False ):
self.doCommSkip = isEnabled
class Window( mythtvgui.BaseWindow ):
def __init__( self ):
mythtvgui.BaseWindow.__init__( self )
self.isDeleted = 0
def autoexpire( self ):
debug( '> mythtvrecordedshowdetails.Window.autoexpire()' )
# toggle the autoexpire flag
db = getInstance( mythtv.Database )
db.setRecordedAutoexpire(
self.program.chanid(),
self.program.starttime(),
not self.program.autoexpire() )
# notify backend that a change was made to the database
if int(mythtv.mythProtocolVersion) <= 13:
db.notifyChange()
# reload program details
self.refresh()
debug( '< mythtvrecordedshowdetails.Window.autoexpire()' )
def copy( self ):
debug( '> mythtvrecordedshowdetails.Window.copy()' )
rc = Dialog().yesno( \
mythtvutil.getLocalizedString( 28 ), \
mythtvutil.getLocalizedString( 68 ) )
if rc:
# build local file path
filename = sre.sub( '\W+', '_', self.program.title() )
filename = sre.sub( '_+', '_', filename )
if not filename.endswith( '_' ):
filename += '_'
filename += self.program.starttime() + ".mpg"
shost = str(getInstance( mythtv.Settings ).getSetting( "mythtv_host" ))
hostIp = socket.gethostbyname(self.program.hostname())
snet = hostIp[:6]
ssnet = shost[:6]
debug(snet + " " + ssnet)
if snet <> ssnet:
hostIp = shost
localFilePath = str(getInstance( mythtv.Settings ).getSetting( "paths_localcopypath" ))
localFilePath = localFilePath.replace( '/', os.sep )
if not localFilePath.endswith( os.sep ):
localFilePath += os.sep
localFilePath += filename
# check that local path exists
dir = str(getInstance( mythtv.Settings ).getSetting( \
"paths_localcopypath" ))
if not os.path.exists( dir ):
os.mkdir( dir )
remoteFilePath = self.program.remoteMythPath()
# do file transfer
debug( "transferring file remoteFilePath=[%s] localFilePath=[%s] HostIp=[%s]"%\
(remoteFilePath,localFilePath,hostIp) )
rc = getInstance( mythtv.Connection ).transferFile( \
remoteFilePath, localFilePath, hostIp )
if rc == 0 and os.path.exists( localFilePath ):
# display dialog to say transfer complete
Dialog().ok( \
mythtvutil.getLocalizedString( 26 ), \
mythtvutil.getLocalizedString( 66 ) )
else:
# display dialog to say transfer failed
Dialog().ok( \
mythtvutil.getLocalizedString( 27 ), \
mythtvutil.getLocalizedString( 67 ) )
debug( '< mythtvrecordedshowdetails.Window.copy()' )
def delete( self ):
debug( '> mythtvrecordedshowdetails.Window.delete()' )
rc = Dialog().yesno( \
mythtvutil.getLocalizedString( 28 ), \
mythtvutil.getLocalizedString( 65 ) )
if rc:
getInstance( mythtv.Connection ).deleteRecording( self.program )
self.isDeleted = 1
self.close()
debug( '< mythtvrecordedshowdetails.Window.delete()' )
def rerecord( self ):
debug( '> mythtvrecordedshowdetails.Window.redelete()' )
rc = Dialog().yesno( \
mythtvutil.getLocalizedString( 28 ), \
mythtvutil.getLocalizedString( 65 ) )
if rc:
getInstance( mythtv.Connection ).rerecordRecording( self.program )
self.isDeleted = 1
self.close()
debug( '< mythtvrecordedshowdetails.Window.redelete()' )
def loadShowDetails( self, program ):
debug( '> mythtvrecordedshowdetails.Window.loadShowDetails()' )
self.program = program
ctl = self.controls['autoexpire'].control
if self.program.autoexpire():
ctl.setLabel( mythtvutil.getLocalizedString( 49 ) ) # save
else:
ctl.setLabel( mythtvutil.getLocalizedString( 50 ) ) # expire
self.populateShowDetails( self.program )
shost = str(getInstance( mythtv.Settings ).getSetting( "mythtv_host" ))
try:
hostIp = socket.gethostbyname(self.program.hostname())
snet = hostIp[:6]
ssnet = shost[:6]
debug(snet + " " + ssnet)
if snet <> ssnet:
hostIp = shost
except:
hostIp = shost
debug( 'hostIp: %s'%hostIp)
try:
thumbFile = getInstance( mythtvgui.ThumbnailCache ).findFile( self.program , hostIp )
if not thumbFile:
Dialog().ok( \
mythtvutil.getLocalizedString( 27 ), \
mythtvutil.getLocalizedString( 85 ) )
else:
x = int(self.getvalue( self.getoption( "screenshot_x" ) ) )
y = int(self.getvalue( self.getoption( "screenshot_y" ) ) )
w = int(self.getvalue( self.getoption( "screenshot_w" ) ) )
h = int(self.getvalue( self.getoption( "screenshot_h" ) ) )
c = self.controls['screenshot'].control
self.removeControl( c )
del c
c = xbmcgui.ControlImage( x, y, w, h, thumbFile )
self.addControl( c )
self.controls['screenshot'].control = c
except:
debug( ' Failed to Load ScreenShot' )
pass
debug( '< mythtvrecordedshowdetails.Window.loadShowDetails()' )
def onControlHook( self, control ):
debug( "> mythtvrecordedshowdetails.Window.onControlHook()" )
id = self.getcontrolid( control )
if id == "play":
self.play()
elif id == "playskip":
self.play(True)
elif id == "autoexpire":
self.autoexpire()
elif id == "copy":
self.copy()
elif id == "delete":
self.delete()
elif id == "rerecord":
self.rerecord()
elif id == "refresh":
self.refresh()
debug( "< mythtvrecordedshowdetails.Window.onControlHook()" )
return 1
def play( self, skipCommercials = False ):
debug( "> mythtvrecordedshowdetails.Window.play()" )
shouldPlay = 0
# size = getInstance( mythtv.Connection ).getFileSize( \
# self.program.remoteMythPath() )
size = self.program.rawFileSize()
debug( " File Size: %s"%str(size) )
if size < 1024:
msg = mythtvutil.getLocalizedString( 54 )% \
(self.program.fullTitle(),self.program.hostname())
raise Exception, msg
else:
shouldPlay = 1
if shouldPlay:
rc = 0
player = Player()
player.setCommSkip( skipCommercials )
# play the file
player.play( self.program.remotePath() )
debug( "< mythtvrecordedshowdetails.Window.play()" )
def populateShowDetails( self, s ):
debug( "> mythtvrecordedshowdetails.Window.populateShowDetails()" )
# populate title
self.controls['show_title'].control.reset()
self.controls['show_title'].control.addLabel( s.fullTitle() )
debug( "show_title=[%s]"%s.fullTitle() )
# populate air date
self.controls['show_air_date'].control.setLabel( s.formattedAirDate() )
debug( "show_air_date=[%s]"%s.formattedAirDate() )
# populate channel
self.controls['show_channel'].control.setLabel( s.formattedChannel() )
debug( "show_channel=[%s]"%s.formattedChannel() )
# populate orig air
self.controls['show_orig_air'].control.setLabel( \
s.formattedOrigAirDate() )
debug( "show_orig_air=[%s]"%s.formattedOrigAirDate() )
# populate description
self.controls['show_descr'].control.reset()
self.controls['show_descr'].control.addLabel( \
s.formattedDescription() )
debug( "show_descr=[%s]"%s.formattedDescription() )
# populate category
self.controls['show_category'].control.setLabel( s.category() )
debug( "show_category=[%s]"%s.category() )
# populate autoexpire
ctl = self.controls['show_autoexpire'].control
if s.autoexpire():
ctl.setLabel( mythtvutil.getLocalizedString( 58 ) )
debug( "show_autoexpire=[%s]"%mythtvutil.getLocalizedString( 58 ) )
else:
ctl.setLabel( mythtvutil.getLocalizedString( 59 ) )
debug( "show_autoexpire=[%s]"%mythtvutil.getLocalizedString( 59 ) )
# populate file size
self.controls['show_file_size'].control.setLabel( \
s.formattedFileSize() )
# if we don't find any with the show start time try the recording start time
rc = loadMarkup( s.chanid(), self.program.starttime() )
if rc <= 0:
rc = loadMarkup( s.chanid(), time.strftime("%Y%m%d%H%M%S",time.localtime(float(s.recstarttime()))))
if rc > 0:
self.controls['playskip'].control.setEnabled(True)
else:
self.controls['playskip'].control.setEnabled(False)
debug( "show_category=[%s]"%s.category() )
debug( "< mythtvrecordedshowdetails.Window.populateShowDetails()" )
def refresh( self ):
debug( "> mythtvrecordedshowdetails.Window.refresh()" )
self.program = getInstance( mythtv.Connection ).getSingleProgram( \
self.program.chanid(), \
self.program.starttime(), \
self.program.endtime() )
self.loadShowDetails( self.program )
debug( "< mythtvrecordedshowdetails.Window.refresh()" )
if __name__ == "__main__":
import mythtvstruct
try:
mythtvutil.debugSetLevel( mythtvutil.DEBUG_GUI | mythtvutil.DEBUG_MISC )
mythtvutil.initialize()
p = getInstance( mythtv.Connection ).getSingleProgram( \
"1014", "20040720140000", "20040720143000" )
showWindow( p )
except Exception, ex:
traceback.print_exc()
Dialog().ok( mythtvutil.getLocalizedString( 27 ), str( ex ) )
|