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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3264 - (show annotations) (download) (as text)
Fri Feb 26 12:24:06 2021 UTC (3 years, 2 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
2 # This Python file uses the following encoding: utf-8
3
4 '''
5 Todic plugin for XBMC
6 Version 1.9.3
7 '''
8
9 import sys
10 import os
11
12
13 import xbmc
14 import xbmcaddon
15 import xbmcgui
16 import xbmcvfs
17 import xbmcplugin
18 import urllib
19 import urllib.request
20
21 # import pprint
22
23 from xml.dom.minidom import parseString
24 from time import time
25
26 __addon__ = xbmcaddon.Addon(id='plugin.video.todic')
27 __key__ = __addon__.getSetting('xbmckey').lower()
28 __entrypoint__ = __addon__.getSetting('entrypoint').lower()
29 __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):
116
117 def __init__(self, *args, **kwargs):
118 # xbmc.Player.__init__(selv,*args,**kwargs)
119 xbmc.Player.__init__(self)
120 self.stopped = False
121 self.started = False
122 self.playingPosition = 0.0
123 self.lastReport = 0
124 print( "[TodicPlayer] init")
125
126 def onPlayBackStarted(self):
127 self.started = True
128 print( "[TodicPlayer] : started")
129
130 #When user presses stop, we report back the the position registered in the last call to self.tick()
131 def onPlayBackStopped(self):
132 self.stopped = True
133 print( "[TodicPlayer] : stopped")
134 self.reportPlaytime("stopped")
135
136 def onPlayBackPaused(self):
137 print( "[TodicPlayer] : paused")
138 self.reportPlaytime("paused")
139
140 def onPlayBackResumed(self):
141 print( "[TodicPlayer] : resumed")
142 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):
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
181
182 def getText(nodelist):
183 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
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):
201 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
208
209 # 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 print( "[Todic] Some error during open_url call to ", url)
216
217
218
219 def rootMenu():
220 kodi_ver = xbmc.getInfoLabel('System.BuildVersion')
221 plugin_ver = __addon__.getAddonInfo('version')
222 msgurl = __backend__ + "&action=messages&kodi=" + urllib.parse.quote(kodi_ver) + "&todicplugin=" + urllib.parse.quote(plugin_ver)
223
224 msg = open_url(msgurl)
225 msg = msg.strip()
226
227 if msg != "":
228 print("[Todic] rootMenu Dialog =" + str(msg))
229 dialog = xbmcgui.Dialog()
230 dialog.ok('XBMC Todic', msg)
231
232 buildList(__backend__, "", False) # call default list
233
234 # Adde xtra items to root menu
235 listitem = xbmcgui.ListItem(label="Søg Film ...")
236 listitem.setArt( { 'icon':'DefaultFolder.png', 'thumb':'DefaultFolder.png'} )
237 listitem.setProperty('Fanart_Image', fanartImage)
238
239 u = sys.argv[0] + "?mode=10&name="
240 xbmcplugin.addDirectoryItem(
241 handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=True)
242
243 # add search series
244 listitem = xbmcgui.ListItem(label="Søg Serier ...")
245 listitem.setArt( { 'icon':'DefaultFolder.png', 'thumb':'DefaultFolder.png'} )
246 listitem.setProperty('Fanart_Image', fanartImage)
247
248 u = sys.argv[0] + "?mode=11&name="
249 xbmcplugin.addDirectoryItem(
250 handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=True)
251
252 xbmcplugin.endOfDirectory(int(sys.argv[1]))
253
254
255 def buildList(url, title, endlist=True):
256 print( '[Todic::buildList]:' + str(url) )
257
258 link = open_url(url)
259 doc = parseString(link)
260 ty = doc.getElementsByTagName("meta")[0].getAttribute("type")
261 print( '[Todic]' + str(ty))
262
263 if ty == 'clipList':
264 mode = '50'
265 folder = False
266 else:
267 mode = '1'
268 folder = True
269
270 entries = doc.getElementsByTagName("entry")
271 l = len(entries)
272
273 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
279
280 if playcount == '':
281 playcount = '0'
282 playcount = int(playcount)
283
284 # print "name:" + name
285 # print "url:" + url
286 # print "thumb:" + thumbi
287 listitem = xbmcgui.ListItem(label=name, label2='test')
288 listitem.setArt( {'icon': 'DefaultFolder.png'} )
289 listitem.setProperty('Fanart_Image', fanartImage)
290 listitem.addContextMenuItems([('Refresh', 'Container.Refresh')])
291 listitem.setArt( {'thumb': thumb} )
292
293 if mode == '50':
294 infoLabels = {}
295 infoLabels['title'] = name
296 infoLabels['playcount'] = playcount
297 # 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 listitem.setInfo('video', infoLabels)
300
301 name = name.encode('UTF-8')
302
303 u = sys.argv[0] + "?mode=" + urllib.parse.quote(mode) + "&name=" + urllib.parse.quote(name) + "&url=" + urllib.parse.quote(url)
304 xbmcplugin.addDirectoryItem(
305 handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=folder, totalItems=l)
306
307 if (endlist == True):
308 xbmcplugin.endOfDirectory(int(sys.argv[1]))
309
310
311 def play_video(url, name):
312 description = ""
313 playPosition = 0
314 savedPosition = 0
315 try:
316 param1 = parse_parameter_string(url)
317 clipkey = param1["clipkey"]
318
319 print( "[Todic] ClipKey:" + clipkey)
320 detailurl = __backend__ + "&action=clipdetails&clipkey=" + clipkey
321 print( "[Todic] detailURL = " + detailurl)
322
323 xml = open_url(detailurl)
324
325 clipDetailsDoc = parseString(xml)
326 savedPosition = int( getText(clipDetailsDoc.getElementsByTagName("position")) )
327 description = getText(clipDetailsDoc.getElementsByTagName("description"))
328 except:
329 print( "[Todic] Unexpected error:", sys.exc_info()[0] )
330
331 if (description == None or description == ""):
332 if (savedPosition > 0):
333 dialog = xbmcgui.Dialog()
334 #yes / true -afspil fra position
335 answer = dialog.yesno(heading='Todic', message='Afspil fra sidste position', nolabel='Fra start', yeslabel='Fortsæt')
336 if (answer == True):
337 playPosition = savedPosition
338
339 play_real_video(url, name, playPosition)
340
341 else:
342 d = TodicMovieDialog()
343 d.setDetailsDoc(clipDetailsDoc)
344 d.setName(name)
345 d.setUrl(url)
346 d.setDescription(description)
347
348 d.doModal()
349
350
351 def play_real_video(url, name, position):
352 xml = open_url(url)
353 print( '[Todic] url: ' + str(url) )
354 print( '[Todic] xml: ' + str(xml) )
355 print( '[Todic] pos: ' + str(position) )
356
357 doc = parseString(xml)
358 url = getText(doc.getElementsByTagName("url"))
359
360 subtitleurl = getText(doc.getElementsByTagName("subtitles"))
361
362
363 print( '[Todic] subs: ' + str(subtitleurl) )
364
365 image = xbmc.getInfoImage('ListItem.Thumb')
366 listitem = xbmcgui.ListItem(label=name)
367 listitem.setArt( {'icon': 'DefaultVideo.png', 'thumb':image} )
368 listitem.setInfo(type="Video", infoLabels={"Title": name})
369
370 listitem.setProperty('StartOffset', str(position) )
371
372 if len(subtitleurl) > 0:
373 listitem.setSubtitles([subtitleurl])
374
375 player = TodicPlayer()
376 player.play(str(url), listitem)
377
378
379 #Holder python kørernde indtil at det bliver bedt om at stoppe
380 kodiMonitor = xbmc.Monitor()
381
382
383 while (not kodiMonitor.abortRequested()):
384 player.tick()
385 kodiMonitor.waitForAbort( 1 )
386
387
388
389 def search():
390 search = getUserInput("Todic Søgning")
391
392 if (search != None and search != ""):
393 url = __backend__ + "&action=search&search=" + \
394 urllib.parse.quote(search)
395
396 # print "[Todic] Search start: " + search
397 # print "[Todic] Search url: " + url
398
399 buildList(url, "søgning")
400
401
402 def searchSeries():
403 search = getUserInput("Todic Serie Søgning")
404
405 if (search != None and search != ""):
406 url = __backend__ + "&action=searchseries&search=" + \
407 urllib.parse.quote(search)
408
409 # print "[Todic] Search start: " + search
410 # print "[Todic] Search url: " + url
411
412 buildList(url, "serie søgning")
413
414
415 #=================================== Tool Box =======================================
416 # shows a more userfriendly notification
417 def showMessage(heading, message):
418 print( "[Todic::showMessage] " + str(message) )
419 print( message )
420 duration = 15 * 1000
421 xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s)' %
422 (heading, message, duration))
423
424
425 # raise a keyboard for user input
426 def getUserInput(title="Input", default="", hidden=False):
427 result = None
428
429 # Fix for when this functions is called with default=None
430 if not default:
431 default = ""
432
433 keyboard = xbmc.Keyboard(default, title)
434 keyboard.setHiddenInput(hidden)
435 keyboard.doModal()
436
437 if keyboard.isConfirmed():
438 result = keyboard.getText()
439
440 return result
441
442
443 def get_params():
444 return parse_parameter_string(sys.argv[2])
445
446
447 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
463
464 params = get_params()
465 url = None
466 name = None
467 mode = None
468
469
470 #print params
471
472 try:
473 url = urllib.parse.unquote(params["url"])
474 except:
475 pass
476 try:
477 name = urllib.parse.unquote(params["name"])
478 except:
479 pass
480 try:
481 mode = int(params["mode"])
482 except:
483 pass
484
485 print( "[Todic] url=" + str(url))
486 print( "[Todic] name=" + str(name))
487 print( "[Todic] mode=" + str(mode))
488
489
490 try:
491 open_url("https://todic.dk")
492 except:
493 showMessage("Fejl", "Kunne ikke forbinde til todic.dk")
494 exit()
495
496
497 if url == 'refresh':
498 # xbmc.output("[tvserver] Container.Refresh") #20130418 xbmc.output virker
499 # ikke med XBMC12
500 xbmc.executebuiltin("Container.Refresh")
501
502
503 elif mode == None:
504 # build main menu
505 rootMenu()
506
507 elif mode == 1:
508 # build list of movie starting letters
509 buildList(url, name)
510
511 elif mode == 10:
512 search()
513
514 elif mode == 11:
515 searchSeries()
516
517
518 elif mode == 50:
519 play_video(url, name)

  ViewVC Help
Powered by ViewVC 1.1.20