Advertisement
Guest User

Untitled

a guest
Aug 6th, 2013
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.62 KB | None | 0 0
  1. import sys, os, socket, telnetlib, time
  2. import xbmc, xbmcaddon, xbmcgui, xbmcplugin, inhibit_shutdown
  3.  
  4. Addon = xbmcaddon.Addon(id="vdr.powersave")
  5.  
  6.  
  7.  
  8. class Main:
  9.     _base = sys.argv[0]
  10.     _enum_forerun = [1,2,5,10,15,20]
  11.     _enum_overrun = [1,2,5,10,15,20]
  12.     _enum_idle= [5,10,15,20,25,30,40,50,60,90,120,180,240,300,360,420,480,540,600]
  13.     _sleep_interval = 10000
  14.     _poll_interval = 6
  15.     _timers = {}
  16.     _lastWakeup = 0
  17.     _idleTime = 0
  18.     _lastIdleTime = 0
  19.     _realIdleTime = 0
  20.     _isLoggedOn = False
  21.     _lastPlaying = False
  22.     _isPlaying = False
  23.     _lastRecording = False
  24.     _isRecording = False
  25.  
  26.     # main routine
  27.     def __init__(self):
  28.         print "vdr.powersave: Plugin started"
  29.         self.getSettings()
  30.         self.getTimers()
  31.         pollCounter = self._poll_interval
  32.         # main loop
  33.         while (not xbmc.abortRequested):
  34.             # reload timers periodically
  35.             if (pollCounter > self._poll_interval):
  36.                 pollCounter = 0
  37.                 self.getTimers()
  38.             else:
  39.                 pollCounter = pollCounter + 1
  40.                
  41.             # set wakeup
  42.             self.setWakeup()
  43.            
  44.             # time warp calculations demands to have our own idle timers
  45.             self._lastIdleTime = self._idleTime
  46.             self._idleTime = xbmc.getGlobalIdleTime()
  47.             if (self._idleTime > self._lastIdleTime):
  48.                 self._realIdleTime = self._realIdleTime + (self._idleTime - self._lastIdleTime)
  49.             else:
  50.                 self._realIdleTime = self._idleTime
  51.  
  52.             # notice changes in playback
  53.             self._lastPlaying = self._isPlaying
  54.             self._isPlaying = xbmc.Player().isPlaying()
  55.  
  56.             # check netstat        
  57.             def check_netstat():
  58.                     if inhibit_shutdown.check_services():
  59.                             return True
  60.  
  61.                     return False
  62.  
  63.             # now this one is tricky: a playback ended, idle would suggest to powersave, but we set the clock back for overrun.
  64.             # Otherwise xbmc could sleep instantly at the end of a movie
  65.             if (self._lastPlaying  == True) & (self._isPlaying == False) & (self._realIdleTime >= self.settings['vdrps_sleepmode_after']):
  66.                 self._realIdleTime = self.settings['vdrps_sleepmode_after'] - self.settings['vdrps_overrun']
  67.                 #print "vdr.powersave: playback stopped!"
  68.  
  69.             # notice changes in recording
  70.             self._lastRecording = self._isRecording
  71.             self._isRecording = self.getIsRecording()
  72.  
  73.             # same trick, for recording issues - gives time to postprocess
  74.             if (self._lastRecording  == True) & (self._isRecording == False) & (self._realIdleTime >= self.settings['vdrps_sleepmode_after']):
  75.                 self._realIdleTime = self.settings['vdrps_sleepmode_after'] - self.settings['vdrps_overrun']
  76.  
  77.            
  78.            
  79.             #print "vdr.powersave: Mark"
  80.  
  81.             # powersave checks ...
  82.             if (self.settings['vdrps_sleepmode'] > 0) & \
  83.                (self._realIdleTime >= self.settings['vdrps_sleepmode_after']):
  84.                 # sleeping time already?
  85.                 if (self._isPlaying):
  86.                     print "vdr.powersave: powersave postponed - xbmc is playing ..."
  87.                 elif (self._isRecording):
  88.                     print "vdr.powersave: powersave postponed - vdr is recording ..."
  89.                 elif (self.getIsRecordPending()):
  90.                     print "vdr.powersave: powersave postponed - record upcomming ..."
  91.                 elif check_netstat():
  92.                             print "vdr.powersave: powersave postponed - Network activity ..."
  93.                 else:
  94.                     if (self.settings['vdrps_sleepmode'] == 1):
  95.                         #print "vdr.powersave: initiating sleepmode S3 ..."
  96.                         xbmc.executebuiltin('Suspend')
  97.                     elif (self.settings['vdrps_sleepmode'] == 2):
  98.                         #print "vdr.powersave: initiating sleepmode S4 ..."
  99.                         xbmc.executebuiltin('Hibernate')
  100.                     elif (self.settings['vdrps_sleepmode'] == 3):
  101.                         #print "vdr.powersave: initiating powerdown ..."
  102.                         xbmc.executebuiltin('Powerdown')
  103.            
  104.            
  105.             # Disabled due to bugged service abort on logouts
  106.             # are we logged on? (Dialog <> 10029)          
  107.             #self._isLoggedOn = (xbmcgui.getCurrentWindowId()<>10029)
  108.             # check for automatic logout ...
  109.             #if (self.settings['vdrps_autologout'] == "true") & \
  110.                #(self._idleTime > self.settings['vdrps_autologout_after']) & \
  111.                #self._isLoggedOn:
  112.                 ## logging out is safe
  113.                 #xbmc.executebuiltin('System.LogOff')
  114.            
  115.            
  116.             # sleep a little ...
  117.             xbmc.sleep(self._sleep_interval)
  118.         # last second check
  119.         self.getTimers()
  120.         # last second alarm clock
  121.         self.setWakeup()
  122.         print "vdr.powersave: Plugin exited"
  123.        
  124.     # get settings from xbmc
  125.     def getSettings(self):
  126.         print "vdr.powersave: Getting settings ..."
  127.         self.settings = {}
  128.         self.settings['vdrps_host'] = Addon.getSetting('vdrps_host')
  129.         self.settings['vdrps_port'] = int(Addon.getSetting('vdrps_port'))
  130.         self.settings['vdrps_forerun'] = self._enum_forerun[int(Addon.getSetting('vdrps_forerun'))] * 60
  131.         self.settings['vdrps_wakecmd'] = Addon.getSetting('vdrps_wakecmd')
  132.         self.settings['vdrps_overrun'] = self._enum_forerun[int(Addon.getSetting('vdrps_overrun'))] * 60
  133.         # Disabled due to bugged service abort on logouts
  134.         #self.settings['vdrps_autologout'] = Addon.getSetting('vdrps_autologout')
  135.         #self.settings['vdrps_autologout_after'] = self._enum_idle[int(Addon.getSetting('vdrps_autologout_after'))] * 60
  136.         self.settings['vdrps_sleepmode'] = int(Addon.getSetting('vdrps_sleepmode'))
  137.         self.settings['vdrps_sleepmode_after'] = self._enum_idle[int(Addon.getSetting('vdrps_sleepmode_after'))] * 60
  138.         self.settings['vdrps_dailywakeup'] = Addon.getSetting('vdrps_dailywakeup')
  139.         self.settings['vdrps_dailywakeup_time'] = int(Addon.getSetting('vdrps_dailywakeup_time')) * 1800
  140.  
  141.     # get timers from vdr
  142.     def getTimers(self):
  143.         #print "vdr.powersave: Getting timers ..."
  144.         # contact SVDRP and parse resopnse
  145.         raw = self._querySVDRP(self.settings['vdrps_host'], self.settings['vdrps_port'])
  146.         # parse when get a response
  147.         if (raw != None):
  148.             self._parseSVDRP(raw)
  149.  
  150.     # set the alarm clock if necessary
  151.     def setWakeup(self):
  152.         # calculate next wakeup time
  153.         stampWakeup = self.getMostRecentTimer() - self.settings['vdrps_forerun']
  154.         stampNow = int(time.time())
  155.         # some extra calculations for daily wakeing
  156.         if (self.settings['vdrps_dailywakeup'] == "true"):
  157.             # extract date and time only
  158.             tupleNow = time.localtime(stampNow)
  159.             stampTimeOnly = (tupleNow.tm_hour*3600)+(tupleNow.tm_min*60)+tupleNow.tm_sec
  160.             stampDateOnly = time.mktime((tupleNow.tm_year,tupleNow.tm_mon,tupleNow.tm_mday,0,0,0,tupleNow.tm_wday,tupleNow.tm_yday,tupleNow.tm_isdst))
  161.  
  162.             # wake me today, or tomorrow?
  163.             if (self.settings['vdrps_dailywakeup_time'] > stampTimeOnly):
  164.                 stampDailyWakeup = stampDateOnly + self.settings['vdrps_dailywakeup_time']
  165.             else:
  166.                 # add a whole day
  167.                 stampDailyWakeup = stampDateOnly + self.settings['vdrps_dailywakeup_time'] + 86400
  168.  
  169.             # daily wakeup is before next timer, so set the alarm clock to it
  170.             if (stampDailyWakeup<stampWakeup):
  171.                 stampWakeup = stampDailyWakeup
  172.        
  173.         # is it in the future and not already set?
  174.         if (stampWakeup>stampNow) & (stampWakeup <> self._lastWakeup):
  175.             # yes we do have to wakeup
  176.             print "vdr.powersave: Wake up on timestamp %d (%s)" % (stampWakeup, time.asctime(time.localtime(stampWakeup)) )
  177.             # call the alarm script
  178.             os.system("%s %d" % (self.settings['vdrps_wakecmd'],stampWakeup))
  179.             # remember the stamp, not to call alarm script twice with the same value
  180.             self._lastWakeup = stampWakeup
  181.            
  182.     # contact SVDRP service and get raw timers
  183.     def _querySVDRP(self, host, port):
  184.         try:
  185.             tndata = None
  186.             # getting in contact
  187.             tnsession = telnetlib.Telnet(host,port,5)
  188.             try:
  189.                 # sending commands
  190.                 tnsession.write("LSTT\n")
  191.                 tnsession.write("QUIT\n")
  192.                 # getting data
  193.                 tndata = tnsession.read_until("closing connection")
  194.             finally:
  195.                 # clean up our mess, and get back
  196.                 tnsession.close()
  197.                 return tndata
  198.  
  199.         except:
  200.             # made a boo boo
  201.             print "vdr.powersave: cannot get list of timers from %s:%s " % (host, port)
  202.             return None
  203.            
  204.     # this function parses the SVDRP session dump for timers and returns a dictonary with status
  205.     def _parseSVDRP(self, raw):
  206.         # empty result list
  207.         timers = {}
  208.         # loop thru lines
  209.         for line in raw.splitlines():
  210.             # as we know timers getting returned with status 250 (ok)
  211.             if line.startswith("250"):
  212.                 try:
  213.                     # get into the fields
  214.                     fields = line[4:].split(":")
  215.                     # check the timer status (flags 1: enabled, 2, instant record, 4, vps, 8: active)
  216.                     timer_status = fields[0].split(" ")[1]
  217.                     # decode starting time
  218.                     timer_start = int(time.mktime(time.strptime(fields[2]+fields[3], "%Y-%m-%d%H%M")))
  219.                     # fill the timer dictonary
  220.                     if timer_start>0:
  221.                         timers[timer_start] = int(timer_status)
  222.                 except:
  223.                     # some lines may fail
  224.                     print "vdr.powersave: unable to parse line '%s' " % (line)
  225.         self._timers = timers
  226.  
  227.     # returns if any timer is actually recording
  228.     def getIsRecording(self):
  229.         for status in self._timers.values():
  230.             if (status & 8) == 8:
  231.                 return True
  232.         return False;
  233.        
  234.     # returns if a record is upcomming within forerun, or idle time to prevent powersave
  235.     def getIsRecordPending(self):
  236.         # decide which period lasts longer
  237.         if (self.settings['vdrps_forerun'] > self.settings['vdrps_sleepmode_after']):
  238.             delta = self.settings['vdrps_forerun']
  239.         else:
  240.             # odd people may set the recording prerun smaller than idle time
  241.             delta = self.settings['vdrps_sleepmode_after']
  242.         # we need the stamps
  243.         stamps = self._timers.keys()
  244.         stampNow = int(time.time())
  245.         for stamp in stamps:
  246.             if (self._timers[stamp] & 1 == 1) & (stamp-delta < stampNow ):
  247.                 # there is a record upcomming
  248.                 return True
  249.         return False
  250.  
  251.     # this returns the most recent enabled timestamp, or None
  252.     def getMostRecentTimer(self):
  253.         # we need a sorted list of the timestamps
  254.         stamps = self._timers.keys()
  255.         stamps.sort()
  256.         # now search for the first enabled one
  257.         for stamp in stamps:
  258.             if self._timers[stamp] & 1 == 1:
  259.                 return int(stamp)
  260.         return 0;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement