def __init__(self): utils.check_data_dir() #in case this directory does not exist yet self.monitor = UpdateMonitor(update_settings = self.createSchedules,after_scan = self.databaseUpdated) self.readLastRun() self.customPaths = CustomPathFile() #force and update on startup to create the array self.createSchedules(True)
def createSchedules(self, forceUpdate=False): utils.log("update timers") self.lock = True # lock so the eval portion does not run self.schedules = [] showDialogs = utils.getSettingBool( 'notify_next_run' ) # if the user has selected to show dialogs for library operations if (utils.getSettingBool('clean_libraries')): # create clean schedule (if needed) if (utils.getSettingInt("clean_timer") != 0): if (utils.getSettingInt('library_to_clean') == 0 or utils.getSettingInt('library_to_clean') == 1): # video clean schedule starts at 12am by default aSchedule = CronSchedule() aSchedule.name = utils.getString(30048) aSchedule.timer_type = utils.__addon_id__ aSchedule.command = { 'method': 'VideoLibrary.Clean', 'params': { 'showdialogs': showDialogs } } if (utils.getSettingInt("clean_timer") == 4): aSchedule.expression = utils.getSetting( "clean_video_cron_expression") else: aSchedule.expression = "0 0 " + aSchedule.cleanLibrarySchedule( utils.getSettingInt("clean_timer")) aSchedule.next_run = self.calcNextRun( aSchedule.expression, time.time()) self.schedules.append(aSchedule) if (utils.getSettingInt('library_to_clean') == 2 or utils.getSettingInt('library_to_clean') == 0): # music clean schedule starts at 2am by default aSchedule = CronSchedule() aSchedule.name = utils.getString(30049) aSchedule.timer_type = utils.__addon_id__ aSchedule.command = { 'method': 'AudioLibrary.Clean', 'params': { 'showdialogs': showDialogs } } if (utils.getSettingInt("clean_timer") == 4): aSchedule.expression = utils.getSetting( "clean_music_cron_expression") else: aSchedule.expression = "0 2 " + aSchedule.cleanLibrarySchedule( utils.getSettingInt("clean_timer")) aSchedule.next_run = self.calcNextRun( aSchedule.expression, time.time()) self.schedules.append(aSchedule) if (utils.getSettingBool('update_video')): utils.log("Creating timer for Video Library") # create the video schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30012) aSchedule.command = { 'method': 'VideoLibrary.Scan', 'params': { 'showdialogs': showDialogs } } aSchedule.expression = self.checkTimer('video') aSchedule.next_run = self.calcNextRun(aSchedule.expression, self.last_run) self.schedules.append(aSchedule) # add custom video paths (separate timers) customPaths = CustomPathFile('video') for aJob in customPaths.getSchedules(showDialogs): utils.log("Creating timer " + aJob.name) aJob.next_run = self.calcNextRun(aJob.expression, self.last_run) self.schedules.append(aJob) if (utils.getSettingBool('update_music')): utils.log("Creating timer for Music Library") # create the music schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30013) aSchedule.command = { 'method': 'AudioLibrary.Scan', 'params': { 'showdialogs': showDialogs } } aSchedule.expression = self.checkTimer('music') aSchedule.next_run = self.calcNextRun(aSchedule.expression, self.last_run) self.schedules.append(aSchedule) # add custom music paths (separate timers) customPaths = CustomPathFile('music') for aJob in customPaths.getSchedules(showDialogs): utils.log("Creating timer " + aJob.name) aJob.next_run = self.calcNextRun(aJob.expression, self.last_run) self.schedules.append(aJob) # release the lock self.lock = False utils.log("Created " + str(len(self.schedules)) + " schedules", xbmc.LOGDEBUG) # show any notifications self.showNotify(not forceUpdate)
class AutoUpdater: last_run = 0 sleep_time = 500 schedules = [] lock = False monitor = None customPaths = None #setup the timer amounts timer_amounts = {} timer_amounts['0'] = 1 timer_amounts['1'] = 2 timer_amounts['2'] = 4 timer_amounts['3'] = 6 timer_amounts['4'] = 12 timer_amounts['5'] = 24 def __init__(self): utils.check_data_dir() #in case this directory does not exist yet self.monitor = UpdateMonitor(update_settings = self.createSchedules,after_scan = self.databaseUpdated) self.readLastRun() self.customPaths = CustomPathFile() #force and update on startup to create the array self.createSchedules(True) def runProgram(self): #a one-time catch for the startup delay if(int(utils.getSetting("startup_delay")) != 0): count = 0 while count < len(self.schedules): if(time.time() > self.schedules[count].next_run): #we missed at least one update, fix this self.schedules[count].next_run = time.time() + int(utils.getSetting("startup_delay")) * 60 count = count + 1 #program has started, check if we should show a notification self.showNotify() while(not xbmc.abortRequested): #don't check unless new minute if(time.time() > self.last_run + 60): self.readLastRun() self.evalSchedules() xbmc.sleep(self.sleep_time) #clean up monitor on exit del self.monitor def evalSchedules(self): if(not self.lock): now = time.time() count = 0 while count < len(self.schedules): cronJob = self.schedules[count] if(cronJob.next_run <= now): if(xbmc.Player().isPlaying() == False or utils.getSetting("run_during_playback") == "true"): if(utils.getSetting('run_on_idle') == 'false' or (utils.getSetting('run_on_idle') == 'true' and self.monitor.screensaver_running)): #check for valid network connection if(self._networkUp()): #check if this scan was delayed due to playback if(cronJob.on_delay == True): #add another minute to the delay self.schedules[count].next_run = now + 60 self.schedules[count].on_delay = False utils.log(cronJob.name + " paused due to playback") elif(self.scanRunning() == False): #run the command for this job utils.log(cronJob.name) if(cronJob.timer_type == 'xbmc'): xbmc.executebuiltin(cronJob.command) else: self.cleanLibrary(cronJob.command) #find the next run time cronJob.next_run = self.calcNextRun(cronJob.expression,now) self.schedules[count] = cronJob elif(self.scanRunning() == True): self.schedules[count].next_run = now + 60 utils.log("Waiting for other scan to finish") else: utils.log("Network down, not running") else: utils.log("Skipping scan, only run when idle") else: self.schedules[count].on_delay = True utils.log("Player is running, wait until finished") count = count + 1 #write last run time now = time.time() self.last_run = now - (now % 60) def createSchedules(self,forceUpdate = False): utils.log("update timers") self.lock = True #lock so the eval portion does not run self.schedules = [] if(utils.getSetting('clean_libraries') == 'true'): #create clean schedule (if needed) if(int(utils.getSetting("clean_timer")) != 0): if(utils.getSetting('library_to_clean') == '0' or utils.getSetting('library_to_clean') == '1'): #video clean schedule starts at 12am by default aSchedule = CronSchedule() aSchedule.name = utils.getString(30048) aSchedule.timer_type = utils.__addon_id__ aSchedule.command = 'video' if(int(utils.getSetting("clean_timer")) == 4): aSchedule.expression = utils.getSetting("clean_video_cron_expression") else: aSchedule.expression = "0 0 " + aSchedule.cleanLibrarySchedule(int(utils.getSetting("clean_timer"))) aSchedule.next_run = self.calcNextRun(aSchedule.expression,time.time()) self.schedules.append(aSchedule) if(utils.getSetting('library_to_clean') == '2' or utils.getSetting('library_to_clean') == '0'): #music clean schedule starts at 2am by default aSchedule = CronSchedule() aSchedule.name = utils.getString(30049) aSchedule.timer_type = utils.__addon_id__ aSchedule.command = 'music' if(int(utils.getSetting("clean_timer")) == 4): aSchedule.expression = utils.getSetting("clean_music_cron_expression") else: aSchedule.expression = "0 2 " + aSchedule.cleanLibrarySchedule(int(utils.getSetting("clean_timer"))) aSchedule.next_run = self.calcNextRun(aSchedule.expression,time.time()) self.schedules.append(aSchedule) if(utils.getSetting('update_video') == 'true'): utils.log("Creating timer for Video Library"); #create the video schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30012) aSchedule.command = 'UpdateLibrary(video)' aSchedule.expression = self.checkTimer('video') aSchedule.next_run = self.calcNextRun(aSchedule.expression,self.last_run) self.schedules.append(aSchedule) if(utils.getSetting('update_music') == 'true'): utils.log("Creating timer for Music Library"); #create the music schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30013) aSchedule.command = 'UpdateLibrary(music)' aSchedule.expression = self.checkTimer('music') aSchedule.next_run = self.calcNextRun(aSchedule.expression,self.last_run) self.schedules.append(aSchedule) if(utils.getSetting('use_custom_1_path') == 'true'): utils.log("Creating timer for Custom Path 1"); #create a custom video path schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30020) aSchedule.command = 'UpdateLibrary(video,' + utils.getSetting('custom_1_scan_path') + ')' aSchedule.expression = self.checkTimer('custom_1') aSchedule.next_run = self.calcNextRun(aSchedule.expression,self.last_run) self.schedules.append(aSchedule) if(utils.getSetting('use_custom_2_path') == 'true'): utils.log("Creating timer for Custom Path 2"); #create a custom video path schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30021) aSchedule.command = 'UpdateLibrary(video,' + utils.getSetting('custom_2_scan_path') + ')' aSchedule.expression = self.checkTimer('custom_2') aSchedule.next_run = self.calcNextRun(aSchedule.expression,self.last_run) self.schedules.append(aSchedule) if(utils.getSetting('use_custom_3_path') == 'true'): utils.log("Creating timer for Custom Path 3"); #create a custom video path schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30022) aSchedule.command = 'UpdateLibrary(video,' + utils.getSetting('custom_3_scan_path') + ')' aSchedule.expression = self.checkTimer('custom_3') aSchedule.next_run = self.calcNextRun(aSchedule.expression,self.last_run) self.schedules.append(aSchedule) #read in any custom path options for aJob in self.customPaths.getJobs(): utils.log("Creating timer " + aJob.name) aJob.next_run = self.calcNextRun(aJob.expression, self.last_run) self.schedules.append(aJob) #release the lock self.lock = False utils.log("Created " + str(len(self.schedules)) + " schedules",xbmc.LOGDEBUG) #show any notifications self.showNotify(not forceUpdate) def checkTimer(self,settingName): result = '' #figure out if using standard or advanced timer if(utils.getSetting(settingName + '_advanced_timer') == 'true'): #copy the expression result = utils.getSetting(settingName + "_cron_expression") else: result = '0 */' + str(self.timer_amounts[utils.getSetting(settingName + "_timer")]) + ' * * *' return result def calcNextRun(self,cronExp,startTime): #create croniter for this expression cron = croniter(cronExp,startTime) nextRun = cron.get_next(float) return nextRun def showNotify(self,displayToScreen = True): #go through and find the next schedule to run next_run_time = CronSchedule() for cronJob in self.schedules: if(cronJob.next_run < next_run_time.next_run or next_run_time.next_run == 0): next_run_time = cronJob inWords = self.nextRunCountdown(next_run_time.next_run) #show the notification (if applicable) if(next_run_time.next_run > time.time() and utils.getSetting('notify_next_run') == 'true' and displayToScreen == True): utils.showNotification(utils.getString(30000),next_run_time.name + " - " + inWords) return inWords def nextRunCountdown(self,nextRun): #compare now with next date cronDiff = nextRun - time.time() if cronDiff < 0: return "" hours = int((cronDiff / 60) / 60) minutes = int(round(cronDiff / 60.0 - hours * 60)) #we always have at least one minute if minutes == 0: minutes = 1 result = str(hours) + " h " + str(minutes) + " m" if hours == 0: result = str(minutes) + " m" elif hours > 36: #just show the date instead result = datetime.fromtimestamp(nextRun).strftime('%m/%d %I:%M%p') elif hours > 24: days = int(hours / 24) hours = hours - days * 24 result = str(days) + " d " + str(hours) + " h " + str(minutes) + " m" return result def cleanLibrary(self,media_type): #check if we should verify with user first if(utils.getSetting('user_confirm_clean') == 'true'): #user can decide 'no' here and exit this runClean = xbmcgui.Dialog().yesno(utils.getString(30000),utils.getString(30052),line2=utils.getString(30053),autoclose=15000) if(not runClean): return #run the clean operation utils.log("Cleaning Database") xbmc.executebuiltin("CleanLibrary(" + media_type + ")") #write last run time, will trigger notifications self.writeLastRun() def readLastRun(self): if(self.last_run == 0): #read it in from the settings if(xbmcvfs.exists(xbmc.translatePath(utils.data_dir() + "last_run.txt"))): runFile = xbmcvfs.File(xbmc.translatePath(utils.data_dir() + "last_run.txt")) try: #there may be an issue with this file, we'll get it the next time through self.last_run = float(runFile.read()) except ValueError: self.last_run = 0 runFile.close() else: self.last_run = 0 def writeLastRun(self): runFile = xbmcvfs.File(xbmc.translatePath(utils.data_dir() + "last_run.txt"),'w') runFile.write(str(self.last_run)) runFile.close() self.showNotify(True) def scanRunning(self): #check if any type of scan is currently running if(xbmc.getCondVisibility('Library.IsScanningVideo') or xbmc.getCondVisibility('Library.IsScanningMusic')): return True else: return False def databaseUpdated(self,database): #check if we should clean the library if(utils.getSetting('clean_libraries') == 'true'): #check if should update while playing media if(xbmc.Player().isPlaying() == False or utils.getSetting("run_during_playback") == "true"): if(int(utils.getSetting("clean_timer")) == 0): #check if we should clean music, or video if((utils.getSetting('library_to_clean') == '0' or utils.getSetting('library_to_clean') == '1') and database == 'video'): self.cleanLibrary(database) if((utils.getSetting('library_to_clean') == '2' or utils.getSetting('library_to_clean') == '0') and database == 'music'): self.cleanLibrary(database) #writeLastRun will trigger notifications self.writeLastRun() def _networkUp(self): utils.log("Starting network check") try: response = urllib2.urlopen('http://www.google.com',timeout=1) return True except: pass return False
def createSchedules(self, forceUpdate=False): utils.log("update timers") self.lock = True #lock so the eval portion does not run self.schedules = [] if (utils.getSetting('clean_libraries') == 'true'): #create clean schedule (if needed) if (int(utils.getSetting("clean_timer")) != 0): if (utils.getSetting('library_to_clean') == '0' or utils.getSetting('library_to_clean') == '1'): #video clean schedule starts at 12am by default aSchedule = CronSchedule() aSchedule.name = utils.getString(30048) aSchedule.timer_type = utils.__addon_id__ aSchedule.command = 'video' if (int(utils.getSetting("clean_timer")) == 4): aSchedule.expression = utils.getSetting( "clean_video_cron_expression") else: aSchedule.expression = "0 0 " + aSchedule.cleanLibrarySchedule( int(utils.getSetting("clean_timer"))) aSchedule.next_run = self.calcNextRun( aSchedule.expression, time.time()) self.schedules.append(aSchedule) if (utils.getSetting('library_to_clean') == '2' or utils.getSetting('library_to_clean') == '0'): #music clean schedule starts at 2am by default aSchedule = CronSchedule() aSchedule.name = utils.getString(30049) aSchedule.timer_type = utils.__addon_id__ aSchedule.command = 'music' if (int(utils.getSetting("clean_timer")) == 4): aSchedule.expression = utils.getSetting( "clean_music_cron_expression") else: aSchedule.expression = "0 2 " + aSchedule.cleanLibrarySchedule( int(utils.getSetting("clean_timer"))) aSchedule.next_run = self.calcNextRun( aSchedule.expression, time.time()) self.schedules.append(aSchedule) if (utils.getSetting('update_video') == 'true'): utils.log("Creating timer for Video Library") #create the video schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30012) aSchedule.command = 'UpdateLibrary(video)' aSchedule.expression = self.checkTimer('video') aSchedule.next_run = self.calcNextRun(aSchedule.expression, self.last_run) self.schedules.append(aSchedule) if (utils.getSetting('update_music') == 'true'): utils.log("Creating timer for Music Library") #create the music schedule aSchedule = CronSchedule() aSchedule.name = utils.getString(30013) aSchedule.command = 'UpdateLibrary(music)' aSchedule.expression = self.checkTimer('music') aSchedule.next_run = self.calcNextRun(aSchedule.expression, self.last_run) self.schedules.append(aSchedule) #read in any custom path options customPaths = CustomPathFile() for aJob in customPaths.getSchedules(): utils.log("Creating timer " + aJob.name) aJob.next_run = self.calcNextRun(aJob.expression, self.last_run) self.schedules.append(aJob) #release the lock self.lock = False utils.log("Created " + str(len(self.schedules)) + " schedules", xbmc.LOGDEBUG) #show any notifications self.showNotify(not forceUpdate)