/[projects]/misc/xbmc/plugin.video.todic/default.py
ViewVC logotype

Diff of /misc/xbmc/plugin.video.todic/default.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1678 by torben, Mon Jan 23 17:31:45 2012 UTC revision 3261 by torben, Fri Feb 19 21:39:29 2021 UTC
# Line 3  Line 3 
3    
4  '''  '''
5      Todic plugin for XBMC      Todic plugin for XBMC
6      Version 0.0.2      Version 1.9.0
7  '''  '''
8    
9  import sys  import sys
 import cgi as urlparse  
10  import os  import os
11    
12    
13  import xbmc  import xbmc
14  import xbmcaddon  import xbmcaddon
15  import xbmcgui  import xbmcgui
16    import xbmcvfs
17  import xbmcplugin  import xbmcplugin
18  import urllib  import urllib
19  import urllib2  import urllib.request
20    
21    # import pprint
22    
23  from xml.dom.minidom import parseString  from xml.dom.minidom import parseString
24    from time import time
25    
26  __addon__ = xbmcaddon.Addon(id='plugin.video.todic')  __addon__ = xbmcaddon.Addon(id='plugin.video.todic')
27  __key__ = __addon__.getSetting('xbmckey').lower()  __key__ = __addon__.getSetting('xbmckey').lower()
28  __backend__ = "http://todic.dk/xbmc.php?xbmckey=" + __key__  __entrypoint__ = __addon__.getSetting('entrypoint').lower()
29  fanartImage = os.path.join(__addon__.getAddonInfo('path'), 'fanart.jpg')  __backend__ = "https://todic.dk/xbmc.php?xbmckey=" + __key__
30    
31    
32    if __entrypoint__ == "alternative":
33        __backend__ = "https://alt.todic.dk/xbmc.php?xbmckey=" + __key__
34    
35    if __entrypoint__ == "testing":
36        __backend__ = "https://todic.dk/xbmc-beta.php?xbmckey=" + __key__
37    
38    print( "[Todic] entrypoint: " + __entrypoint__ )
39    print( "[Todic] backend: " + __backend__ )
40    print( "[Todic] version: " + __addon__.getAddonInfo('version') )
41    
42    fanartImage = os.path.join(__addon__.getAddonInfo('path'), 'movie_bg_blur.jpg')
43    datapath = xbmcvfs.translatePath(
44        'special://profile/addon_data/plugin.video.todic/')
45    
46    ADDON_PATH = __addon__.getAddonInfo('path')
47    SkinMasterPath = os.path.join(ADDON_PATH, 'skins') + '/'
48    MySkinPath = (os.path.join(SkinMasterPath, '720p')) + '/'
49    MySkin = 'main.xml'
50    
51    
52    class TodicMovieDialog(xbmcgui.WindowXMLDialog):
53    
54        def __new__(cls):
55            return super(TodicMovieDialog, cls).__new__(cls, "main.xml", ADDON_PATH)
56    
57        def __init__(self):
58            super(TodicMovieDialog, self).__init__()
59            self.position = 0
60    
61        def onClick(self, controlId):
62            print( "[Todic] MovieDialog OnClick: " + str(controlId) )
63    
64            if (controlId == 50):
65                self.close()
66                play_real_video(self.url, self.name, 0)
67    
68            if (controlId == 51):
69                self.close()
70                play_real_video(self.url, self.name, self.position)
71    
72            if (controlId == 98):
73                self.close()
74    
75        def onInit(self):
76    
77            print( "[Todic] MovieDialog onInit" )
78            self.getControl(1).setLabel(self.name)
79            self.getControl(2).setLabel(self.moviegroups)
80            self.getControl(3).setLabel(self.description)
81            self.getControl(10).setLabel(self.playlength)
82            self.getControl(11).setLabel(self.codecdetails)
83    
84            if (self.position > 0):
85                self.getControl(51).setVisible(True)
86                self.getControl(50).setPosition(100, 570)
87                self.getControl(51).setPosition(450, 570)
88                self.getControl(50).controlLeft( self.getControl(51) )
89                self.getControl(50).controlRight( self.getControl(51) )
90            else:
91                self.getControl(51).setVisible(False)
92    
93            #orig_img_width = self.getControl(40).getWidth()
94            #self.starwidth = (float(self.imdbrating) / 10.0) * orig_img_width
95            #self.getControl(40).setWidth(int(self.starwidth))
96    
97        def setDetailsDoc(self, detailsDoc):
98            print( "[Todic] MovieDialog setDetailsDoc:")
99            self.imdbrating = getText(detailsDoc.getElementsByTagName("imdbrating"))
100            self.moviegroups = getText(detailsDoc.getElementsByTagName("moviegroups"))
101            self.playlength = getText(detailsDoc.getElementsByTagName("playlength"))
102            self.codecdetails = getText(detailsDoc.getElementsByTagName("codecdetails"))
103            self.position = int( getText(detailsDoc.getElementsByTagName("position")) )
104    
105        def setUrl(self, url):
106            self.url = url
107    
108        def setName(self, name):
109            self.name = name
110    
111        def setDescription(self, description):
112            self.description = description
113    
114    
115  class TodicPlayer(xbmc.Player):  class TodicPlayer(xbmc.Player):
116          def __init__(self, *args, **kwargs):  
117                  #xbmc.Player.__init__(selv,*args,**kwargs)      def __init__(self, *args, **kwargs):
118                  xbmc.Player.__init__(self, xbmc.PLAYER_CORE_MPLAYER )          # xbmc.Player.__init__(selv,*args,**kwargs)
119                  self.stopped = False          xbmc.Player.__init__(self)
120                  self.started = False          self.stopped = False
121                  print "[TodicPlayer] init"          self.started = False
122            self.playingPosition = 0.0
123  #       @catchall                self.lastReport = 0
124          def onPlayBackStarted(self):          print( "[TodicPlayer] init")
125                  self.started = True  
126                  print "[TodicPlayer] : started"      def onPlayBackStarted(self):
127  #               super.onPlayBackStarted()          self.started = True
128            print( "[TodicPlayer] : started")
129          def onPlayBackStopped(self):  
130                  self.stopped = True      #When user presses stop, we report back the the position registered in the last call to self.tick()
131                  print "[TodicPlayer] : stopped"      def onPlayBackStopped(self):
132            self.stopped = True
133          def onPlayBackEnded(self):          print( "[TodicPlayer] : stopped")
134                  self.stopped = True          self.reportPlaytime("stopped")
135                  print "[TodicPlayer] : ended"  
136        def onPlayBackPaused(self):
137          def callbackLoop(self):          print( "[TodicPlayer] : paused")
138                  print "[Todic] startLoop"          self.reportPlaytime("paused")
139                  while (self.stopped == False):  
140                          if (self.started == True ):      def onPlayBackResumed(self):
141                                  print "[todic] " + str(self.getTime())          print( "[TodicPlayer] : resumed")
142                          xbmc.sleep(5000)          self.reportPlaytime("resumed")
143                            
144    
145        def onPlayBackEnded(self):
146            self.stopped = True
147            print( "[TodicPlayer] : ended")
148            self.reportPlaytime("ended")
149    
150        def tick(self):
151            #print( "[Todic] Tick: " + str( self.isPlaying() ) )
152            if ( self.isPlaying() ):
153                tmpTime = self.getTime()
154    
155                #only report time if it has changed in the mean time
156                if tmpTime != self.playingPosition:
157                    self.playingPosition = tmpTime
158                    now = time()
159                    #print( "[Todic] tick " + str(now) + " " + str(self.lastReport) + " : " +str(now - self.lastReport) )
160                    if ( (now - self.lastReport) > 60.0):
161                        self.lastReport = now
162                        self.reportPlaytime("playing")
163    
164        def reportPlaytime(self, subaction):
165            if (self.playingPosition > 60):
166                url = __backend__ + "&action=playbacktime&subaction=" + subaction + "&time=" + str( self.playingPosition )
167                print( "[Todic] reportPlaytime:" + url)
168                open_url_safe(url)
169    
170    
171    
172  def getText2(nodelist):  def getText2(nodelist):
173          rc = []      rc = []
174          for node in nodelist:      for node in nodelist:
175                  if node.nodeType == node.TEXT_NODE:          if node.nodeType == node.TEXT_NODE:
176                          rc.append(node.data)              rc.append(node.data)
177                  else:          else:
178                          rc.append( getText(node.childNodes) )              rc.append(getText(node.childNodes))
179          return ''.join(rc)      return ''.join(rc)
180    
181    
182  def getText(nodelist):  def getText(nodelist):
183          if nodelist.length == 0:      if nodelist.length == 0:
184                  return ''          return ''
185          else:      else:
186                  if nodelist[0].childNodes.length == 0:          if nodelist[0].childNodes.length == 0:
187                          return ''              return ''
188                  else:          else:
189                          return nodelist[0].childNodes[0].nodeValue              return nodelist[0].childNodes[0].nodeValue
190    
191    
192    
193    def SaveFile(path, data):
194        file = open(path, 'w')
195        file.write(data)
196        file.close()
197    
198    
199    
200  def open_url(url):  def open_url(url):
201          req = urllib2.Request(url)      with urllib.request.urlopen(url) as response:
202          content = urllib2.urlopen(req)          data = response.read()
203          data = content.read()          return data
204          content.close()  
205          return data  
206    # wraps open url in a catch-all exception handler
207    # usefull for periodic back-reporting that should not interrupt the program flow
208    def open_url_safe(url):
209        try:
210            return open_url(url)
211        except:
212            print( "[Todic] Some error during open_url call to ", url)
213    
214    
215    
216  def rootMenu():  def rootMenu():
217        kodi_ver = xbmc.getInfoLabel('System.BuildVersion')
218        plugin_ver = __addon__.getAddonInfo('version')
219        msgurl = __backend__ + "&action=messages&kodi=" + urllib.parse.quote(kodi_ver) + "&todicplugin=" + urllib.parse.quote(plugin_ver)
220    
221          buildList(__backend__, "", False) # call default list      msg = open_url(msgurl)
222        msg = msg.strip()
223    
224          # Adde xtra items to root menu      if msg != "":
225          listitem = xbmcgui.ListItem(label = "Søg film ...", iconImage = 'DefaultFolder.png', thumbnailImage = 'DefaultFolder.png')          dialog = xbmcgui.Dialog()
226          listitem.setProperty('Fanart_Image', fanartImage)          dialog.ok('XBMC Todic', msg)
227    
228          u = sys.argv[0] + "?mode=10&name="      buildList(__backend__, "", False)  # call default list
         ok = xbmcplugin.addDirectoryItem(handle = int(sys.argv[1]), url = u, listitem = listitem, isFolder = True)  
229    
230          xbmcplugin.endOfDirectory(int(sys.argv[1]))      # Adde xtra items to root menu
231        listitem = xbmcgui.ListItem(label="Søg Film ...")
232        listitem.setArt( { 'icon':'DefaultFolder.png', 'thumb':'DefaultFolder.png'} )
233        listitem.setProperty('Fanart_Image', fanartImage)
234    
235        u = sys.argv[0] + "?mode=10&name="
236        xbmcplugin.addDirectoryItem(
237            handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=True)
238    
239  def buildList(url,title, endlist=True):      # add search series
240          print '[TODIC]:'+str(url)              listitem = xbmcgui.ListItem(label="Søg Serier ...")
241        listitem.setArt( { 'icon':'DefaultFolder.png', 'thumb':'DefaultFolder.png'} )
242        listitem.setProperty('Fanart_Image', fanartImage)
243    
244          link = open_url(url)      u = sys.argv[0] + "?mode=11&name="
245          doc = parseString(link)      xbmcplugin.addDirectoryItem(
246          ty = doc.getElementsByTagName("meta")[0].getAttribute("type")          handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=True)
         print '[TODIC]'+str(ty)  
247    
248          if ty == 'clipList':      xbmcplugin.endOfDirectory(int(sys.argv[1]))
                 mode = '50'  
                 folder = False  
         else:  
                 mode = '1'  
                 folder = True  
249    
         entries = doc.getElementsByTagName("entry")  
         l=len(entries)  
         description = ''  
         for entry in entries:  
                 name =  getText( entry.getElementsByTagName("title") )  
                 url =  getText( entry.getElementsByTagName("url") )  
                 thumb = getText( entry.getElementsByTagName("cover") )  
                 description = getText( entry.getElementsByTagName("description") )  
250    
251                  name = name.encode('latin-1')  def buildList(url, title, endlist=True):
252                  description = description.encode('latin-1')      print( '[Todic::buildList]:' + str(url) )
253    
254  ##              print "name:" + name      link = open_url(url)
255  #               print "url:" + url      doc = parseString(link)
256  #               print "thumb:" + thumb      ty = doc.getElementsByTagName("meta")[0].getAttribute("type")
257  #               print "description:" + description      print( '[Todic]' + str(ty))
258    
259        if ty == 'clipList':
260            mode = '50'
261            folder = False
262        else:
263            mode = '1'
264            folder = True
265    
266                  listitem = xbmcgui.ListItem(label = name, label2='test', iconImage = 'DefaultFolder.png', thumbnailImage = thumb)      entries = doc.getElementsByTagName("entry")
267                  listitem.setProperty('Fanart_Image', fanartImage)      l = len(entries)
                 if mode == '50':  
                         infoLabels = {}  
                         infoLabels['title'] = name  
                         infoLabels['plot'] = description          
                         listitem.setInfo('video', infoLabels)  
268    
269                  u = sys.argv[0] + "?mode=" + urllib.quote(mode) + "&name=" + urllib.quote(name) + "&url=" + urllib.quote(url)      for entry in entries:
270                  ok = xbmcplugin.addDirectoryItem(handle = int(sys.argv[1]), url = u, listitem = listitem, isFolder = folder, totalItems = l)          name = getText(entry.getElementsByTagName("title"))
271            url = getText(entry.getElementsByTagName("url"))
272            thumb = getText(entry.getElementsByTagName("cover"))
273            playcount = getText(entry.getElementsByTagName("playcount"))
274    
         if (endlist == True):    
                 xbmcplugin.endOfDirectory(int(sys.argv[1]))  
275    
276            if playcount == '':
277                playcount = '0'
278            playcount = int(playcount)
279    
280    # print "name:" + name
281    #               print "url:" + url
282    #               print "thumb:" + thumbi
283            listitem = xbmcgui.ListItem(label=name, label2='test')
284            listitem.setArt( {'icon': 'DefaultFolder.png'} )
285            listitem.setProperty('Fanart_Image', fanartImage)
286            listitem.addContextMenuItems([('Refresh', 'Container.Refresh')])
287            listitem.setArt( {'thumb': thumb} )
288    
289            if mode == '50':
290                infoLabels = {}
291                infoLabels['title'] = name
292                infoLabels['playcount'] = playcount
293    #            if playcount > 0:
294    #                listitem.setArt( {'thumb': thumb} ) #not pretty - but at least we can show a different icon for unwatched/watched in kodi18  
295                listitem.setInfo('video', infoLabels)
296    
297            name = name.encode('UTF-8')
298    
299            u = sys.argv[0] + "?mode=" + urllib.parse.quote(mode) + "&name=" + urllib.parse.quote(name) + "&url=" + urllib.parse.quote(url)
300            xbmcplugin.addDirectoryItem(
301                handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=folder, totalItems=l)
302    
303        if (endlist == True):
304            xbmcplugin.endOfDirectory(int(sys.argv[1]))
305    
306    
307  def play_video(url, name):  def play_video(url, name):
308          xml = open_url(url)      description = ""
309        playPosition = 0
310        savedPosition = 0
311        try:
312            param1 = parse_parameter_string(url)
313            clipkey = param1["clipkey"]
314    
315            print( "[Todic] ClipKey:" + clipkey)
316            detailurl = __backend__ + "&action=clipdetails&clipkey=" + clipkey
317            print( "[Todic] detailURL = " + detailurl)
318    
319            xml = open_url(detailurl)
320    
321            clipDetailsDoc = parseString(xml)
322            savedPosition = int( getText(clipDetailsDoc.getElementsByTagName("position")) )
323            description = getText(clipDetailsDoc.getElementsByTagName("description"))
324        except:
325            print( "[Todic] Unexpected error:", sys.exc_info()[0] )
326    
327        if (description == None or description == ""):
328            if (savedPosition > 0):
329                dialog = xbmcgui.Dialog()
330                #yes / true -afspil fra position
331                answer = dialog.yesno(heading='Todic', line1='Afspil fra sidste position', nolabel='Fra start', yeslabel='Fortsæt')
332                if (answer == True):
333                    playPosition = savedPosition
334            
335            play_real_video(url, name, playPosition)
336    
337        else:
338            d = TodicMovieDialog()
339            d.setDetailsDoc(clipDetailsDoc)
340            d.setName(name)
341            d.setUrl(url)
342            d.setDescription(description)
343    
344            d.doModal()
345    
346    
347    def play_real_video(url, name, position):
348        xml = open_url(url)
349        print( '[Todic] url: ' + str(url) )
350        print( '[Todic] xml: ' + str(xml) )
351        print( '[Todic] pos: ' + str(position) )
352    
353        doc = parseString(xml)
354        url = getText(doc.getElementsByTagName("url"))
355    
356        subtitleurl = getText(doc.getElementsByTagName("subtitles"))
357    
358    
359        print( '[Todic] subs: ' + str(subtitleurl) )
360    
361        image = xbmc.getInfoImage('ListItem.Thumb')
362        listitem = xbmcgui.ListItem(label=name)
363        listitem.setArt( {'icon': 'DefaultVideo.png', 'thumb':image} )
364        listitem.setInfo(type="Video", infoLabels={"Title": name})
365    
366        listitem.setProperty('StartOffset', str(position) )
367    
368        if len(subtitleurl) > 0:
369            listitem.setSubtitles([subtitleurl])
370    
371        player = TodicPlayer()
372        player.play(str(url), listitem)
373    
374    
375        #Holder python kørernde indtil at det bliver bedt om at stoppe
376        kodiMonitor = xbmc.Monitor()
377        
378        
379        while (not kodiMonitor.abortRequested()):
380            player.tick()
381            kodiMonitor.waitForAbort( 1 )
382    
         doc = parseString(xml)  
         url = getText( doc.getElementsByTagName("url") )  
383    
         print '[TODIC]:'+str(url)  
         image = xbmc.getInfoImage( 'ListItem.Thumb' )  
         listitem = xbmcgui.ListItem(label = name , iconImage = 'DefaultVideo.png', thumbnailImage = image)  
         listitem.setInfo( type = "Video", infoLabels={ "Title": name } )  
   
         player = TodicPlayer(xbmc.PLAYER_CORE_AUTO)  
         player.play(str(url), listitem)  
 #       player.callbackLoop()  
384    
385    def search():
386        search = getUserInput("Todic Søgning")
387    
388        if (search != None and search != ""):
389            url = __backend__ + "&action=search&search=" + \
390                urllib.parse.quote(search)
391    
392  def search():          # print "[Todic] Search start: " + search
393          search = getUserInput("Todic Søgning")          # print "[Todic] Search url: " + url
394    
395          if (search != None and search != ""):          buildList(url, "søgning")
                 url = __backend__ + "&action=search&search=" + urllib.quote_plus(search)  
396    
                 #print "[TODIC] Search start: " + search  
                 #print "[TODIC] Search url: " + url  
397    
398                  buildList(url, "søgning")  def searchSeries():
399        search = getUserInput("Todic Serie Søgning")
400    
401                if (search != None and search != ""):
402            url = __backend__ + "&action=searchseries&search=" + \
403                urllib.parse.quote(search)
404    
405            # print "[Todic] Search start: " + search
406            # print "[Todic] Search url: " + url
407    
408                            buildList(url, "serie søgning")
409  #=================================== Tool Box =======================================  
410    
411    #=================================== Tool Box =======================================
412  # shows a more userfriendly notification  # shows a more userfriendly notification
413  def showMessage(heading, message):  def showMessage(heading, message):
414          duration = 15*1000      print( "[Todic::showMessage] " + message)
415          xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s)' % ( heading, message, duration) )      print( message )
416        duration = 15 * 1000
417        xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s)' %
418                            (heading, message, duration))
419    
420    
421  # raise a keyboard for user input  # raise a keyboard for user input
422  def getUserInput(title = "Input", default="", hidden=False):  def getUserInput(title="Input", default="", hidden=False):
423          result = None      result = None
424    
425        # Fix for when this functions is called with default=None
426        if not default:
427            default = ""
428    
429        keyboard = xbmc.Keyboard(default, title)
430        keyboard.setHiddenInput(hidden)
431        keyboard.doModal()
432    
433          # Fix for when this functions is called with default=None      if keyboard.isConfirmed():
434          if not default:          result = keyboard.getText()
435                  default = ""  
436                                return result
         keyboard = xbmc.Keyboard(default, title)  
         keyboard.setHiddenInput(hidden)  
         keyboard.doModal()  
                   
         if keyboard.isConfirmed():  
                 result = keyboard.getText()  
                   
         return result  
437    
438    
439  def get_params():  def get_params():
440          param=[]      return parse_parameter_string(sys.argv[2])
441          paramstring=sys.argv[2]  
442          if len(paramstring)>=2:  
443                  params=sys.argv[2]  def parse_parameter_string(paramstring):
444                  cleanedparams=params.replace('?','')      param = []
445                  if (params[len(params)-1]=='/'):      if len(paramstring) >= 2:
446                          params=params[0:len(params)-2]          params = paramstring
447                  pairsofparams=cleanedparams.split('&')          cleanedparams = params.replace('?', '')
448                  param={}          if (params[len(params) - 1] == '/'):
449                  for i in range(len(pairsofparams)):              params = params[0:len(params) - 2]
450                          splitparams={}          pairsofparams = cleanedparams.split('&')
451                          splitparams=pairsofparams[i].split('=')          param = {}
452                          if (len(splitparams))==2:          for i in range(len(pairsofparams)):
453                                  param[splitparams[0]]=splitparams[1]                                                  splitparams = {}
454          return param              splitparams = pairsofparams[i].split('=')
455                if (len(splitparams)) == 2:
456                    param[splitparams[0]] = splitparams[1]
457        return param
458    
 params = get_params()  
 url = None  
 name = None  
 mode = None  
459    
460  params = get_params()  params = get_params()
461  url = None  url = None
462  name = None  name = None
463  mode = None  mode = None
464    
465    
466    #print params
467    
468  try:  try:
469          url = urllib.unquote_plus(params["url"])      url = urllib.parse.unquote(params["url"])
470  except:  except:
471          pass      pass
472  try:  try:
473          name = urllib.unquote_plus(params["name"])      name = urllib.parse.unquote(params["name"])
474  except:  except:
475          pass      pass
476  try:  try:
477          mode = int(params["mode"])      mode = int(params["mode"])
478  except:  except:
479          pass      pass
480    
481    
 if mode == None:  
         #build main menu  
         rootMenu()  
         
 elif mode == 1:  
         #build list of movie starting letters  
         buildList(url, name)  
482    
483  elif mode == 10:  try:
484          search()      open_url("https://todic.dk")
485            except:
486        showMessage("Fejl", "Kunne ikke forbinde til todic.dk")
487        exit()
488    
 elif mode == 50:  
         play_video(url, name)  
489    
490    if url == 'refresh':
491        # xbmc.output("[tvserver] Container.Refresh") #20130418 xbmc.output virker
492        # ikke med XBMC12
493        xbmc.executebuiltin("Container.Refresh")
494    
495    
496    elif mode == None:
497        # build main menu
498        rootMenu()
499    
500    elif mode == 1:
501        # build list of movie starting letters
502        buildList(url, name)
503    
504    elif mode == 10:
505        search()
506    
507    elif mode == 11:
508        searchSeries()
509    
510    
511    elif mode == 50:
512        play_video(url, name)

Legend:
Removed from v.1678  
changed lines
  Added in v.3261

  ViewVC Help
Powered by ViewVC 1.1.20