From 553fc5d6c8ee1e319fbfe4862d3545de1ab8d317 Mon Sep 17 00:00:00 2001 From: betonme Date: Mon, 12 Nov 2012 18:17:48 +0100 Subject: [PATCH] Issue 10 popup bug fixed New screen handling implemented --- src/EMCMediaCenter.py | 131 +++++++-------- src/EnhancedMovieCenter.py | 8 +- src/InfoBarSupport.py | 23 +++ src/MovieCenter.py | 278 ++++++++++++++++++-------------- src/MovieSelection.py | 319 ++++++++++++++++--------------------- src/RecordingsControl.py | 44 +++-- src/ServiceSupport.py | 7 +- src/plugin.py | 23 ++- 8 files changed, 415 insertions(+), 418 deletions(-) diff --git a/src/EMCMediaCenter.py b/src/EMCMediaCenter.py index b8f56d97..5240c7a4 100644 --- a/src/EMCMediaCenter.py +++ b/src/EMCMediaCenter.py @@ -54,8 +54,10 @@ from Components.Pixmap import Pixmap from enigma import ePicLoad -from MovieCenter import sidDVD, sidDVB +from MovieCenter import sidDVD, sidDVB, toggleProgressService +from RecordingsControl import getRecording +import NavigationInstance dvdPlayerPlg = "%s%s"%(resolveFilename(SCOPE_PLUGINS), "Extensions/DVDPlayer/plugin.pyo") @@ -72,7 +74,7 @@ class EMCMediaCenter( CutList, Screen, HelpableScreen, InfoBarSupport ): ENABLE_RESUME_SUPPORT = True ALLOW_SUSPEND = True - def __init__(self, session, playlist, recordings, playall=None, lastservice=None): + def __init__(self, session, playlist, playall=None, lastservice=None): # The CutList must be initialized very first CutList.__init__(self) @@ -206,20 +208,23 @@ def __init__(self, session, playlist, recordings, playall=None, lastservice=None self.firstStart = True self.stopped = False self.closedByDelete = False - self.playerOpenedList = False self.closeAll = False self.lastservice = lastservice or self.session.nav.getCurrentlyPlayingServiceReference() self.playlist = playlist self.playall = playall self.playcount = -1 - self.recordings = recordings self.service = None - self.recordings.setPlayerInstance(self) self.picload = ePicLoad() self.picload.PictureData.get().append(self.showCoverCallback) + # Record events + try: + NavigationInstance.instance.RecordTimer.on_state_change.append(self.recEvent) + except Exception, e: + emcDebugOut("[EMCMediaCenter] Record observer add exception:\n" + str(e)) + # Dialog Events self.onShown.append(self.__onShow) # Don't use onFirstExecBegin() it will crash self.onClose.append(self.__onClose) @@ -287,14 +292,14 @@ def evEOF(self, needToClose=False): #except: # pass # Workaround for E2 dvb player bug in combination with running recordings and existings cutlists - record = self.recordings.getRecording(path) + record = getRecording(path) if record: try: os.remove(cutspath) except: pass # Further cutlist handling - self.recordings.toggleProgress(service, True) + toggleProgressService(service, True) self.service = service if service and service.type == sidDVD: @@ -323,16 +328,16 @@ def evEOF(self, needToClose=False): self["DVDPlayerPlaybackActions"].setEnabled(False) # Check if the video preview is active and already running -# if config.EMC.movie_preview.value: -# ref = self.session.nav.getCurrentlyPlayingServiceReference() -# if ref and service and ref.getPath() == service.getPath(): -# #s = self.session.nav.getCurrentService() -# #cue = s and s.cueSheet() -# #if cue is not None: -# #cue.setCutListEnable(1) -# self.downloadCuesheet() -# #print "EMC cue.setCutListEnable(1)" -# #return + # if config.EMC.movie_preview.value: + # ref = self.session.nav.getCurrentlyPlayingServiceReference() + # if ref and service and ref.getPath() == service.getPath(): + # #s = self.session.nav.getCurrentService() + # #cue = s and s.cueSheet() + # #if cue is not None: + # #cue.setCutListEnable(1) + # self.downloadCuesheet() + # #print "EMC cue.setCutListEnable(1)" + # #return # Is this really necessary # TEST for M2TS Audio problem @@ -367,14 +372,6 @@ def evEOF(self, needToClose=False): def leavePlayer(self, stopped=True): #TEST is stopped really necessary self.stopped = stopped - if self.playerOpenedList: - print "leavePlayer self.recordings.close" - self.recordings.close() - #self.session.close(self.recordings) - #self.session.execEnd(self.recordings) - self.playerOpenedList = False - #self.recordings.hide() - return self.setSubtitleState(False) if self.dvdScreen: @@ -387,50 +384,65 @@ def leavePlayer(self, stopped=True): if self.service and self.service.type != sidDVB: self.updateCutList( self.getSeekPlayPosition(), self.getSeekLength() ) - self.recordings.setPlayerInstance(None) - reopen = False try: - #from MovieSelection import gMS - self.recordings.returnService = self.service +# self.recordings.returnService = self.service if self.stopped: emcDebugOut("[EMCPlayer] Player closed by user") if config.EMC.movie_reopen.value: - #DelayedFunction(80, gMS.session.execDialog, gMS) # doesn't crash Enigma2 subtitle functionality #self.recordings.show() reopen = True elif self.closedByDelete: emcDebugOut("[EMCPlayer] closed due to file delete") - #DelayedFunction(80, gMS.session.execDialog, gMS) # doesn't crash Enigma2 subtitle functionality #self.recordings.show() reopen = True else: emcDebugOut("[EMCPlayer] closed due to playlist EOF") if self.closeAll: AddPopup( - _("EMC\nZap to Live TV of record"), - MessageBox.TYPE_INFO, - 3, - "EMCCloseAllAndZap" - ) + _("EMC\nZap to Live TV of record"), + MessageBox.TYPE_INFO, + 3, + "EMCCloseAllAndZap" + ) else: - if self.playerOpenedList or config.EMC.movie_reopenEOF.value: # did the player close while movie list was open? - #DelayedFunction(80, gMS.session.execDialog, gMS) # doesn't crash Enigma2 subtitle functionality + if config.EMC.movie_reopenEOF.value: # did the player close while movie list was open? #self.recordings.show() reopen = True - self.playerOpenedList = False self.service = None except Exception, e: emcDebugOut("[EMCPlayer] leave exception:\n" + str(e)) self.close(reopen) + def recEvent(self, timer): + try: + # Check if record is currently played + path = timer.Filename + ".ts" + if path == self.service.getPath(): + # WORKAROUND Player is running during a record ends + # We should find a more flexible universal solution + DelayedFunction(3000, self.updatePlayer) + # ATTENTION thist won't fix the other situation + # If a running record will be played and the player is stopped before the record ends + # -> Then E2 will overwrite the existing cuts. + except Exception, e: + emcDebugOut("[spRO] recEvent exception:\n" + str(e)) + + def updatePlayer(self): + self.updateFromCuesheet() + def __onClose(self): if self.picload: del self.picload if self.lastservice: self.session.nav.playService(self.lastservice) self.lastservice = None + # Record events + try: + NavigationInstance.instance.RecordTimer.on_state_change.remove(self.recEvent) + except Exception, e: + emcDebugOut("[EMCMediaCenter] Record observer remove exception:\n" + str(e)) ############################################################################## ## Recordings relevant function @@ -439,7 +451,7 @@ def getLength(self): service = self.service path = service and service.getPath() if path: - record = self.recordings.getRecording(path) + record = getRecording(path) if record: #TODO There is still a problem with split records with cut numbers begin, end, s = record @@ -458,7 +470,7 @@ def getPosition(self): service = self.service path = service and service.getPath() if path: - record = self.recordings.getRecording(path) + record = getRecording(path) if record: begin, end, s = record return int((time() - begin) * 90000) @@ -492,7 +504,6 @@ def currentlyPlayedMovie(self): def movieSelected(self, playlist, playall=None): print "movieSelected" - self.playerOpenedList = False if playlist is not None and len(playlist) > 0: self.playcount = -1 @@ -778,9 +789,9 @@ def setChapterLabel(self): # InfoBarShowMovies def showMovies(self): try: - self.playerOpenedList = True - self.session.execDialog(self.recordings) - #self.recordings.show() + from MovieSelection import EMCSelection + #self.session.openWithCallback(showMoviesCallback, EMCSelection) + self.session.open(EMCSelection, playerInstance=self, returnService=self.service ) except Exception, e: emcDebugOut("[EMCPlayer] showMovies exception:\n" + str(e)) @@ -811,17 +822,6 @@ def doShow(self): # self.dvdScreen.hide() InfoBarShowHide.doShow(self) - # InfoBarCueSheetSupport - def playLastCB(self, answer): - if answer == True: - self.doSeek(self.resume_point) - # From Merlin2 - elif config.EMC.movie_jump_first_mark.value == True: - self.jumpToFirstMark() - elif self.service and self.service.type == sidDVD: - DelayedFunction(50, boundFunction(self.dvdPlayerWorkaround)) - self.showAfterSeek() - # InfoBarNumberZap def keyNumberGlobal(self, number): if self.service and self.service.type == sidDVD: @@ -829,16 +829,6 @@ def keyNumberGlobal(self, number): from Plugins.Extensions.DVDPlayer.plugin import ChapterZap self.session.openWithCallback(self.numberEntered, ChapterZap, "0") - def numberEntered(self, retval): - if retval and retval > 0 and retval != "": - self.zapToNumber(retval) - - def zapToNumber(self, number): - if self.service: - seekable = self.getSeek() - if seekable: - seekable.seekChapter(number) - # InfoBarMenu Key_Menu #def mainMenu(self): # self.enterDVDMenu() @@ -875,25 +865,26 @@ def doEofInternal(self, playing): if self.in_menu: self.hide() - if config.EMC.record_eof_zap.value and self.recordings and self.service: + if config.EMC.record_eof_zap.value and self.service: #TEST # get path from iPlayableService #ref = self.session.nav.getCurrentlyPlayingServiceReference() #if ref and self.service and ref.getPath() == self.service.getPath(): - record = self.recordings.getRecording(self.service.getPath()) + record = getRecording(self.service.getPath()) if record: begin, end, service = record - #last = ( time() - begin ) * 90000 # Seek play position and record length differ about one second + #last = ( time() - begin ) * 90000 #if last < (self.getSeekPlayPosition() + 1*90000): + # Zap to new channel self.lastservice = service self.service = None self.closeAll = True - #DelayedFunction(10, boundFunction(self.leavePlayer, False)) self.leavePlayer(False) return + #TEST just return and ignore if there is more to play #else: ##if self.seekstate == self.SEEK_STATE_EOF: diff --git a/src/EnhancedMovieCenter.py b/src/EnhancedMovieCenter.py index a56ea925..27e99a8d 100644 --- a/src/EnhancedMovieCenter.py +++ b/src/EnhancedMovieCenter.py @@ -53,7 +53,7 @@ from EMCTasker import emcTasker, emcDebugOut -EMCVersion = "V3.9.2" +EMCVersion = "V4.0.0b4" EMCAbout = "\n Enhanced Movie Center " +EMCVersion+ "\n\n (C) 2012 by\n Coolman, Betonme & Swiss-MAD \n\n If you like this plugin and you want to support it,\n or if just want to say ''thanks'',\n please donate via PayPal. \n\n Thanks a lot ! \n\n PayPal: enhancedmoviecenter@gmail.com" @@ -85,8 +85,6 @@ def setupKeyResponseValues(dummyself=None, dummy=None): def cleanupSetup(dummy=None): try: - #from MovieSelection import gMS - from plugin import gRecordings global trashCleanCall if trashCleanCall is not None: if trashCleanCall.exists(): @@ -109,8 +107,8 @@ def cleanupSetup(dummy=None): # Recall setup funktion trashCleanCall = DelayedFunction(1000*seconds, cleanupSetup) # Execute trash cleaning - #DelayedFunction(2000, gMS.purgeExpired) - DelayedFunction(2000, gRecordings.purgeExpired) + from MovieSelection import purgeExpired + DelayedFunction(2000, purgeExpired) emcDebugOut("Next trashcan cleanup in " + str(seconds/60) + " minutes") except Exception, e: emcDebugOut("[sp] cleanupSetup exception:\n" + str(e)) diff --git a/src/InfoBarSupport.py b/src/InfoBarSupport.py index 20d42d48..f8529cf2 100644 --- a/src/InfoBarSupport.py +++ b/src/InfoBarSupport.py @@ -111,8 +111,11 @@ def __init__(self): "jumpNextMark": (self.jumpNextMark, _("jump to next marked position")), "toggleMark": (self.toggleMark, _("toggle a cut mark at the current position")) }, prio=1) + self.cut_list = [ ] self.is_closing = False + self.resume_point = 0 + self.__event_tracker = ServiceEventTracker(screen=self, eventmap= { iPlayableService.evStart: self.__serviceStarted, @@ -151,7 +154,27 @@ def __serviceStarted(self): self.jumpToFirstMark() elif config.EMC.movie_jump_first_mark.value == True: self.jumpToFirstMark() + + def playLastCB(self, answer): + if answer == True: + self.doSeek(self.resume_point) + # From Merlin2 + elif config.EMC.movie_jump_first_mark.value == True: + self.jumpToFirstMark() + elif self.service and self.service.type == sidDVD: + DelayedFunction(50, boundFunction(self.dvdPlayerWorkaround)) + self.showAfterSeek() + + def numberEntered(self, retval): + if retval and retval > 0 and retval != "": + self.zapToNumber(retval) + def zapToNumber(self, number): + if self.service: + seekable = self.getSeek() + if seekable: + seekable.seekChapter(number) + # From Merlin2 def jumpToFirstMark(self): firstMark = None diff --git a/src/MovieCenter.py b/src/MovieCenter.py index 7ddf5913..91b336b2 100644 --- a/src/MovieCenter.py +++ b/src/MovieCenter.py @@ -35,10 +35,10 @@ from enigma import eListboxPythonMultiContent, eListbox, gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, eServiceReference, eServiceCenter from timer import TimerEntry -from RecordingsControl import RecordingsControl +from . import _ +from RecordingsControl import RecordingsControl, getRecording from DelayedFunction import DelayedFunction from EMCTasker import emcDebugOut -from EnhancedMovieCenter import _ from VlcPluginInterface import VlcPluginInterfaceList, vlcSrv, vlcDir, vlcFil from operator import itemgetter from CutListSupport import CutList @@ -145,6 +145,149 @@ def readBasicCfgFile(file): f.close() return data +#------------------------------------------------- +# func: getPlayerService(path, name="", ext=None) +# +# Determine the service of a media file +#------------------------------------------------- +def getPlayerService(path, name="", ext=None): + if ext in plyDVB: + service = eServiceReference(sidDVB, 0, path) + elif ext in plyMP3: + service = eServiceReference(sidMP3, 0, path) + elif ext in plyDVD: + service = eServiceReference(sidDVD, 0, path) + #QUESTION Is the special name handling really necessary + if service: + # Copied from dvd player + if path.endswith("/VIDEO_TS") or path.endswith("/"): + names = service.toString().rsplit("/",3) + if names[2].startswith("Disk ") or names[2].startswith("DVD "): + #TEST name = str(names[1]) + " - " + str(names[2]) + name = names[1] + " - " + names[2] + else: + name = names[2] + elif ext in plyM2TS: + service = eServiceReference(sidM2TS, 0, path) + else: + path = path.replace(":","") # because of VLC player + service = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path) + if name: + service.setName(name) + return service + +def getProgress(service, length=0, last=0, forceRecalc=False, cuts=None): + # All calculations are done in seconds + # The progress of a recording isn't correct, because we only get the actual length not the final + cuts = None + progress = 0 + #updlen = length + if last <= 0: + # Get last position from cut file + if cuts is None: + cuts = CutList( service.getPath() ) + last = cuts.getCutListLast() + # Check for valid position + if last > 0 or forceRecalc: + # Valid position + # Recalc the movie length to calculate the progress status + if length <= 0: + if service: + esc = eServiceCenter.getInstance() + info = esc and esc.info(service) + length = info and info.getLength(service) or 0 + if length <= 0: + if cuts is None: + cuts = CutList( service.getPath() ) + length = cuts.getCutListLength() + if length <= 0: + # Set default file length if is not calculateable + # 90 minutes = 90 * 60 + length = 5400 + # We only update the entry if we do not use the default value + # updlen = 0 + #else: + # updlen = length + #else: + # updlen = length + if length: + progress = calculateProgress(last, length) + else: + # This should never happen, we always have our default length + progress = 100 + #emcDebugOut("[MC] getProgress(): Last without any length") + else: + # No position implies progress is zero + progress = 0 + return progress, length + +def calculateProgress(last, length): + progress = 0 + if length: + # Adjust the watched movie length (98% of movie length) + # else we will never see the 100% + adjlength = float(length) / 100.0 * 98.0 + # Calculate progress and round up + progress = int( math.ceil ( float(last) / float(adjlength) * 100.0 ) ) + # Normalize progress + if progress < 0: progress = 0 + elif progress > 100: progress = 100 + return progress + +def toggleProgressService(service, preparePlayback, forceProgress=-1, first=False): + if service is None: + return + + # Cut file handling + path = service.getPath() + + # Only for compatibilty reasons + # Should be removed anytime + cuts = path +".cuts" + cutsr = path +".cutsr" + if os.path.exists(cutsr) and not os.path.exists(cuts): + # Rename file - to catch all old EMC revisions + try: + os.rename(cutsr, cuts) + except Exception, e: + emcDebugOut("[CUTS] Exception in toggleProgressService: " + str(e)) + # All calculations are done in seconds + cuts = CutList( path ) + last = cuts.getCutListLast() + #length = self["list"].getLengthOfService(service) + progress, length = getProgress(service, length=0, last=last, forceRecalc=True, cuts=cuts) + + if not preparePlayback: + if first: + if progress < 100: forceProgress = 50 # force next state 100 + else: forceProgress = 100 # force next state 0 + if forceProgress > -1: + progress = forceProgress + + if progress >= 100: + # 100% -> 0 + # Don't care about preparePlayback, always reset to 0% + # Save last marker + cuts.toggleLastCutList(cuts.CUT_TOGGLE_START) + elif progress <= 0: + # 0% -> SAVEDLAST or length + cuts.toggleLastCutList(cuts.CUT_TOGGLE_RESUME) + else: + # 1-99% -> length + cuts.toggleLastCutList(cuts.CUT_TOGGLE_FINISHED) + else: + if progress >= 100 or config.EMC.movie_rewind_finished.value is True and progress >= int(config.EMC.movie_finished_percent.value): + # 100% -> 0 or + # Start playback and rewind is set and movie progress > finished -> 0 + # Don't save SavedMarker + cuts.toggleLastCutList(cuts.CUT_TOGGLE_START_FOR_PLAY) + else: + # Delete SavedMarker + cuts.toggleLastCutList(cuts.CUT_TOGGLE_FOR_PLAY) + + # Update movielist entry + #self["list"].invalidateService(service) + return progress # muss drinnen bleiben sonst crashed es bei foreColorSelected def MultiContentEntryProgress(pos = (0, 0), size = (0, 0), percent = None, borderWidth = None, foreColor = None, foreColorSelected = None, backColor = None, backColorSelected = None): @@ -248,7 +391,7 @@ def __init__(self): # Initially load the movielist # So it must not be done when the user it opens the first time #MAYBE this should be configurable - DelayedFunction(10000, self.reloadIfNecessary, self.loadPath) + #DelayedFunction(10000, self.reloadIfNecessary, self.loadPath) def reloadIfNecessary(self, loadPath): if not self.list: @@ -354,7 +497,7 @@ def resetSorting(self, reload=False): self.list = self.doListSort(self.list) self.l.setList( self.list ) -# Not workin anymore +# Not working anymore # def nextSortingMode(self): # from Plugins.Extensions.EnhancedMovieCenter.plugin import sort_choices # sorts = list( set( [sort for sort, desc in sort_choices] ) ) @@ -446,9 +589,9 @@ def doListSort(self, sortlist): elif mode == "P": # Progress if not order: - sortlist.sort( key=lambda x: ( self.getProgress(x[0], x[6]) ) ) #,x[2],x[8]) ) + sortlist.sort( key=lambda x: ( getProgress(x[0], x[6]) ) ) #,x[2],x[8]) ) else: - sortlist.sort( key=lambda x: ( self.getProgress(x[0], x[6]) ) ) # ,x[2],-x[8]) ) + sortlist.sort( key=lambda x: ( getProgress(x[0], x[6]) ) ) # ,x[2],-x[8]) ) # Combine lists if order: @@ -481,70 +624,6 @@ def recStateChange(self, timer): # But it is fast enough emcDebugOut("[MC] Timer ended") DelayedFunction(3000, self.refreshList) - - from MovieSelection import gMS - if gMS and gMS.playerInstance is not None: - # Check if record is currently played - record = timer.Filename + ".ts" - if record == gMS.playerInstance.service.getPath(): - # WORKAROUND Player is running during a record ends - # We should find a more flexible universal solution - DelayedFunction(3000, self.updatePlayer) - # ATTENTION thist won't fix the other situation - # If a running record will be played and the player is stopped before the record ends - # -> Then E2 will overwrite the existing cuts. - - def updatePlayer(self): - from MovieSelection import gMS - if gMS and gMS.playerInstance is not None: - gMS.playerInstance.updateFromCuesheet() - - def getProgress(self, service, length=0, last=0, forceRecalc=False, cuts=None): - # All calculations are done in seconds - # The progress of a recording isn't correct, because we only get the actual length not the final - cuts = None - progress = 0 - updlen = length - if last <= 0: - # Get last position from cut file - if cuts is None: - cuts = CutList( service.getPath() ) - last = cuts.getCutListLast() - # Check for valid position - if last > 0 or forceRecalc: - # Valid position - # Recalc the movie length to calculate the progress status - if length <= 0: - if service: - esc = eServiceCenter.getInstance() - info = esc and esc.info(service) - length = info and info.getLength(service) or 0 - if length <= 0: - if cuts is None: - cuts = CutList( service.getPath() ) - length = cuts.getCutListLength() - if length <= 0: - # Set default file length if is not calculateable - # 90 minutes = 90 * 60 - length = 5400 - # We only update the entry if we do not use the default value - updlen = 0 - else: - updlen = length - else: - updlen = length - if updlen: - self.updateLength(service, updlen) - if length: - progress = self.calculateProgress(last, length) - else: - # This should never happen, we always have our default length - progress = 100 - #emcDebugOut("[MC] getProgress(): Last without any length") - else: - # No position implies progress is zero - progress = 0 - return progress def getRecordProgress(self, path): # The progress of all recordings is updated @@ -553,28 +632,15 @@ def getRecordProgress(self, path): # The progress of one recording is updated # - if it will be highlighted the list # Note: There is no auto update mechanism of the recording progress - record = self.recControl.getRecording(path) + record = getRecording(path) if record: begin, end, service = record last = time() - begin length = end - begin - return self.calculateProgress(last, length) + return calculateProgress(last, length) else: return 0 - def calculateProgress(self, last, length): - progress = 0 - if length: - # Adjust the watched movie length (98% of movie length) - # else we will never see the 100% - adjlength = float(length) / 100.0 * 98.0 - # Calculate progress and round up - progress = int( math.ceil ( float(last) / float(adjlength) * 100.0 ) ) - # Normalize progress - if progress < 0: progress = 0 - elif progress > 100: progress = 100 - return progress - def updateLength(self, service, length): # Update entry in list... so next time we don't need to recalc idx = self.getIndexOfService(service) @@ -666,7 +732,9 @@ def buildMovieCenterEntry(self, service, sorttitle, date, title, path, selnum, l if config.EMC.movie_progress.value: # Calculate progress and state - progress = service and self.getProgress(service, length) or 0 + progress, updlen = getProgress(service, length) or 0 + if updlen: + self.updateLength(service, updlen) movieUnwatched = config.EMC.movie_progress.value and progress < int(config.EMC.movie_watching_percent.value) movieWatching = config.EMC.movie_progress.value and progress >= int(config.EMC.movie_watching_percent.value) and progress < int(config.EMC.movie_finished_percent.value) movieFinished = config.EMC.movie_progress.value and progress >= int(config.EMC.movie_finished_percent.value) @@ -1441,7 +1509,7 @@ def reload(self, loadPath, simulate=False, recursive=False): except UnicodeDecodeError: title = title.decode("iso-8859-1").encode("utf-8") - service = self.getPlayerService(path, title) + service = getPlayerService(path, title) sorttitle = title.lower() @@ -1572,7 +1640,7 @@ def reload(self, loadPath, simulate=False, recursive=False): title += " "+ext[1:] # Get player service and set formatted title - service = self.getPlayerService(path, title, ext) + service = getPlayerService(path, title, ext) # Bad workaround to get all information into our Service Source service.date = date @@ -1685,7 +1753,7 @@ def getNextService(self): if dvdStruct: pathname = os.path.dirname(dvdStruct) ext = os.path.splitext(dvdStruct)[1].lower() - service = self.getPlayerService(pathname, dir, ext) + service = getPlayerService(pathname, dir, ext) if not self.serviceBusy(service): yield service if files: @@ -1694,7 +1762,7 @@ def getNextService(self): if ext in extMedia: pathname = os.path.join(root, name) #TODO get formatted Name - service = self.getPlayerService(pathname, name, ext) + service = getPlayerService(pathname, name, ext) if not self.serviceBusy(service): yield service @@ -1740,7 +1808,7 @@ def getRandomService(self): ext = os.path.splitext(pathname)[1] if ext in plyAll: # Entry is playable - service = self.getPlayerService(pathname, entry, ext) + service = getPlayerService(pathname, entry, ext) if not self.serviceBusy(service): yield service @@ -1749,36 +1817,10 @@ def getRandomService(self): if dvdStruct: path = os.path.dirname(dvdStruct) ext = os.path.splitext(dvdStruct)[1].lower() - service = self.getPlayerService(path, entry, ext) + service = getPlayerService(path, entry, ext) if not self.serviceBusy(service): yield service - def getPlayerService(self, path, name="", ext=None): - if ext in plyDVB: - service = eServiceReference(sidDVB, 0, path) - elif ext in plyMP3: - service = eServiceReference(sidMP3, 0, path) - elif ext in plyDVD: - service = eServiceReference(sidDVD, 0, path) - #QUESTION Is the special name handling really necessary - if service: - # Copied from dvd player - if path.endswith("/VIDEO_TS") or path.endswith("/"): - names = service.toString().rsplit("/",3) - if names[2].startswith("Disk ") or names[2].startswith("DVD "): - #TEST name = str(names[1]) + " - " + str(names[2]) - name = names[1] + " - " + names[2] - else: - name = names[2] - elif ext in plyM2TS: - service = eServiceReference(sidM2TS, 0, path) - else: - path = path.replace(":","") # because of VLC player - service = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path) - if name: - service.setName(name) - return service - def currentSelIsPlayable(self): try: return self.list[self.getCurrentIndex()][7] in extMedia except: return False diff --git a/src/MovieSelection.py b/src/MovieSelection.py index 4af08da5..18e7a162 100644 --- a/src/MovieSelection.py +++ b/src/MovieSelection.py @@ -52,7 +52,7 @@ from DelayedFunction import DelayedFunction from EnhancedMovieCenter import _ from EMCTasker import emcTasker, emcDebugOut -from MovieCenter import MovieCenter +from MovieCenter import MovieCenter, getPlayerService, getProgress, toggleProgressService from MovieSelectionMenu import MovieMenu from EMCMediaCenter import EMCMediaCenter from VlcPluginInterface import VlcPluginInterfaceSel @@ -68,7 +68,110 @@ from MovieCenter import extList, extVideo, extMedia, extDir, plyAll, plyDVD, cmtBME2, cmtBMEMC, cmtDir global extList, extVideo, extMedia, extDir, plyAll, plyDVD, cmtBME2, cmtBMEMC, cmtDir -gMS = None + +# Move all trashcan operations to a separate file / class +def purgeExpired(emptyTrash=False): + try: + movie_trashpath = config.EMC.movie_trashcan_path.value + movie_homepath = os.path.realpath(config.EMC.movie_homepath.value) + + # Avoid cleaning the movie home folder + for root, dirs, files in os.walk(movie_trashpath): + if os.path.realpath(root) in movie_homepath: + AddPopup( + _("EMC: Skipping Trashcan Cleanup\nMovie Home Path is equal to or a subfolder of the Trashcan"), + MessageBox.TYPE_INFO, + 0, + "EMC_TRASHCAN_CLEANUP_SKIPPED_ID" + ) + return + + if os.path.exists(movie_trashpath): + if config.EMC.movie_trashcan_clean.value is True or emptyTrash: + # Trashcan cleanup + purgeCmd = "" + currTime = localtime() + for root, dirs, files in os.walk(movie_trashpath): + for movie in files: + # Only check media files + ext = os.path.splitext(movie)[1].lower() + if ext in extMedia: + fullpath = os.path.join(root, movie) + if os.path.exists(fullpath): + if emptyTrash or currTime > localtime(os.stat(fullpath).st_mtime + 24*60*60*int(config.EMC.movie_trashcan_limit.value)): + #purgeCmd += '; rm -f "'+ os.path.splitext(fullpath)[0] +'."*' + + #TEST_E2DELETE + service = getPlayerService(fullpath, movie, ext) + serviceHandler = eServiceCenter.getInstance() + offline = serviceHandler.offlineOperations(service) + result = False + if offline is not None: + # really delete! + if not offline.deleteFromDisk(0): + result = True + if result == False: + AddPopup( + _("EMC Trashcan Cleanup failed!"), + MessageBox.TYPE_ERROR, + 0, + "EMC_TRASHCAN_CLEANUP_FAILED_ID" + ) + return + else: + path = os.path.splitext(fullpath)[0].replace("'","\'") + purgeCmd += '; rm -f "'+ path +'."*' + #TEST_E2DELETE + + if purgeCmd != "": + emcTasker.shellExecute(purgeCmd[2:]) + emcDebugOut("[EMCMS] trashcan cleanup activated") + else: + emcDebugOut("[EMCMS] trashcan cleanup: nothing to delete...") + if config.EMC.movie_finished_clean.value is True: + #TODO very slow + # Movie folder cleanup + # Start only if dreambox is in standby + # No subdirectory handling + import Screens.Standby + if Screens.Standby.inStandby: + mvCmd = "" + currTime = localtime() + for root, dirs, files in os.walk(movie_homepath): + if root.startswith(movie_trashpath): + # Don't handle the trashcan and its subfolders + continue + for movie in files: + + # Only check media files + ext = os.path.splitext(movie)[1].lower() + if ext in extMedia: + fullpath = os.path.join(root, movie) + fullpathcuts = fullpath + ".cuts" + if os.path.exists(fullpathcuts): + if currTime > localtime(os.stat(fullpathcuts).st_mtime + 24*60*60*int(config.EMC.movie_finished_limit.value)): + # Check progress + service = getPlayerService(fullpath, movie, ext) + progress, length = getProgress(service, forceRecalc=True) + if progress >= int(config.EMC.movie_finished_percent.value): + # cut file extension + fullpath = os.path.splitext(fullpath)[0].replace("'","\'") + # create a time stamp with touch for all corresponding files + mvCmd += '; touch "'+ fullpath +'."*' + # move movie into the trashcan + mvCmd += '; mv "'+ fullpath +'."* "'+ movie_trashpath +'"' + if mvCmd != "": + association = [] + #Not necessary anymore - Is done always on show + #association.append((reloadList)) # Force list reload after cleaning + emcTasker.shellExecute(mvCmd[2:], association) + emcDebugOut("[EMCMS] finished movie cleanup activated") + else: + emcDebugOut("[EMCMS] finished movie cleanup: nothing to move...") + else: + emcDebugOut("[EMCMS] trashcan cleanup: no trashcan...") + except Exception, e: + emcDebugOut("[EMCMS] purgeExpired exception:\n" + str(e)) class SelectionEventInfo: @@ -234,7 +337,11 @@ def dvdPlayerWorkaround(self): class EMCSelection(Screen, HelpableScreen, SelectionEventInfo, VlcPluginInterfaceSel, DirectoryStack, E2Bookmarks, EMCBookmarks): - def __init__(self, session): + + returnService = None + currentPath = None + + def __init__(self, session, playerInstance=None, returnService=None): Screen.__init__(self, session) SelectionEventInfo.__init__(self) VlcPluginInterfaceSel.__init__(self) @@ -254,10 +361,11 @@ def __init__(self, session): self.skin = Cool.read() Cool.close() - self.playerInstance = None + self.playerInstance = playerInstance self.lastPlayedMovies = None self.multiSelectIdx = None - self.returnService = None + if returnService: + self.returnService = returnService self.lastservice = None self.cursorDir = 0 self["wait"] = Label(_("Reading directory...")) @@ -267,8 +375,6 @@ def __init__(self, session): self["key_green"] = Button() self["key_yellow"] = Button() self["key_blue"] = Button() - global gMS - gMS = self self["actions"] = HelpableActionMap(self, "PluginMovieSelectionActions", { "EMCOK": (self.entrySelected, _("Play selected movie(s)")), @@ -321,7 +427,8 @@ def __init__(self, session): HelpableScreen.__init__(self) - self.currentPath = config.EMC.movie_homepath.value + if self.currentPath == None: + self.currentPath = config.EMC.movie_homepath.value self.tmpSelList = None # Used for file operations # Key press short long handling @@ -463,7 +570,7 @@ def setNextPath(self, nextdir = None, service = None): if nextdir == ".." or nextdir is None or nextdir.endswith(".."): if self.currentPath != "" and self.currentPath != "/": # Open Parent folder - service = self["list"].getPlayerService(self.currentPath) + service = getPlayerService(self.currentPath) nextdir = os.path.dirname(self.currentPath) else: # No way to go folder up @@ -596,7 +703,7 @@ def menuCallback(self, selection=None, parameter=None): elif selection == "reload": self.initList() elif selection == "plugin": self.onDialogShow() elif selection == "setup": self.onDialogShow() - elif selection == "ctrash": self.purgeExpired() + elif selection == "ctrash": purgeExpired() elif selection == "trash": self.changeDir(config.EMC.movie_trashcan_path.value) elif selection == "delete": self.deleteFile(True) elif selection == "cutlistmarker": self.removeCutListMarker() @@ -610,7 +717,7 @@ def menuCallback(self, selection=None, parameter=None): elif selection == "updatetitle": self.updateTitle() elif selection == "imdb": self.imdb() elif selection == "rename": self.rename() - elif selection == "emptytrash": self.purgeExpired(emptyTrash=True) + elif selection == "emptytrash": purgeExpired(emptyTrash=True) def openMenu(self): current = self.getCurrent() @@ -844,7 +951,7 @@ def resetSelectionList(self): for service in selectedlist: self["list"].toggleSelection(service) - def toggleProgress(self, service=None, preparePlayback=False): + def toggleProgress(self, service=None): if self.multiSelectIdx: self.multiSelectIdx = None self.updateTitle() @@ -855,70 +962,16 @@ def toggleProgress(self, service=None, preparePlayback=False): if current is not None: # Force copy of selectedlist selectedlist = self["list"].makeSelectionList()[:] - if len(selectedlist)>1 and not preparePlayback: + if len(selectedlist)>1: first = True for sel in selectedlist: - progress = self.__toggleProgressService(sel, preparePlayback, forceProgress, first) + progress = toggleProgressService(sel, False, forceProgress, first) + self["list"].invalidateService(service) first = False - if not preparePlayback: - forceProgress = progress - else: - self.__toggleProgressService(service, preparePlayback) - - def __toggleProgressService(self, service, preparePlayback, forceProgress=-1, first=False): - if service is None: - return - - # Cut file handling - path = service.getPath() - - # Only for compatibilty reasons - # Should be removed anytime - cuts = path +".cuts" - cutsr = path +".cutsr" - if os.path.exists(cutsr) and not os.path.exists(cuts): - # Rename file - to catch all old EMC revisions - try: - os.rename(cutsr, cuts) - except Exception, e: - emcDebugOut("[CUTS] Exception in __toggleProgressService: " + str(e)) - # All calculations are done in seconds - cuts = CutList( path ) - last = cuts.getCutListLast() - length = self["list"].getLengthOfService(service) - progress = self["list"].getProgress(service, length=length, last=last, forceRecalc=True, cuts=cuts) - - if not preparePlayback: - if first: - if progress < 100: forceProgress = 50 # force next state 100 - else: forceProgress = 100 # force next state 0 - if forceProgress > -1: - progress = forceProgress - - if progress >= 100: - # 100% -> 0 - # Don't care about preparePlayback, always reset to 0% - # Save last marker - cuts.toggleLastCutList(cuts.CUT_TOGGLE_START) - elif progress <= 0: - # 0% -> SAVEDLAST or length - cuts.toggleLastCutList(cuts.CUT_TOGGLE_RESUME) - else: - # 1-99% -> length - cuts.toggleLastCutList(cuts.CUT_TOGGLE_FINISHED) - else: - if progress >= 100 or config.EMC.movie_rewind_finished.value is True and progress >= int(config.EMC.movie_finished_percent.value): - # 100% -> 0 or - # Start playback and rewind is set and movie progress > finished -> 0 - # Don't save SavedMarker - cuts.toggleLastCutList(cuts.CUT_TOGGLE_START_FOR_PLAY) - else: - # Delete SavedMarker - cuts.toggleLastCutList(cuts.CUT_TOGGLE_FOR_PLAY) - - # Update movielist entry - self["list"].invalidateService(service) - return progress + #if not preparePlayback: + forceProgress = progress + #else: + # toggleProgressService(service, preparePlayback) def IMDbSearch(self): name = '' @@ -1199,11 +1252,11 @@ def __reloadList(self, path): ############################################################################# # Playback functions # - def setPlayerInstance(self, player): - try: - self.playerInstance = player - except Exception, e: - emcDebugOut("[EMCMS] setPlayerInstance exception:\n" + str(e)) +# def setPlayerInstance(self, player): +# try: +# self.playerInstance = player +# except Exception, e: +# emcDebugOut("[EMCMS] setPlayerInstance exception:\n" + str(e)) def openPlayer(self, playlist, playall=False): # Force update of event info after playing movie @@ -1221,12 +1274,11 @@ def openPlayer(self, playlist, playall=False): # Start Player if self.playerInstance is None: - self.close(playlistcopy, self, playall, self.lastservice) + self.close(playlistcopy, playall, self.lastservice) self.busy = False else: self.playerInstance.movieSelected(playlist, playall) self.busy = False - self.close() def entrySelected(self, playall=False): @@ -1330,9 +1382,6 @@ def lastPlayedCheck(self, service): # else: # return False - def getRecording(self, path): - return self["list"].recControl.getRecording(path) - def stopRecordConfirmation(self, confirmed): if not confirmed: return # send as a list? @@ -1826,106 +1875,4 @@ def trashcanCreate(self, confirmed): self.session.open(MessageBox, _("Trashcan create failed. Check mounts and permissions."), MessageBox.TYPE_ERROR) emcDebugOut("[EMCMS] trashcanCreate exception:\n" + str(e)) - # Move all trashcan operations to a separate class - def purgeExpired(self, emptyTrash=False): - try: - movie_trashpath = config.EMC.movie_trashcan_path.value - movie_homepath = os.path.realpath(config.EMC.movie_homepath.value) - - # Avoid cleaning the movie home folder - for root, dirs, files in os.walk(movie_trashpath): - if os.path.realpath(root) in movie_homepath: - AddPopup( - _("EMC: Skipping Trashcan Cleanup\nMovie Home Path is equal to or a subfolder of the Trashcan"), - MessageBox.TYPE_INFO, - 0, - "EMC_TRASHCAN_CLEANUP_SKIPPED_ID" - ) - return - - if os.path.exists(movie_trashpath): - if config.EMC.movie_trashcan_clean.value is True or emptyTrash: - # Trashcan cleanup - purgeCmd = "" - currTime = localtime() - for root, dirs, files in os.walk(movie_trashpath): - for movie in files: - # Only check media files - ext = os.path.splitext(movie)[1].lower() - if ext in extMedia: - fullpath = os.path.join(root, movie) - if os.path.exists(fullpath): - if emptyTrash or currTime > localtime(os.stat(fullpath).st_mtime + 24*60*60*int(config.EMC.movie_trashcan_limit.value)): - #purgeCmd += '; rm -f "'+ os.path.splitext(fullpath)[0] +'."*' - - #TEST_E2DELETE - service = self["list"].getPlayerService(fullpath, movie, ext) - serviceHandler = eServiceCenter.getInstance() - offline = serviceHandler.offlineOperations(service) - result = False - if offline is not None: - # really delete! - if not offline.deleteFromDisk(0): - result = True - if result == False: - #self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR) - AddPopup( - _("EMC Trashcan Cleanup failed!"), - MessageBox.TYPE_ERROR, - 0, - "EMC_TRASHCAN_CLEANUP_FAILED_ID" - ) - return - else: - path = os.path.splitext(fullpath)[0].replace("'","\'") - purgeCmd += '; rm -f "'+ path +'."*' - #TEST_E2DELETE - - if purgeCmd != "": - emcTasker.shellExecute(purgeCmd[2:]) - emcDebugOut("[EMCMS] trashcan cleanup activated") - else: - emcDebugOut("[EMCMS] trashcan cleanup: nothing to delete...") - if config.EMC.movie_finished_clean.value is True: - #TODO very slow - # Movie folder cleanup - # Start only if dreambox is in standby - # No subdirectory handling - import Screens.Standby - if Screens.Standby.inStandby: - mvCmd = "" - currTime = localtime() - for root, dirs, files in os.walk(movie_homepath): - if root.startswith(movie_trashpath): - # Don't handle the trashcan and its subfolders - continue - for movie in files: - - # Only check media files - ext = os.path.splitext(movie)[1].lower() - if ext in extMedia: - fullpath = os.path.join(root, movie) - fullpathcuts = fullpath + ".cuts" - if os.path.exists(fullpathcuts): - if currTime > localtime(os.stat(fullpathcuts).st_mtime + 24*60*60*int(config.EMC.movie_finished_limit.value)): - # Check progress - service = self["list"].getPlayerService(fullpath, movie, ext) - progress = self["list"].getProgress(service, forceRecalc=True) - if progress >= int(config.EMC.movie_finished_percent.value): - # cut file extension - fullpath = os.path.splitext(fullpath)[0].replace("'","\'") - # create a time stamp with touch for all corresponding files - mvCmd += '; touch "'+ fullpath +'."*' - # move movie into the trashcan - mvCmd += '; mv "'+ fullpath +'."* "'+ movie_trashpath +'"' - if mvCmd != "": - association = [] - association.append((self.reloadList)) # Force list reload after cleaning - emcTasker.shellExecute(mvCmd[2:], association) - emcDebugOut("[EMCMS] finished movie cleanup activated") - else: - emcDebugOut("[EMCMS] finished movie cleanup: nothing to move...") - else: - emcDebugOut("[EMCMS] trashcan cleanup: no trashcan...") - except Exception, e: - emcDebugOut("[EMCMS] purgeExpired exception:\n" + str(e)) + diff --git a/src/RecordingsControl.py b/src/RecordingsControl.py index 33aa7675..cd043dc5 100644 --- a/src/RecordingsControl.py +++ b/src/RecordingsControl.py @@ -30,6 +30,21 @@ from DelayedFunction import DelayedFunction +def getRecording(filename): + try: + if filename[0] == "/": filename = os.path.basename(filename) + if filename.endswith(".ts"): filename = filename[:-3] + + for timer in NavigationInstance.instance.RecordTimer.timer_list: + try: timer.Filename + except: timer.calculateFilename() + if filename == os.path.basename(timer.Filename): + return timer.begin, timer.end, timer.service_ref.ref + except Exception, e: + emcDebugOut("[emcRC] getRecording exception:\n" + str(e)) + return None + + class NetworkAwareness: def __init__(self): self.retries = 0 @@ -137,24 +152,6 @@ def isRecording(self, filename): emcDebugOut("[emcRC] isRecording exception:\n" + str(e)) return False - def getRecording(self, filename): - try: - if filename[0] == "/": filename = os.path.basename(filename) - if filename.endswith(".ts"): filename = filename[:-3] - if filename in self.recDict: - begin, end, ref, id = self.recDict[filename] - if end - begin == 0: - for timer in NavigationInstance.instance.RecordTimer.timer_list: - if str(timer) == id: - # Update record times - begin = timer.begin - end = timer.end - self.recDict[filename] = (begin, end, ref, id) - return begin, end, ref - except Exception, e: - emcDebugOut("[emcRC] getRecording exception:\n" + str(e)) - return None - def isRemoteRecording(self, filename): try: if filename[0] == "/": filename = os.path.basename(filename) @@ -236,11 +233,12 @@ def recFilesRead(self): self.recRemoteList = [] recf = None try: - for x in os.listdir(config.EMC.folder.value): - path = os.path.join(config.EMC.folder.value, x) - if x.endswith(".rec") and path != self.recFile: - recf = open( path, "rb" ) - self.recRemoteList += pickle.load(recf) + if config.EMC.folder.value and os.path.exists(config.EMC.folder.value): + for x in os.listdir(config.EMC.folder.value): + path = os.path.join(config.EMC.folder.value, x) + if x.endswith(".rec") and path != self.recFile: + recf = open( path, "rb" ) + self.recRemoteList += pickle.load(recf) except Exception, e: emcDebugOut("[emcRC] recFilesRead exception:\n" + str(e)) finally: diff --git a/src/ServiceSupport.py b/src/ServiceSupport.py index 1c5c30e7..7a820c63 100644 --- a/src/ServiceSupport.py +++ b/src/ServiceSupport.py @@ -32,7 +32,7 @@ from CutListSupport import CutList from MetaSupport import MetaList from EitSupport import EitList - +from RecordingsControl import getRecording instance = None @@ -164,7 +164,7 @@ def __init__(self, service): self.__extendeddescription = eit and eit.getEitDescription() \ or meta and meta.getMetaDescription() \ or "" - ## + if not self.__extendeddescription: if isreal: if config.EMC.movie_real_path.value: @@ -249,8 +249,7 @@ def getLength(self, service=None): # If it is a record we will force to use the timer duration length = 0 if config.EMC.record_show_real_length.value: - from MovieSelection import gMS - record = gMS.getRecording(self.path) + record = getRecording(self.path) if record: begin, end, service = record length = end - begin # times = (begin, end) : end - begin diff --git a/src/plugin.py b/src/plugin.py index cd8a24c6..e30054ed 100644 --- a/src/plugin.py +++ b/src/plugin.py @@ -138,10 +138,10 @@ def langListSel(): # Date format is implemented using datetime.strftime date_choices = [ ("", _("Off")), - ("%d.%m.%Y", _("DD.MM.YYYY")), + ("%d.%m.%Y", _("DD.MM.YYYY")), ("%d.%m %H:%M", _("DD.MM HH:MM")), - ("%d.%m. %H:%M", _("DD.MM. HH:MM")), - ("%Y/%m/%d", _("YYYY/MM/DD")), + ("%d.%m. %H:%M", _("DD.MM. HH:MM")), + ("%Y/%m/%d", _("YYYY/MM/DD")), ("%m/%d %H:%M", _("MM/DD HH:MM")) ] dirinfo_choices = [ ("", _("Off")), @@ -289,13 +289,12 @@ def langListSel(): config.EMC.InfoLong = ConfigSelection(choices = [("IMDbSearch", _("IMDb Search")), ("TMDBInfo", _("TMDB Info")), ('CSFDInfo', _('CSFD Info'))], default = "IMDbSearch") gSession = None -gRecordings = None def showMoviesNew(dummy_self = None): try: - global gSession, gRecordings - gSession.execDialog(gRecordings) - gRecordings.callback = showMoviesCallback + global gSession + from MovieSelection import EMCSelection + gSession.openWithCallback(showMoviesCallback, EMCSelection) except Exception, e: emcDebugOut("[showMoviesNew] exception:\n" + str(e)) @@ -316,8 +315,8 @@ def autostart(reason, **kwargs): if reason == 0: # start if kwargs.has_key("session"): global gSession - gSession = kwargs["session"] from EnhancedMovieCenter import EMCStartup + gSession = kwargs["session"] EMCStartup(gSession) emcTasker.Initialize(gSession) @@ -334,21 +333,21 @@ def autostart(reason, **kwargs): emcDebugOut("[spStartup] MovieCenter launch override exception:\n" + str(e)) try: - global gRecordings from MovieSelection import EMCSelection - gRecordings = gSession.instantiateDialog(EMCSelection) + gSession.openWithCallback(showMoviesCallback, EMCSelection) except Exception, e: emcDebugOut("[spStartup] instantiateDialog exception:\n" + str(e)) def pluginOpen(session, *args, **kwargs): - from EnhancedMovieCenter import EnhancedMovieCenterMenu try: + from EnhancedMovieCenter import EnhancedMovieCenterMenu session.open(EnhancedMovieCenterMenu) except Exception, e: emcDebugOut("[pluginOpen] exception:\n" + str(e)) def recordingsOpen(session, *args, **kwargs): - showMoviesNew() + from MovieSelection import EMCSelection + session.openWithCallback(showMoviesCallback, EMCSelection) def Plugins(**kwargs): from EnhancedMovieCenter import EMCVersion