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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3264 - (hide annotations) (download) (as text)
Fri Feb 26 12:24:06 2021 UTC (3 years, 3 months ago) by torben
File MIME type: text/x-python
File size: 15070 byte(s)
1.9.3 fix resume of episodes after 19 matrix api migration

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

  ViewVC Help
Powered by ViewVC 1.1.20