Advertisement
Guest User

Untitled

a guest
Sep 24th, 2014
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 22.75 KB | None | 0 0
  1. import xbmc
  2. import xbmcgui
  3. import xbmcaddon
  4. import os
  5. import datetime
  6. import time
  7. import _strptime
  8. import threading
  9. import urllib2
  10. import StringIO
  11. import sqlite3
  12. import threading
  13. from sqlite3 import dbapi2 as database
  14. from xml.etree import ElementTree
  15. import xml.etree.ElementTree as ET
  16. from UserDict import DictMixin
  17.  
  18. # two separate flags to kill the AllChannelsThread and the TimerThread
  19. __killthread__ = False
  20. CHANNELS_PER_PAGE = 7
  21.  
  22. # ...
  23.  
  24.  
  25. #get actioncodes from keyboard.xml
  26. ACTION_MOVE_LEFT = 1
  27. ACTION_MOVE_RIGHT = 2
  28. ACTION_MOVE_UP = 3
  29. ACTION_MOVE_DOWN = 4
  30. ACTION_ENTER = 7
  31. ACTION_PREVIOUS_MENU = 10
  32. ACTION_BACKSPACE = 110
  33. ACTION_NUMBER1 = 59
  34. ACTION_NUMBER2 = 60
  35. ACTION_NUMBER3 = 61
  36. ACTION_NUMBER4 = 62
  37. ACTION_NUMBER5 = 63
  38. ACTION_NUMBER6 = 64
  39. ACTION_NUMBER7 = 65
  40. ACTION_NUMBER8 = 66
  41. ACTION_NUMBER9 = 67
  42. ACTION_NUMBER0 = 58
  43.  
  44. def cSetVisible(WiNdOw,iD,V=True): WiNdOw.getControl(iD).setVisible(V)
  45. ADDON = xbmcaddon.Addon(id = 'script.tvguide')
  46.  
  47.  
  48. class OrderedDict(dict, DictMixin):
  49.  
  50.     def __init__(self, *args, **kwds):
  51.         if len(args) > 1:
  52.             raise TypeError('expected at most 1 arguments, got %d' % len(args))
  53.         try:
  54.             self.__end
  55.         except AttributeError:
  56.             self.clear()
  57.         self.update(*args, **kwds)
  58.  
  59.     def clear(self):
  60.         self.__end = end = []
  61.         end += [None, end, end]         # sentinel node for doubly linked list
  62.         self.__map = {}                 # key --> [key, prev, next]
  63.         dict.clear(self)
  64.  
  65.     def __setitem__(self, key, value):
  66.         if key not in self:
  67.             end = self.__end
  68.             curr = end[1]
  69.             curr[2] = end[1] = self.__map[key] = [key, curr, end]
  70.         dict.__setitem__(self, key, value)
  71.  
  72.     def __delitem__(self, key):
  73.         dict.__delitem__(self, key)
  74.         key, prev, next = self.__map.pop(key)
  75.         prev[2] = next
  76.         next[1] = prev
  77.  
  78.     def __iter__(self):
  79.         end = self.__end
  80.         curr = end[2]
  81.         while curr is not end:
  82.             yield curr[0]
  83.             curr = curr[2]
  84.  
  85.     def __reversed__(self):
  86.         end = self.__end
  87.         curr = end[1]
  88.         while curr is not end:
  89.             yield curr[0]
  90.             curr = curr[1]
  91.  
  92.     def popitem(self, last=True):
  93.         if not self:
  94.             raise KeyError('dictionary is empty')
  95.         if last:
  96.             key = reversed(self).next()
  97.         else:
  98.             key = iter(self).next()
  99.         value = self.pop(key)
  100.         return key, value
  101.  
  102.     def __reduce__(self):
  103.         items = [[k, self[k]] for k in self]
  104.         tmp = self.__map, self.__end
  105.         del self.__map, self.__end
  106.         inst_dict = vars(self).copy()
  107.         self.__map, self.__end = tmp
  108.         if inst_dict:
  109.             return (self.__class__, (items,), inst_dict)
  110.         return self.__class__, (items,)
  111.  
  112.     def keys(self):
  113.         return list(self)
  114.  
  115.     setdefault = DictMixin.setdefault
  116.     update = DictMixin.update
  117.     pop = DictMixin.pop
  118.     values = DictMixin.values
  119.     items = DictMixin.items
  120.     iterkeys = DictMixin.iterkeys
  121.     itervalues = DictMixin.itervalues
  122.     iteritems = DictMixin.iteritems
  123.  
  124.     def __repr__(self):
  125.         if not self:
  126.             return '%s()' % (self.__class__.__name__,)
  127.         return '%s(%r)' % (self.__class__.__name__, self.items())
  128.  
  129.     def copy(self):
  130.         return self.__class__(self)
  131.  
  132.     @classmethod
  133.     def fromkeys(cls, iterable, value=None):
  134.         d = cls()
  135.         for key in iterable:
  136.             d[key] = value
  137.         return d
  138.  
  139.     def __eq__(self, other):
  140.         if isinstance(other, OrderedDict):
  141.             if len(self) != len(other):
  142.                 return False
  143.             for p, q in  zip(self.items(), other.items()):
  144.                 if p != q:
  145.                     return False
  146.             return True
  147.         return dict.__eq__(self, other)
  148.  
  149.     def __ne__(self, other):
  150.         return not self == other
  151.  
  152.  
  153.  
  154. class MyClass(xbmcgui.WindowXML):
  155.  
  156.      def __new__(cls):
  157.          return super(MyClass, cls).__new__(cls, 'script-tvguide-mainmenu.xml', ADDON.getAddonInfo('path'))
  158.  
  159.  
  160.      def __init__(self):
  161.          self._timel = []
  162.          self.thread = None
  163.  
  164.  
  165.  
  166.      def onInit(self):
  167.          cSetVisible(self,2,False)
  168.          self.getControl(3).setAnimations([('fade', 'effect=fade start=0 end=100 time=1500')])
  169.          self.getControl(10).setVisible(False)
  170.          cSetVisible(self,11,True)
  171.          allchannels_yellow_BOX = self.getControl(11)
  172.          allchannels_yellow_BOX.setImage("special://home/addons/script.tvguide/resources/skins/Default/media/channels_yellow.png")
  173.          cSetVisible(self,10,False)
  174.          allchannels_blue_BOX = self.getControl(10)
  175.          allchannels_blue_BOX.setImage("special://home/addons/script.tvguide/resources/skins/Default/media/channels_blue.png")
  176.          cSetVisible(self,4200,False)
  177.          loading_gif = self.getControl(4200)
  178.          loading_gif.setImage("special://home/addons/script.tvguide/resources/skins/Default/media/tvguide-loading.gif")
  179.          ADDON = xbmcaddon.Addon(id = 'script.tvguide')
  180.          english_enabled = ADDON.getSetting('english.enabled') == 'true'
  181.          french_enabled = ADDON.getSetting('french.enabled') == 'true'
  182.          self.getString = ADDON.getLocalizedString
  183.          self.getControl(46).setVisible(False)
  184.          self.getControl(46).setLabel(self.getString(30001))
  185.          self.getControl(47).setVisible(False)
  186.          self.getControl(47).setLabel(self.getString(30001))
  187.          self.getControl(54).setVisible(False)
  188.          self.getControl(54).setLabel(self.getString(30005))
  189.          self.getControl(55).setVisible(False)
  190.          self.getControl(55).setLabel(self.getString(30005))
  191.          self.getControl(90).setVisible(False)
  192.          self.getControl(90).setLabel(self.getString(30023))
  193.          cSetVisible(self,4201,False)
  194.          cSetVisible(self,4202,False)
  195.          cSetVisible(self,4204,False)
  196.          cSetVisible(self,4205,False)
  197.          cSetVisible(self,4206,False)
  198.  
  199.  
  200.  
  201.          if english_enabled:
  202.              cSetVisible(self,46,True)
  203.              cSetVisible(self,54,True)
  204.              
  205.  
  206.  
  207.  
  208.          if french_enabled:
  209.              cSetVisible(self,264,True)
  210.  
  211.          
  212.          
  213.      def parseDateTimeToMinutesSinceEpoch(self, p_datetime):
  214.          datetime = time.strptime(p_datetime, "%Y%m%d%H%M%S")
  215.          seconds_epoch = time.mktime(datetime)
  216.          minutes_epoch = int(seconds_epoch / 60)
  217.          return minutes_epoch
  218.  
  219.  
  220.  
  221.      def abortdownload(self):
  222.          global __killthread__
  223.          __killthread__ = True
  224.          if self.thread is not None:
  225.             self.thread.join(3000)
  226.          del self.thread
  227.          self.thread = None
  228.  
  229.  
  230.  
  231.      def All_Channels(self):
  232.          yellow_flag = True
  233.          global __killthread__
  234.          self.getControl(4202).setLabel("0%")
  235.          try:
  236.              # DOWNLOAD THE XML SOURCE HERE
  237.              url = ADDON.getSetting('allchannel.url')
  238.              data = ''
  239.              response = urllib2.urlopen(url)
  240.              meta = response.info()
  241.              file_size = int(meta.getheaders("Content-Length")[0])
  242.              file_size_dl = 0
  243.              block_size = 2048
  244.              while True and not __killthread__:
  245.                  mbuffer = response.read(block_size)
  246.                  if not mbuffer:
  247.                      break
  248.                  file_size_dl += len(mbuffer)
  249.                  data += mbuffer
  250.                  state = int(file_size_dl * 10.0 / file_size)
  251.                  self.getControl(4202).setLabel(str(state) + '%')
  252.              else:
  253.                  if __killthread__:
  254.                      raise AbortDownload('downloading')
  255.              del response
  256.  
  257.              # CREATE DATABASE
  258.              profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', 'source.db'))
  259.              if os.path.exists(profilePath):
  260.                  os.remove(profilePath)
  261.              con = database.connect(profilePath)
  262.              cur = con.cursor()
  263.              cur.execute('CREATE TABLE programs(channel TEXT, title TEXT, start_date TIMESTAMP, stop_date TIMESTAMP, description TEXT)')
  264.              con.commit()
  265.  
  266.              # Get the loaded data
  267.              total_count = data.count('programme')/2
  268.              tv_elem = ElementTree.parse(StringIO.StringIO(data)).getroot()
  269.              cur = con.cursor()
  270.              count = 1
  271.              channels = OrderedDict()
  272.  
  273.              for channel in tv_elem.findall('channel'):
  274.                  channel_name = channel.find('display-name').text
  275.                  for program in channel.findall('programme'):
  276.                      if __killthread__:
  277.                          raise AbortDownload('filling')
  278.                      title = program.find('title').text
  279.                      start_time = program.get("start")
  280.                      stop_time = program.get("stop")
  281.                      cur.execute("INSERT INTO programs(channel, title, start_date, stop_date)" + " VALUES(?, ?, ?, ?)", [channel_name, title, start_time, stop_time])
  282.                      status = 10 + int(float(count)/float(total_count) * 90.0)
  283.                      self.getControl(4202).setLabel(str(status) + '%')
  284.                      xbmc.sleep(10)
  285.                      count += 1
  286.                  con.commit()
  287.              print 'Channels have been successfully stored into the database!'
  288.              self.getControl(4202).setLabel('100%')
  289.              xbmc.sleep(3000)
  290.  
  291.              # Set the date and time row
  292.              current_time = time.time() # now (in seconds)
  293.              half_hour = current_time + 60*30  # now + 30 minutes
  294.              one_hour = current_time + 60*60  # now + 60 minutes
  295.  
  296.              for t in [current_time,half_hour,one_hour]:
  297.                  if (0 <= datetime.datetime.now().minute <= 29):
  298.                      self.getControl(4204).setLabel(time.strftime("%I").lstrip('0') + ':00' + time.strftime("%p"))
  299.                      self.getControl(4205).setLabel(time.strftime("%I").lstrip('0') + ':30' + time.strftime("%p"))
  300.                      self.getControl(4206).setLabel(time.strftime("%I" + ":00%p",time.localtime(t)).lstrip("0"))
  301.                  else:
  302.                      self.getControl(4204).setLabel(time.strftime("%I").lstrip('0') + ':30' + time.strftime("%p"))
  303.                      self.getControl(4205).setLabel(time.strftime("%I" + ":00%p",time.localtime(t)).lstrip("0"))
  304.                      self.getControl(4206).setLabel(time.strftime("%I" + ":30%p",time.localtime(t)).lstrip("0"))
  305.  
  306.  
  307.              #Pull the data from the database
  308.              channelList = list()
  309.              database_path = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', 'source.db'))
  310.  
  311.              if os.path.exists(database_path):
  312.                  #get the channels list
  313.                  cur.execute('SELECT channel FROM programs WHERE channel GROUP BY channel')
  314.  
  315.                  for row in cur:
  316.                      channels = row[0].encode('ascii')
  317.                      channelList.append(channels)
  318.  
  319.                  # set the channels text
  320.                  for index in range(0, CHANNELS_PER_PAGE):
  321.                      channel = channelList[index]
  322.                      channel_index = index
  323.  
  324.                      if channel is not None:
  325.                          self.getControl(4110 + index).setLabel(channel)
  326.  
  327.                      #get the programs list
  328.                      cur = con.cursor()
  329.                      cur.execute('SELECT channel, title, start_date, stop_date FROM programs WHERE channel=?', [channel])
  330.                      programList = list()
  331.                      programs = cur.fetchall()
  332.  
  333.                      start_pos = 390    # indent for first program
  334.                      for ind, row in enumerate(programs):
  335.                          program = row[1].encode('ascii'), str(row[2]), str(row[3])
  336.                          title = row[1].encode('ascii')
  337.                          program_start_date = str(row[2])
  338.                          program_end_date = str(row[3])                      
  339.                          
  340.                          #convert the date formats into minutes
  341.                          minutes_start = self.parseDateTimeToMinutesSinceEpoch(program_start_date)
  342.                          minutes_end = self.parseDateTimeToMinutesSinceEpoch(program_end_date)
  343.                          minutes_length = minutes_end - minutes_start
  344.                        
  345.                          
  346.                          program_index = ind                 # No longer need
  347.                          program_start = (ind * 60)          # No longer need
  348.                          program_length = minutes_length
  349.                          program_notification = program
  350.                          program_minutes = minutes_length    # No longer need
  351.                          program_start_to_end = 370          # No longer need
  352.                          programs_top = 314
  353.                          program_height = 35
  354.                          #pixels_per_minute = 1080 / 200     # No longer need
  355.                          program_gap = 3
  356.                          
  357.                          
  358.                          position_start = start_pos
  359.                          position_top = programs_top + channel_index * (program_height + program_gap)
  360.                          
  361.                          ####################### program_length in minutes
  362.                          
  363.                          if 10 <= program_length < 60:
  364.                             program_width = 350
  365.                          elif 60 <= program_length < 90:
  366.                              program_width = 700
  367.                          elif 90 <= program_length < 105:
  368.                              program_width = 1050
  369.                          elif 105 <= program_length < 120:
  370.                              program_width = 1400
  371.                          elif 120 <= program_length < 150:
  372.                              program_width = 1750
  373.                          elif 150 <= program_length < 180:
  374.                              program_width = 2100
  375.                          elif 180 <= program_length < 210:
  376.                              program_width = 2450
  377.                          elif 210 <= program_length < 240:
  378.                              program_width = 2800
  379.                          elif 240 <= program_length < 270:
  380.                              program_width = 3150
  381.                          elif 270 <= program_length < 300:
  382.                              program_width = 3500
  383.                          elif 300 <= program_length < 330:
  384.                              program_width = 3850
  385.                          elif 330 <= program_length < 360:
  386.                              program_width = 4200
  387.                          elif 360 <= program_length < 390:
  388.                              program_width = 3250
  389.                          elif 390 <= program_length < 420:
  390.                              program_width = 4550
  391.                          elif 420 <= program_length < 450:
  392.                              program_width = 4900
  393.                          elif 450 <= program_length < 480:
  394.                              program_width = 5250
  395.                          
  396.                          start_pos += program_width + 2 * program_gap
  397.                          
  398.                          if program_width > 1:
  399.                          
  400.                              if yellow_flag:
  401.                                  if program_notification:
  402.                                      button_nofocus = 'changelang_yellow.png'
  403.                                      button_focus = 'channels_yellow.png'
  404.                                  else:
  405.                                      button_nofocus = 'changelang_yellow.png'
  406.                                      button_focus = 'channels_yellow.png'
  407.                                  yellow_flag = False
  408.                                  text_color = '0xFF000000'
  409.                                  
  410.                              else:
  411.                                  if program_notification:
  412.                                      button_nofocus = 'channels_bar1.png'
  413.                                      button_focus = 'channels_yellow.png'
  414.                                  else:
  415.                                      button_nofocus = 'channels_bar1.png'
  416.                                      button_focus = 'channels_yellow.png'
  417.                                  text_color = '0xFFFFFFFF'
  418.  
  419.                              if program_width < 1:
  420.                                  program_title = ''
  421.                              else:
  422.                                  program_title = '[B]' + title + '[/B]'
  423.                                  
  424.  
  425.                              program_controls = xbmcgui.ControlButton(
  426.                                  int(position_start),
  427.                                  int(position_top),
  428.                                  int(program_width),
  429.                                  int(program_height),
  430.                                  program_title,
  431.                                  focusTexture = button_focus,
  432.                                  noFocusTexture = button_nofocus,
  433.                                  textColor = text_color,
  434.                              )
  435.                              self.addControl(program_controls)
  436.                      cur.close()
  437.  
  438.  
  439.  
  440.              #Enabled EPG and other controls
  441.              self.getControl(4200).setVisible(False)
  442.              self.getControl(4202).setVisible(False)
  443.              self.getControl(4203).setVisible(False)
  444.              self.getControl(4204).setVisible(True)
  445.              self.getControl(4205).setVisible(True)
  446.              self.getControl(4206).setVisible(True)
  447.  
  448.  
  449.  
  450.          except AbortDownload, e:
  451.              __killthread__ = False
  452.              if e.value == 'downloading':
  453.                  try:
  454.                     if response is not None:
  455.                          self.thread = AllChannelsThread(self.All_Channels)
  456.                          self.thread.start()
  457.                     return
  458.                  except:
  459.                     return
  460.              elif e.value == 'filling':
  461.                  try:
  462.                     if cur is not None:
  463.                         del cur
  464.                     if con is not None:
  465.                         con.close()
  466.                         del con
  467.                     if os.path.exists(profilePath):
  468.                         os.remove(profilePath)
  469.                     return
  470.                  except:
  471.                     return
  472.  
  473.  
  474.      def onAction(self, action):
  475.          tvguide_table = xbmc.getCondVisibility('Control.IsVisible(5000)')
  476.          tvguide_1 = xbmc.getCondVisibility('Control.IsVisible(5001)')
  477.          tvguide_2 = xbmc.getCondVisibility('Control.IsVisible(4201)')
  478.          tvguide_3 = xbmc.getCondVisibility('Control.IsVisible(4001)')
  479.          tvguide_4 = xbmc.getCondVisibility('Control.IsVisible(4002)')
  480.          tvguide_5 = xbmc.getCondVisibility('Control.IsVisible(4003)')
  481.          tvguide_6 = xbmc.getCondVisibility('Control.IsVisible(4004)')
  482.          tvguide_7 = xbmc.getCondVisibility('Control.IsVisible(4011)')
  483.          tvguide_8 = xbmc.getCondVisibility('Control.IsVisible(4012)')
  484.          tvguide_9 = xbmc.getCondVisibility('Control.IsVisible(4013)')
  485.          tvguide_10 = xbmc.getCondVisibility('Control.IsVisible(4014)')
  486.          tvguide_11 = xbmc.getCondVisibility('Control.IsVisible(4020)')
  487.          tvguide_yellow = xbmc.getCondVisibility('Control.IsVisible(3)')
  488.          self.strAction = xbmcgui.ControlLabel(300, 200, 600, 200, '', 'font14', '0xFF00FF00')
  489.          allchannels_yellow = xbmc.getCondVisibility('Control.IsVisible(11)')
  490.          self.addControl(self.strAction)
  491.          ADDON = xbmcaddon.Addon(id = 'script.tvguide')
  492.          english_enabled = ADDON.getSetting('english.enabled') == 'true'
  493.          french_enabled = ADDON.getSetting('french.enabled') == 'true'
  494.          allchannels_enabled = ADDON.getSetting('allchannels.enabled') == 'true'
  495.          main_loading = 4200
  496.          main_loading_progress = 4201
  497.          main_loading_time_left = 4202
  498.  
  499.  
  500.  
  501.          if action == ACTION_PREVIOUS_MENU:
  502.              self.close()
  503.              return
  504.  
  505.  
  506.          if action == ACTION_BACKSPACE:
  507.              if allchannels_enabled:
  508.                  cSetVisible(self,3,True)
  509.                  cSetVisible(self,11,True)                
  510.                  cSetVisible(self,4200,False)
  511.                  cSetVisible(self,4201,False)
  512.                  cSetVisible(self,4202,False)
  513.                  self.getControl(4202).setLabel("")
  514.                  ADDON.setSetting('allchannels.enabled', 'false')
  515.                  self.abortdownload()
  516.                  self.getControl(4202).setLabel('')
  517.                  self.getControl(4203).setVisible(False)
  518.                  self.getControl(4204).setVisible(False)
  519.                  self.getControl(4205).setVisible(False)
  520.                  self.getControl(4206).setVisible(False)
  521.                  cSetVisible(self,46,True)
  522.                  cSetVisible(self,90,False)
  523.                  cSetVisible(self,54,True)
  524.                  profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', 'source.db'))
  525.                  # Deletes the db file if it persists after abort
  526.                  if os.path.exists(profilePath):
  527.                      os.remove(profilePath)
  528.  
  529.  
  530.  
  531.              elif tvguide_yellow == True:
  532.                  self.close()
  533.                  return
  534.  
  535.  
  536.  
  537.          if action == ACTION_ENTER:
  538.              if tvguide_yellow:
  539.                  if allchannels_yellow:
  540.                      cSetVisible(self,3,False)
  541.                      cSetVisible(self,11,False)
  542.                      ADDON.setSetting('allchannels.enabled', 'true')
  543.                      cSetVisible(self,4200,True)
  544.                      cSetVisible(self,4201,True)
  545.                      cSetVisible(self,4202,True)
  546.                      cSetVisible(self,46,False)
  547.                      cSetVisible(self,54,False)
  548.                      cSetVisible(self,90,True)
  549.                      self.getControl(4202).setLabel("0%")
  550.                      self.thread = AllChannelsThread(self.All_Channels)
  551.                      self.thread.start()
  552.                      
  553.                          
  554.  
  555.                        
  556.  
  557.  
  558. class AllChannelsThread(threading.Thread):
  559.     # This is needed for proper threading. The other method continued to block on the call.
  560.     def __init__(self, xtarget):
  561.         threading.Thread.__init__(self, name='all_channels_thread')
  562.         self.xtarget = xtarget
  563.  
  564.     def start(self):
  565.         threading.Thread.start(self)
  566.  
  567.     def run(self):
  568.         self.xtarget()
  569.  
  570.     def stop(self):
  571.         self.join(2000)
  572.  
  573. class AbortDownload(Exception):
  574.  
  575.     def __init__(self, value):
  576.         self.value = value
  577.  
  578.     def __str__(self):
  579.         return repr(self.value)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement