psike

LazyTV-service.py

May 2nd, 2014
227
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. # Copyright (C) 2013 KodeKarnage
  5. #
  6. # This Program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2, or (at your option)
  9. # any later version.
  10. #
  11. # This Program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with XBMC; see the file COPYING. If not, write to
  18. # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19. # http://www.gnu.org/copyleft/gpl.html
  20.  
  21. '''
  22. #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  23. #@@@@@@@@@@
  24. #@@@@@@@@@@ - create and maintain smart playlist
  25. #@@@@@@@@@@ - insert playlist check on Playstarted to help suppress next ep notify
  26. #@@@@@@@@@@
  27. #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'''
  28.  
  29.  
  30. import xbmc
  31. import xbmcgui
  32. import xbmcaddon
  33. import os
  34. import time
  35. import datetime
  36. import ast
  37. import json
  38. import re
  39. import random
  40. import sys
  41.  
  42. # This is a throwaway variable to deal with a python bug
  43. try:
  44. throwaway = datetime.datetime.strptime('20110101','%Y%m%d')
  45. except:
  46. pass
  47.  
  48. __addon__ = xbmcaddon.Addon()
  49. __addonid__ = __addon__.getAddonInfo('id')
  50. __addonversion__ = tuple([int(x) for x in __addon__.getAddonInfo('version').split('.')])
  51. __scriptPath__ = __addon__.getAddonInfo('path')
  52. __profile__ = xbmc.translatePath(__addon__.getAddonInfo('profile'))
  53. __setting__ = __addon__.getSetting
  54. lang = __addon__.getLocalizedString
  55. videoplaylistlocation = xbmc.translatePath('special://profile/playlists/video/')
  56. start_time = time.time()
  57. base_time = time.time()
  58. WINDOW = xbmcgui.Window(10000)
  59. DIALOG = xbmcgui.Dialog()
  60.  
  61. WINDOW.setProperty("LazyTV.Version", str(__addonversion__))
  62. WINDOW.setProperty("LazyTV.ServicePath", str(__scriptPath__))
  63. WINDOW.setProperty('LazyTV_service_running', 'starting')
  64.  
  65. promptduration = int(__setting__('promptduration'))
  66. promptdefaultaction = int(__setting__('promptdefaultaction'))
  67.  
  68. keep_logs = True if __setting__('logging') == 'true' else False
  69. playlist_notifications = True if __setting__("notify") == 'true' else False
  70. resume_partials = True if __setting__('resume_partials') == 'true' else False
  71. nextprompt = True if __setting__('nextprompt') == 'true' else False
  72. prevcheck = True if __setting__('prevcheck') == 'true' else False
  73. moviemid = True if __setting__('moviemid') == 'true' else False
  74. first_run = True if __setting__('first_run') == 'true' else False
  75. maintainsmartplaylist = True if __setting__('maintainsmartplaylist') == 'true' else False
  76.  
  77. def log(message, label = '', reset = False):
  78. if keep_logs:
  79. global start_time
  80. global base_time
  81. new_time = time.time()
  82. gap_time = "%5f" % (new_time - start_time)
  83. start_time = new_time
  84. total_gap = "%5f" % (new_time - base_time)
  85. logmsg = '%s : %s :: %s ::: %s - %s ' % (__addonid__, total_gap, gap_time, label, message)
  86. xbmc.log(msg = logmsg)
  87. base_time = start_time if reset else base_time
  88.  
  89.  
  90. # get the current version of XBMC
  91. versstr = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["version", "name"]}, "id": 1 }')
  92. vers = ast.literal_eval(versstr)
  93. if 'result' in vers and 'version' in vers['result'] and (int(vers['result']['version']['major']) > 12 or int(vers['result']['version']['major']) == 12 and int(vers['result']['version']['minor']) > 8):
  94. __release__ = "Gotham"
  95. else:
  96. __release__ = "Frodo"
  97.  
  98. whats_playing = {"jsonrpc": "2.0","method": "Player.GetItem","params": {"properties": ["showtitle","tvshowid","episode", "season", "playcount", "resume"],"playerid": 1},"id": "1"}
  99. now_playing_details = {"jsonrpc": "2.0","method": "VideoLibrary.GetEpisodeDetails","params": {"properties": ["playcount", "tvshowid"],"episodeid": "1"},"id": "1"}
  100. ep_to_show_query = {"jsonrpc": "2.0","method": "VideoLibrary.GetEpisodeDetails","params": {"properties": ["lastplayed","tvshowid"],"episodeid": "1"},"id": "1"}
  101. prompt_query = {"jsonrpc": "2.0","method": "VideoLibrary.GetEpisodeDetails","params": {"properties": ["season","episode","showtitle","tvshowid"],"episodeid": "1"},"id": "1"}
  102. show_request = {"jsonrpc": "2.0","method": "VideoLibrary.GetTVShows","params": {"filter": {"field": "playcount","operator": "is","value": "0"},"properties": ["genre","title","playcount","mpaa","watchedepisodes","episode","thumbnail"]},"id": "1"}
  103. show_request_all = {"jsonrpc": "2.0","method": "VideoLibrary.GetTVShows","params": {"properties": ["title"]},"id": "1"}
  104. show_request_lw = {"jsonrpc": "2.0","method": "VideoLibrary.GetTVShows","params": {"filter": {"field": "playcount", "operator": "is", "value": "0" },"properties": ["lastplayed"], "sort":{"order": "descending", "method":"lastplayed"} },"id": "1" }
  105. eps_query = {"jsonrpc": "2.0","method": "VideoLibrary.GetEpisodes","params": {"properties": ["season","episode","runtime","resume","playcount","tvshowid","lastplayed","file"],"tvshowid": "1"},"id": "1"}
  106. ep_details_query = {"jsonrpc": "2.0","method": "VideoLibrary.GetEpisodeDetails","params": {"properties": ["title","playcount","plot","season","episode","showtitle","file","lastplayed","rating","resume","art","streamdetails","firstaired","runtime","tvshowid"],"episodeid": 1},"id": "1"}
  107. seek = {"jsonrpc": "2.0","id": 1, "method": "Player.Seek","params": {"playerid": 1, "value": 0 }}
  108. plf = {"jsonrpc": "2.0","id": 1, "method": "Files.GetDirectory", "params": {"directory": "special://profile/playlists/video/", "media": "video"}}
  109. add_this_ep = {'jsonrpc': '2.0','id': 1, "method": 'Playlist.Add', "params": {'item' : {'episodeid' : 'placeholder' }, 'playlistid' : 1}}
  110.  
  111. log('Running: ' + str(__release__))
  112.  
  113.  
  114. def json_query(query, ret):
  115. try:
  116. xbmc_request = json.dumps(query)
  117. result = xbmc.executeJSONRPC(xbmc_request)
  118. result = unicode(result, 'utf-8', errors='ignore')
  119. if ret:
  120. return json.loads(result)['result']
  121.  
  122. else:
  123. return json.loads(result)
  124. except:
  125. xbmc_request = json.dumps(query)
  126. result = xbmc.executeJSONRPC(xbmc_request)
  127. result = unicode(result, 'utf-8', errors='ignore')
  128. log(json.loads(result))
  129. return json.loads(result)
  130.  
  131.  
  132. def stringlist_to_reallist(string):
  133. # this is needed because ast.literal_eval gives me EOF errors for no obvious reason
  134. real_string = string.replace("[","").replace("]","").replace(" ","").split(",")
  135. return real_string
  136.  
  137.  
  138. def runtime_converter(time_string):
  139. if time_string == '':
  140. return 0
  141. else:
  142. x = time_string.count(':')
  143.  
  144. if x == 0:
  145. return int(time_string)
  146. elif x == 2:
  147. h, m, s = time_string.split(':')
  148. return int(h) * 3600 + int(m) * 60 + int(s)
  149. elif x == 1:
  150. m, s = time_string.split(':')
  151. return int(m) * 60 + int(s)
  152. else:
  153. return 0
  154.  
  155.  
  156. def iStream_fix(show_npid,showtitle,episode_np,season_np):
  157.  
  158. # streams from iStream dont provide the showid and epid for above
  159. # they come through as tvshowid = -1, but it has episode no and season no and show name
  160. # need to insert work around here to get showid from showname, and get epid from season and episode no's
  161. # then need to ignore prevcheck
  162. log('fixing istream, data follows...')
  163. log('show_npid = ' +str(show_npid))
  164. log('showtitle = ' +str(showtitle))
  165. log('episode_np = ' +str(episode_np))
  166. log('season_np = ' + str(season_np))
  167. redo = True
  168. count = 0
  169. while redo and count < 2: # this ensures the section of code only runs twice at most
  170. redo = False
  171. count += 1
  172. if show_npid == -1 and showtitle and episode_np and season_np:
  173. prevcheck = False
  174. tmp_shows = json_query(show_request_all,True)
  175. log('tmp_shows = ' + str(tmp_shows))
  176. if 'tvshows'in tmp_shows:
  177. for x in tmp_shows['tvshows']:
  178. if x['label'] == showtitle:
  179. show_npid = x['tvshowid']
  180. eps_query['params']['tvshowid'] = show_npid
  181. tmp_eps = json_query(eps_query,True)
  182. log('tmp eps = '+ str(tmp_eps))
  183. if 'episodes' in tmp_eps:
  184. for y in tmp_eps['episodes']:
  185. if fix_SE(y['season']) == season_np and fix_SE(y['episode']) == episode_np:
  186. ep_npid = y['episodeid']
  187. log('playing epid stream = ' + str(ep_npid))
  188.  
  189. # get odlist
  190. tmp_od = ast.literal_eval(WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', show_npid)))
  191. if show_npid in randos:
  192. tmpoff = WINDOW.getProperty("%s.%s.offlist" % ('LazyTV', show_npid))
  193. if tmp_off:
  194. tmp_od += ast.literal_eval(tmp_off)
  195. log('tmp od = ' + str(tmp_od))
  196. log('ep_npid = ' + str(ep_npid))
  197. if ep_npid not in tmp_od:
  198. log('iStream fix calls get eps')
  199. Main.get_eps([show_npid])
  200. log('iStream fix post get eps')
  201. redo = True
  202.  
  203. return False, show_npid, ep_npid
  204.  
  205.  
  206. def fix_SE(string):
  207. if len(str(string)) == 1:
  208. return '0' + str(string)
  209. else:
  210. return str(string)
  211.  
  212.  
  213. def _breathe():
  214. # lets addon know the service is running
  215. if WINDOW.getProperty('LazyTV_service_running') == 'marco':
  216. WINDOW.setProperty('LazyTV_service_running', 'polo')
  217.  
  218.  
  219. class LazyPlayer(xbmc.Player):
  220. def __init__(self, *args, **kwargs):
  221. xbmc.Player.__init__(self)
  222. LazyPlayer.np_next = False
  223. LazyPlayer.pl_running = 'null'
  224. LazyPlayer.playing_showid = False
  225. LazyPlayer.playing_epid = False
  226. LazyPlayer.nextprompt_trigger = False
  227.  
  228.  
  229. def onPlayBackStarted(self):
  230. log('Playbackstarted',reset=True)
  231. global prevcheck
  232.  
  233. Main.target = False
  234. LazyPlayer.nextprompt_trigger_override = True
  235.  
  236.  
  237. #check if an episode is playing
  238. self.ep_details = json_query(whats_playing, True)
  239. log('this is playing = ' + str(self.ep_details))
  240.  
  241. # grab odlist
  242. # check if current show is in odlist
  243. # if it is then pause and post notification, include S0xE0x of first available
  244. # if notification is Yes Watch then unpause (this should be default action)
  245. # if notification is No, then go to the TV show page
  246. # of if they prefer, start playing that OnDeck episode
  247.  
  248. # xbmc.getInfoLabel('')
  249.  
  250. self.pl_running = WINDOW.getProperty("%s.playlist_running" % ('LazyTV'))
  251.  
  252. if 'item' in self.ep_details and 'type' in self.ep_details['item']:
  253.  
  254. # check if this is a playlist, and if it is then suppress the next_ep_notify when there are more than 1 items
  255. if xbmc.getInfoLabel('VideoPlayer.PlaylistLength') != '1':
  256. log('nextprompt override')
  257. LazyPlayer.nextprompt_trigger_override = False
  258.  
  259.  
  260. if self.ep_details['item']['type'] in ['unknown','episode']:
  261.  
  262. episode_np = fix_SE(self.ep_details['item']['episode'])
  263. season_np = fix_SE(self.ep_details['item']['season'])
  264. showtitle = self.ep_details['item']['showtitle']
  265. show_npid = int(self.ep_details['item']['tvshowid'])
  266.  
  267. try:
  268. ep_npid = int(self.ep_details['item']['id'])
  269. except KeyError:
  270. if self.ep_details['item']['episode'] <0:
  271. prevcheck = False
  272. ep_npid = False
  273. show_npid = False
  274. else:
  275. prevcheck, show_npid, ep_npid = iStream_fix(show_npid,showtitle,episode_np,season_np)
  276.  
  277.  
  278. log(prevcheck, label='prevcheck')
  279.  
  280. if prevcheck and show_npid not in randos and self.pl_running != 'true':
  281. odlist = ast.literal_eval(WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', show_npid)))
  282. stored_epid = int(WINDOW.getProperty("%s.%s.EpisodeID" % ('LazyTV', show_npid)))
  283. stored_seas = fix_SE(int(WINDOW.getProperty("%s.%s.Season" % ('LazyTV', show_npid))))
  284. stored_epis = fix_SE(int(WINDOW.getProperty("%s.%s.Episode" % ('LazyTV', show_npid))))
  285. if ep_npid in odlist[1:] and stored_epid:
  286. #pause
  287. xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"Player.PlayPause","params":{"playerid":1,"play":false},"id":1}')
  288.  
  289. #show notification
  290. usr_note = DIALOG.yesno(lang(32160), lang(32161) % (showtitle,stored_seas, stored_epis), lang(32162))
  291. log(usr_note)
  292.  
  293. if usr_note == 0:
  294. #unpause
  295. xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"Player.PlayPause","params":{"playerid":1,"play":true},"id":1}')
  296. else:
  297. xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Player.Stop", "params": { "playerid": 1 }, "id": 1}')
  298. xbmc.sleep(100)
  299. xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "episodeid": %d }, "options":{ "resume": true } }, "id": 1 }' % (stored_epid))
  300.  
  301. if self.pl_running == 'true' and playlist_notifications:
  302.  
  303. xbmc.executebuiltin('Notification(%s,%s S%sE%s,%i)' % (lang(32163),showtitle,season_np,episode_np,5000))
  304.  
  305. if (self.pl_running == 'true' and resume_partials) or self.pl_running == 'listview':
  306.  
  307. res_point = self.ep_details['item']['resume']
  308. if res_point['position'] > 0:
  309.  
  310. seek_point = int((float(res_point['position']) / float(res_point['total'])) *100)
  311. seek['params']['value'] = seek_point
  312. json_query(seek, True)
  313.  
  314. # this prompts Main daemon to set up the swap and prepare the prompt
  315. LazyPlayer.playing_epid = ep_npid
  316. LazyPlayer.playing_showid = show_npid
  317. log('LazyPlayer supplied showid = ' + str(LazyPlayer.playing_showid))
  318. log('LazyPlayer supplied epid = '+ str(LazyPlayer.playing_epid))
  319.  
  320.  
  321. elif self.ep_details['item']['type'] == 'movie' and self.pl_running == 'true' :
  322.  
  323. if playlist_notifications:
  324.  
  325. xbmc.executebuiltin('Notification(%s,%s,%i)' % (lang(32163),self.ep_details['item']['label'],5000))
  326.  
  327. if resume_partials and self.ep_details['item']['resume']['position'] > 0:
  328. seek_point = int((float(self.ep_details['item']['resume']['position']) / float(self.ep_details['item']['resume']['total'])) *100)
  329. seek['params']['value'] = seek_point
  330. json_query(seek, True)
  331.  
  332. elif moviemid and self.ep_details['item']['playcount'] != 0:
  333. time = runtime_converter(xbmc.getInfoLabel('VideoPlayer.Duration'))
  334. seek_point = int(100 * (time * 0.75 * ((random.randint(0,100) / 100.0) ** 2)) / time)
  335. seek['params']['value'] = seek_point
  336. json_query(seek, True)
  337.  
  338. log('Playbackstarted_End')
  339.  
  340.  
  341. def onPlayBackStopped(self):
  342. self.onPlayBackEnded()
  343.  
  344. def onPlayBackEnded(self):
  345. log('Playbackended', reset =True)
  346.  
  347. LazyPlayer.playing_epid = False
  348.  
  349. xbmc.sleep(500) #give the chance for the playlist to start the next item
  350.  
  351.  
  352. # this is all to handle the next_ep_notification
  353. self.now_name = xbmc.getInfoLabel('VideoPlayer.TVShowTitle')
  354.  
  355. if self.now_name == '':
  356.  
  357. if self.pl_running == 'true':
  358. WINDOW.setProperty("LazyTV.playlist_running", 'false')
  359.  
  360. if LazyPlayer.nextprompt_trigger and LazyPlayer.nextprompt_trigger_override:
  361. LazyPlayer.nextprompt_trigger = False
  362. SE = str(int(Main.nextprompt_info['season'])) + 'x' + str(int(Main.nextprompt_info['episode']))
  363.  
  364. log('promptdefaultaction = ' + str(promptdefaultaction))
  365.  
  366. if promptdefaultaction == 0:
  367. ylabel = lang(32092)
  368. nlabel = lang(32091)
  369. elif promptdefaultaction == 1:
  370. ylabel = lang(32091)
  371. nlabel = lang(32092)
  372.  
  373. elif __release__ == 'Frodo':
  374. if promptduration:
  375. prompt = DIALOG.select(lang(32164), [lang(32165) % promptduration, lang(32166) % (Main.nextprompt_info['showtitle'], SE)], yeslabel = ylabel, nolabel = nlabel, autoclose=promptduration * 1000)
  376. else:
  377. prompt = DIALOG.select(lang(32164), [lang(32165) % promptduration, lang(32166) % (Main.nextprompt_info['showtitle'], SE)], yeslabel = ylabel, nolabel = nlabel)
  378.  
  379. elif __release__ == 'Gotham':
  380. if promptduration:
  381. prompt = DIALOG.yesno(lang(32167) % promptduration, lang(32168) % (Main.nextprompt_info['showtitle'], SE), lang(32169), yeslabel = ylabel, nolabel = nlabel, autoclose=promptduration * 1000)
  382. else:
  383. prompt = DIALOG.yesno(lang(32167) % promptduration, lang(32168) % (Main.nextprompt_info['showtitle'], SE), lang(32169), yeslabel = ylabel, nolabel = nlabel)
  384.  
  385. else:
  386. prompt = 0
  387.  
  388. log("nextep original prompt = " + str(prompt))
  389.  
  390. if prompt == -1:
  391. prompt = 0
  392. elif prompt == 0:
  393. if promptdefaultaction == 1:
  394. prompt = 1
  395. elif prompt == 1:
  396. if promptdefaultaction == 1:
  397. prompt = 0
  398.  
  399. log("nextep final prompt = " + str(prompt))
  400.  
  401. if prompt:
  402. xbmc.executeJSONRPC('{"jsonrpc": "2.0","id": 1, "method": "Playlist.Clear", "params": {"playlistid": 1}}')
  403. #xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "episodeid": %d }, "options":{ "resume": true } }, "id": 1 }' % Main.nextprompt_info['episodeid'])
  404.  
  405. add_this_ep['params']['item']['episodeid'] = int(Main.nextprompt_info['episodeid'])
  406. json_query(add_this_ep, False)
  407. xbmc.sleep(50)
  408. xbmc.Player().play(xbmc.PlayList(1))
  409.  
  410. Main.nextprompt_info = {}
  411.  
  412. log('Playbackended_End')
  413.  
  414.  
  415. class LazyMonitor(xbmc.Monitor):
  416.  
  417. def __init__(self, *args, **kwargs):
  418. xbmc.Monitor.__init__(self)
  419.  
  420.  
  421. def onSettingsChanged(self):
  422. #update the settings
  423. grab_settings()
  424.  
  425. def onDatabaseUpdated(self, database):
  426. if database == 'video':
  427. log('updating due to database notification')
  428. # update the entire list again, this is to ensure we have picked up any new shows.
  429. Main.onLibUpdate = True
  430.  
  431.  
  432. def onNotification(self, sender, method, data):
  433. #this only works for GOTHAM
  434. log('notification!')
  435.  
  436. skip = False
  437.  
  438. try:
  439. self.ndata = ast.literal_eval(data)
  440. except:
  441. skip = True
  442.  
  443. if skip == True:
  444. pass
  445.  
  446. elif method == 'VideoLibrary.OnUpdate':
  447. # Method VideoLibrary.OnUpdate
  448. # data {"item":{"id":1,"type":"episode"},"playcount":4}
  449.  
  450. if 'item' in self.ndata:
  451.  
  452. if 'playcount' in self.ndata:
  453.  
  454. if 'type' in self.ndata['item']:
  455.  
  456. if self.ndata['item']['type'] == 'episode':
  457.  
  458. if self.ndata['playcount'] == 1:
  459.  
  460. log('manual change to watched status, data = ' + str(self.ndata))
  461.  
  462. ep_to_show_query['params']['episodeid'] = self.ndata['item']['id']
  463. tmp_showid = json_query(ep_to_show_query, True)['episodedetails']['tvshowid']
  464. LazyPlayer.playing_epid = self.ndata['item']['id']
  465.  
  466. proceed = False
  467. if tmp_showid in randos:
  468.  
  469. retod = WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', tmp_showid))
  470. try:
  471. a = ast.literal_eval(retod)
  472. except:
  473. a=[]
  474. retoff = WINDOW.getProperty("%s.%s.offlist" % ('LazyTV', tmp_showid))
  475. try:
  476. b = ast.literal_eval(retoff)
  477. except:
  478. b = []
  479.  
  480. if LazyPlayer.playing_epid in a or LazyPlayer.playing_epid in b:
  481. proceed = True
  482.  
  483. else:
  484. retod = WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', tmp_showid))
  485. try:
  486. a = ast.literal_eval(retod)
  487. except:
  488. a = []
  489. if LazyPlayer.playing_epid in a:
  490. proceed = True
  491.  
  492. if proceed:
  493. Main.monitor_override = True
  494. LazyPlayer.playing_showid = json_query(ep_to_show_query, True)['episodedetails']['tvshowid']
  495. log('monitor supplied showid - ' + str(LazyPlayer.playing_showid))
  496. log('monitor supplied epid - ' + str(LazyPlayer.playing_epid))
  497. else:
  498. LazyPlayer.playing_epid = False
  499.  
  500.  
  501. class Main(object):
  502. def __init__(self, *args, **kwargs):
  503. log('monitor instantiated', reset = True)
  504.  
  505. self.initial_limit = 10
  506. self.count = 0
  507. Main.target = False
  508. Main.nextprompt_info = {}
  509. Main.onLibUpdate = False
  510. Main.monitor_override = False
  511. Main.nepl = []
  512. self.eject = False
  513. self.randy_flag = False # the list of currently stored episodes
  514.  
  515. self.initialisation()
  516.  
  517. log('daemon started')
  518. self._daemon() #_daemon keeps the monitor alive
  519.  
  520. def initialisation(self):
  521. log('variable_init_started')
  522.  
  523. self.Player = LazyPlayer() # used to post notifications on episode change
  524. self.Monitor = LazyMonitor(self)
  525. self.retrieve_all_show_ids() # queries to get all show IDs
  526.  
  527. WINDOW.setProperty("%s.playlist_running" % ('LazyTV'), 'null')
  528.  
  529. self.get_eps(showids = self.all_shows_list) #gets the beginning list of unwatched shows
  530.  
  531. xbmc.sleep(1000) # wait 1 seconds before filling the full list
  532.  
  533. self.get_eps(showids = self.all_shows_list)
  534.  
  535. log('variable_init_End')
  536.  
  537.  
  538.  
  539. def _daemon(self):
  540. WINDOW.setProperty('LazyTV_service_running' , 'true')
  541. xbmc.executebuiltin('Notification(%s,%s,%i)' % ('LazyTV',lang(32173),5000))
  542.  
  543.  
  544. while not xbmc.abortRequested and WINDOW.getProperty('LazyTV_service_running'):
  545. xbmc.sleep(100)
  546. self._daemon_check()
  547.  
  548. def _daemon_check(self):
  549.  
  550. _breathe()
  551.  
  552. self.np_next = False
  553.  
  554. if Main.onLibUpdate:
  555. Main.onLibUpdate = False
  556. self.retrieve_all_show_ids()
  557. self.get_eps(showids = self.all_shows_list)
  558.  
  559.  
  560. shuf = WINDOW.getProperty("LazyTV.rando_shuffle")
  561. if shuf == 'true':
  562. WINDOW.setProperty("LazyTV.rando_shuffle", 'false')
  563. log('shuffling randos')
  564. self.reshuffle_randos()
  565.  
  566.  
  567. # this will only show up when the Player detects a TV episode is playing
  568. if LazyPlayer.playing_showid and LazyPlayer.playing_showid in Main.nepl:
  569. log('message recieved, showid = ' + str(LazyPlayer.playing_showid))
  570.  
  571. self.sp_next = LazyPlayer.playing_showid
  572.  
  573. # set TEMP episode
  574. retod = WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', self.sp_next))
  575. retoff = WINDOW.getProperty("%s.%s.offlist" % ('LazyTV', self.sp_next))
  576. offd = ast.literal_eval(retoff)
  577. ond = ast.literal_eval(retod)
  578. tmp_wep = int(WINDOW.getProperty("%s.%s.CountWatchedEps" % ('LazyTV', self.sp_next)).replace("''",'0')) + 1
  579. tmp_uwep = max(0, int(WINDOW.getProperty("%s.%s.CountUnwatchedEps" % ('LazyTV', self.sp_next)).replace("''",'0')) - 1)
  580.  
  581. log('odlist = ' + str(retod))
  582.  
  583.  
  584. if self.sp_next in randos:
  585.  
  586. npodlist = offd + ond
  587.  
  588. if npodlist:
  589.  
  590. if LazyPlayer.playing_epid not in npodlist:
  591. log('rando not in npodlist')
  592.  
  593. self.np_next = False
  594.  
  595. else:
  596. log('rando in odlist')
  597.  
  598. if LazyPlayer.playing_epid in ond:
  599. ond.remove(LazyPlayer.playing_epid)
  600. else:
  601. offd.remove(LazyPlayer.playing_epid)
  602.  
  603. npodlist = offd + ond
  604. random.shuffle(npodlist)
  605. self.np_next = npodlist[0]
  606.  
  607. self.randy_flag = True
  608.  
  609. self.store_next_ep(self.np_next,'temp', ond, offd, tmp_wep, tmp_wep)
  610.  
  611. LazyPlayer.playing_epid = False
  612. LazyPlayer.playing_showid = False
  613.  
  614. if Main.monitor_override:
  615. log('monitor override, swap called')
  616.  
  617. Main.monitor_override = False
  618. LazyPlayer.playing_epid = False
  619. Main.target = False
  620. self.np_next = False
  621.  
  622. self.swap_over(self.sp_next)
  623.  
  624. else:
  625.  
  626. npodlist = ond
  627.  
  628. if npodlist:
  629.  
  630. if LazyPlayer.playing_epid not in npodlist:
  631. log('supplied epid not in odlist')
  632.  
  633. self.np_next = False
  634. LazyPlayer.playing_showid = False
  635. LazyPlayer.playing_epid = False
  636.  
  637. else:
  638.  
  639. cp = npodlist.index(LazyPlayer.playing_epid)
  640. log('supplied epid in odlist at position = ' + str(cp))
  641.  
  642. if cp != len(npodlist) - 1:
  643.  
  644. self.np_next = npodlist[cp + 1] #if the episode is in the list then take the next item and store in temp
  645. newod = [int(x) for x in npodlist[cp + 1:]]
  646.  
  647. self.store_next_ep(self.np_next,'temp', newod, offd, tmp_wep, tmp_wep )
  648.  
  649. log('supplied epid not last in list, retrieved new ep = ' + str(self.np_next))
  650. log('new odlist = ' + str(newod))
  651.  
  652. if Main.monitor_override:
  653. log('monitor override, swap called')
  654.  
  655. self.swap_over(self.sp_next)
  656.  
  657. Main.monitor_override = False
  658. LazyPlayer.playing_epid = False
  659. Main.target = False
  660. self.np_next = False
  661.  
  662. else:
  663. log('supplied epid in last position in odlist, flag to remove from nepl')
  664. self.eject = True #if the episode is the last in the list then send the message to remove the showid from nepl
  665.  
  666. if self.np_next:
  667. log('next ep to load = ' + str(self.np_next))
  668.  
  669. # set NEXTPROMPT if required
  670.  
  671. if nextprompt and self.np_next and not self.eject and not self.randy_flag:
  672.  
  673. prompt_query['params']['episodeid'] = int(self.np_next)
  674.  
  675. cp_details = json_query(prompt_query, True)
  676.  
  677. log(cp_details)
  678.  
  679. if 'episodedetails' in cp_details:
  680.  
  681. Main.nextprompt_info = cp_details['episodedetails']
  682.  
  683.  
  684. # set the TARGET time, every tv show will have a target, some may take longer to start up
  685. tick = 0
  686. while not Main.target and tick < 20:
  687.  
  688. Main.target = runtime_converter(xbmc.getInfoLabel('VideoPlayer.Duration')) * 0.9
  689. tick += 1
  690.  
  691. xbmc.sleep(250)
  692.  
  693. log(label='tick = ',message=str(tick))
  694. log(message='%s:%d' % (int(Main.target/60 if Main.target else 0),Main.target%60), label='target')
  695.  
  696. # resets the ids so this first section doesnt run again until some thing new is playing
  697. LazyPlayer.playing_showid = False
  698.  
  699. # only allow the monitor override to run once
  700. Main.monitor_override = False
  701.  
  702. # only allow the randy flag to run once, this avoids previous episode notification for randos
  703. self.randy_flag = False
  704.  
  705.  
  706. # check the position of the played item every 5 seconds, if it is beyond the Main.target position then trigger the pre-stop update
  707. if Main.target:
  708.  
  709. self.count = (self.count + 1) % 50
  710.  
  711. if self.count == 0: #check the position of the playing item every 5 seconds, if it is past the Main.target then run the swap
  712.  
  713. if runtime_converter(xbmc.getInfoLabel('VideoPlayer.Time')) > Main.target:
  714.  
  715. log('Main.target exceeded')
  716. log(self.nextprompt_info)
  717.  
  718. if self.eject:
  719. self.remove_from_nepl(self.sp_next)
  720. self.sp_next = False
  721. self.eject = False
  722.  
  723. if self.sp_next:
  724. self.swap_over(self.sp_next)
  725. log('swap occurred')
  726.  
  727. if nextprompt and self.nextprompt_info:
  728. log('trigger set')
  729. LazyPlayer.nextprompt_trigger = True
  730.  
  731. self.sp_next = False
  732. self.np_next = False
  733. Main.target = False
  734. Main.monitor_override = False
  735.  
  736. @classmethod
  737. def remove_from_nepl(self,showid):
  738. log('removing from nepl')
  739. if showid in Main.nepl:
  740. log('nepl before = ' + str(Main.nepl))
  741. Main.nepl.remove(showid)
  742. log('nepl after = ' + str(Main.nepl))
  743. WINDOW.setProperty("%s.nepl" % 'LazyTV', str(Main.nepl))
  744.  
  745.  
  746. '''@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  747. remove from smartpl
  748. '''
  749.  
  750. @classmethod
  751. def add_to_nepl(self,showid):
  752. log('adding to nepl')
  753. if showid not in Main.nepl:
  754. log('nepl before = ' + str(Main.nepl))
  755. Main.nepl.append(showid)
  756. log('nepl after = ' + str(Main.nepl))
  757. WINDOW.setProperty("%s.nepl" % 'LazyTV', str(Main.nepl))
  758.  
  759.  
  760. @classmethod
  761. def reshuffle_randos(self, sup_rand=[]):
  762. # this reshuffles the randos, it leaves the rando in the odlist
  763. # it can accept a list of randos or individual ones
  764. # this can only be called at the start of the random play or list view ADDON
  765. # because if it happens after the rando is displayed
  766. # the playingID wont match the stored ID
  767. log('shuffle started')
  768.  
  769. if not sup_rand:
  770. shuf_rand = randos
  771. else:
  772. shuf_rand = sup_rand
  773.  
  774. log('shuffle list = ' +str(shuf_rand))
  775.  
  776. for rando in shuf_rand:
  777.  
  778. # get odlist
  779. try:
  780. tmp_od = ast.literal_eval(WINDOW.getProperty("LazyTV.%s.odlist" % rando))
  781. except:
  782. tmp_od = []
  783. try:
  784. tmp_off = ast.literal_eval(WINDOW.getProperty("LazyTV.%s.offlist" % rando))
  785. except:
  786. tmp_off = []
  787.  
  788. ep = WINDOW.getProperty("LazyTV.%s.EpisodeID" % rando)
  789.  
  790. if not ep:
  791. continue
  792.  
  793. tmp_ep = int(ep)
  794.  
  795. tmp_wep = WINDOW.getProperty("%s.%s.CountWatchedEps" % ('LazyTV', rando)).replace("''",'0')
  796. tmp_uwep = WINDOW.getProperty("%s.%s.CountUnwatchedEps" % ('LazyTV', rando)).replace("''",'0')
  797.  
  798. tmp_cmb = tmp_od + tmp_off
  799. if not tmp_cmb:
  800. continue
  801.  
  802. # choose new rando
  803. random.shuffle(tmp_cmb)
  804. randy = tmp_cmb[0]
  805.  
  806. # get ep details and load it up
  807. self.store_next_ep(randy, rando, tmp_od, tmp_off, tmp_uwep, tmp_wep)
  808. log('shuffle ended')
  809.  
  810.  
  811. def retrieve_all_show_ids(self):
  812. log('retrieve_all_shows_started')
  813.  
  814. self.result = json_query(show_request, True)
  815. if 'tvshows' not in self.result:
  816. self.all_shows_list = []
  817. else:
  818. self.all_shows_list = [id['tvshowid'] for id in self.result['tvshows']]
  819. log('retrieve_all_shows_End')
  820.  
  821.  
  822. @classmethod
  823. def get_eps(self, showids = []):
  824. log('get_eps_started', reset =True)
  825. kcount = 0
  826. # called whenever the Next_Eps stored in 10000 need to be updated
  827. # determines the next ep for the showids it is sent and saves the info to 10000
  828.  
  829. #turns single show id into a list
  830. self.showids = showids if isinstance(showids, list) else [showids]
  831.  
  832. self.lshowsR = json_query(show_request_lw, True) #gets showids and last watched
  833.  
  834. if 'tvshows' not in self.lshowsR: #if 'tvshows' isnt in the result, have the list be empty so we return without doing anything
  835. self.show_lw = []
  836. else:
  837. self.show_lw = [x['tvshowid'] for x in self.lshowsR['tvshows'] if x['tvshowid'] in self.showids]
  838.  
  839. for my_showid in self.show_lw: #process the list of shows
  840.  
  841. _breathe()
  842.  
  843. eps_query['params']['tvshowid'] = my_showid # creates query
  844. self.ep = json_query(eps_query, True) # query grabs the TV show episodes
  845.  
  846. if 'episodes' not in self.ep: #ignore show if show has no episodes
  847. continue
  848. else:
  849. self.eps = self.ep['episodes']
  850.  
  851. played_eps = []
  852. all_unplayed = []
  853. ondeck_eps = []
  854. Season = 1 # these are set to 1x1 in order to ignore specials
  855. Episode = 0
  856. watched_showcount = 0
  857. self.count_ondeckeps = 0 # will be the total number of ondeck episodes
  858. on_deck_epid = ''
  859.  
  860. _append = all_unplayed.append #reference to avoid reevaluation on each loop
  861.  
  862. # runs through the list and finds the watched episode with the highest season and episode numbers, and creates a list of unwatched episodes
  863. for ep in self.eps:
  864. if ep['playcount'] != 0:
  865. watched_showcount += 1
  866. if (ep['season'] == Season and ep['episode'] > Episode) or ep['season'] > Season:
  867. Season = ep['season']
  868. Episode = ep['episode']
  869. else:
  870. _append(ep)
  871.  
  872. # remove duplicate files, this removes the second ep in double episodes
  873. files = []
  874. tmpvar = all_unplayed
  875. for ep in tmpvar:
  876. if ep['file'] and ep['file'] in files:
  877. all_unplayed.remove(ep)
  878. else:
  879. files.append(ep['file'])
  880. del files
  881. del tmpvar
  882.  
  883.  
  884. # this is the handler for random shows, basically, if the show is in the rando list, then unwatched all shows are considered on deck
  885. # this section will now provide both an ondeck list and an offdeck list
  886. unordered_ondeck_eps = [x for x in all_unplayed if x['season'] > Season or (x['season'] == Season and x['episode'] > Episode)]
  887. offdeck_eps = [x for x in all_unplayed if x not in unordered_ondeck_eps]
  888.  
  889. self.count_eps = len(self.eps) # the total number of episodes
  890. self.count_weps = watched_showcount # the total number of watched episodes
  891. self.count_uweps = self.count_eps - self.count_weps # the total number of unwatched episodes
  892.  
  893. # sorts the list of unwatched shows by lowest season and lowest episode, filters the list to remove empty strings
  894. if unordered_ondeck_eps:
  895. unordered_ordered_eps = sorted(unordered_ondeck_eps, key = lambda unordered_ondeck_eps: (unordered_ondeck_eps['season'], unordered_ondeck_eps['episode']))
  896. else:
  897. unordered_ordered_eps = []
  898. ondeck_eps = filter(None, unordered_ordered_eps)
  899.  
  900. if not ondeck_eps and not offdeck_eps: # ignores show if there is no on-deck or offdeck episodes
  901. if my_showid in Main.nepl: # remove the show from nepl
  902. self.remove_from_nepl(my_showid)
  903. continue
  904.  
  905. # get the id for the next show and load the list of episode ids into ondecklist
  906. if my_showid in randos or not ondeck_eps:
  907. comb_deck = ondeck_eps + offdeck_eps
  908. random.shuffle(comb_deck)
  909. on_deck_epid = comb_deck[0]['episodeid']
  910. else:
  911. on_deck_epid = ondeck_eps[0]['episodeid']
  912.  
  913. # another handler for randos, as they have to stay in the odlist
  914. on_deck_list = [x['episodeid'] for x in ondeck_eps] if ondeck_eps else []
  915. off_deck_list = [x['episodeid'] for x in offdeck_eps] if offdeck_eps else []
  916.  
  917. #load the data into 10000 using the showID as the ID
  918. self.store_next_ep(on_deck_epid, my_showid, on_deck_list, off_deck_list, self.count_uweps, self.count_weps)
  919.  
  920. # if the show doesnt have any ondeck eps and it isnt in randos, then dont consider it active
  921. # (even though the offdeck list has been saved and a random episode has been selected and saved)
  922. if not ondeck_eps and my_showid not in randos:
  923. continue
  924.  
  925. # store the showID in NEPL so DEFAULT can retrieve it
  926. if my_showid not in Main.nepl:
  927. Main.nepl.append(my_showid)
  928.  
  929. #update the stored nepl
  930. WINDOW.setProperty("%s.nepl" % 'LazyTV', str(Main.nepl))
  931.  
  932. log('get_eps_Ended')
  933.  
  934. @classmethod
  935. def store_next_ep(self,episodeid,tvshowid, ondecklist, offdecklist, uwep=0,wep=0):
  936.  
  937. #stores the episode info into 10000
  938. try:
  939. TVShowID_ = int(tvshowid)
  940. except:
  941. TVShowID_ = tvshowid
  942.  
  943. if not xbmc.abortRequested:
  944.  
  945. _breathe()
  946.  
  947. ep_details_query['params']['episodeid'] = episodeid # creates query
  948.  
  949. ep_details = json_query(ep_details_query, True) # query grabs all the episode details
  950.  
  951. if ep_details.has_key('episodedetails'): # continue only if there are details
  952. ep_details = ep_details['episodedetails']
  953. episode = ("%.2d" % float(ep_details['episode']))
  954. season = "%.2d" % float(ep_details['season'])
  955. episodeno = "s%se%s" %(season,episode)
  956. rating = str(round(float(ep_details['rating']),1))
  957.  
  958. if ep_details['resume']['position'] and ep_details['resume']['total']:
  959. resume = "true"
  960. played = '%s%%'%int((float(ep_details['resume']['position']) / float(ep_details['resume']['total'])) * 100)
  961. else:
  962. resume = "false"
  963. played = '0%'
  964.  
  965. art = ep_details['art']
  966.  
  967. #if ep_details['playcount'] >= 1:
  968. # watched = "true"
  969. #else:
  970. # watched = "false"
  971. #if not self.PLOT_ENABLE and watched == "false":
  972. #if watched == "false":
  973. # plot = "* Plot hidden to avoid spoilers. *"
  974. #else:
  975. # plot = ep_details['plot']
  976. #plot = ''
  977. #path = self.media_path(ep_details['file'])
  978. #play = 'XBMC.RunScript(' + __addonid__ + ',episodeid=' + str(ep_details.get('episodeid')) + ')'
  979. #streaminfo = self.media_streamdetails(ep_details['file'].encode('utf-8').lower(),ep_details['streamdetails'])
  980.  
  981. WINDOW.setProperty("%s.%s.Title" % ('LazyTV', TVShowID_), ep_details['title'])
  982. WINDOW.setProperty("%s.%s.Episode" % ('LazyTV', TVShowID_), episode)
  983. WINDOW.setProperty("%s.%s.EpisodeNo" % ('LazyTV', TVShowID_), episodeno)
  984. WINDOW.setProperty("%s.%s.Season" % ('LazyTV', TVShowID_), season)
  985. WINDOW.setProperty("%s.%s.TVshowTitle" % ('LazyTV', TVShowID_), ep_details['showtitle'])
  986. WINDOW.setProperty("%s.%s.Art(thumb)" % ('LazyTV', TVShowID_), art.get('thumb',''))
  987. WINDOW.setProperty("%s.%s.Art(tvshow.poster)" % ('LazyTV', TVShowID_), art.get('tvshow.poster',''))
  988. WINDOW.setProperty("%s.%s.Resume" % ('LazyTV', TVShowID_), resume)
  989. WINDOW.setProperty("%s.%s.PercentPlayed" % ('LazyTV', TVShowID_), played)
  990. WINDOW.setProperty("%s.%s.CountWatchedEps" % ('LazyTV', TVShowID_), str(wep))
  991. WINDOW.setProperty("%s.%s.CountUnwatchedEps" % ('LazyTV', TVShowID_), str(uwep))
  992. WINDOW.setProperty("%s.%s.CountonDeckEps" % ('LazyTV', TVShowID_), str(len(ondecklist)))
  993. WINDOW.setProperty("%s.%s.EpisodeID" % ('LazyTV', TVShowID_), str(episodeid))
  994. WINDOW.setProperty("%s.%s.odlist" % ('LazyTV', TVShowID_), str(ondecklist))
  995. WINDOW.setProperty("%s.%s.offlist" % ('LazyTV', TVShowID_), str(offdecklist))
  996. WINDOW.setProperty("%s.%s.File" % ('LazyTV', TVShowID_), ep_details['file'])
  997.  
  998. #WINDOW.setProperty("%s.%s.Watched" % ('LazyTV', TVShowID_), watched)
  999. #WINDOW.setProperty("%s.%s.Path" % ('LazyTV', TVShowID_), path)
  1000. #WINDOW.setProperty("%s.%s.Play" % ('LazyTV', TVShowID_), play)
  1001. #WINDOW.setProperty("%s.%s.VideoCodec" % ('LazyTV', TVShowID_), streaminfo['videocodec'])
  1002. #WINDOW.setProperty("%s.%s.VideoResolution" % ('LazyTV', TVShowID_), streaminfo['videoresolution'])
  1003. #WINDOW.setProperty("%s.%s.VideoAspect" % ('LazyTV', TVShowID_), streaminfo['videoaspect'])
  1004. #WINDOW.setProperty("%s.%s.AudioCodec" % ('LazyTV', TVShowID_), streaminfo['audiocodec'])
  1005. #WINDOW.setProperty("%s.%s.AudioChannels" % ('LazyTV', TVShowID_), str(streaminfo['audiochannels']))
  1006. #WINDOW.setProperty("%s.%s.Art(tvshow.fanart)" % ('LazyTV', TVShowID_), art.get('tvshow.fanart',''))
  1007. #WINDOW.setProperty("%s.%s.Art(tvshow.banner)" % ('LazyTV', TVShowID_), art.get('tvshow.banner',''))
  1008. #WINDOW.setProperty("%s.%s.Art(tvshow.clearlogo)" % ('LazyTV', TVShowID_), art.get('tvshow.clearlogo',''))
  1009. #WINDOW.setProperty("%s.%s.Art(tvshow.clearart)" % ('LazyTV', TVShowID_), art.get('tvshow.clearart',''))
  1010. #WINDOW.setProperty("%s.%s.Art(tvshow.landscape)" % ('LazyTV', TVShowID_), art.get('tvshow.landscape',''))
  1011. #WINDOW.setProperty("%s.%s.Art(tvshow.characterart)"% ('LazyTV', TVShowID_), art.get('tvshow.characterart',''))
  1012. #WINDOW.setProperty("%s.%s.Rating" % ('LazyTV', TVShowID_), rating)
  1013. #WINDOW.setProperty("%s.%s.Runtime" % ('LazyTV', TVShowID_), str(int((ep_details['runtime'] / 60) + 0.5)))
  1014. #WINDOW.setProperty("%s.%s.Premiered" % ('LazyTV', TVShowID_), ep_details['firstaired'])
  1015. #WINDOW.setProperty("%s.%s.Plot" % ('LazyTV', TVShowID_), plot)
  1016. #WINDOW.setProperty("%s.%s.DBID" % ('LazyTV', TVShowID_), str(ep_details.get('episodeid')))
  1017.  
  1018. del ep_details
  1019.  
  1020. Main.update_smartplaylist(TVShowID_)
  1021.  
  1022.  
  1023. def swap_over(self, TVShowID_):
  1024. log('swapover_started')
  1025.  
  1026. WINDOW.setProperty("%s.%s.Title" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Title" % ('LazyTV', 'temp')))
  1027. WINDOW.setProperty("%s.%s.Episode" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Episode" % ('LazyTV', 'temp')))
  1028. WINDOW.setProperty("%s.%s.EpisodeNo" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.EpisodeNo" % ('LazyTV', 'temp')))
  1029. WINDOW.setProperty("%s.%s.Season" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Season" % ('LazyTV', 'temp')))
  1030. WINDOW.setProperty("%s.%s.TVshowTitle" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.TVshowTitle" % ('LazyTV', 'temp')))
  1031. WINDOW.setProperty("%s.%s.Art(thumb)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(thumb)" % ('LazyTV', 'temp')))
  1032. WINDOW.setProperty("%s.%s.Art(tvshow.poster)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.poster)" % ('LazyTV', 'temp')))
  1033. WINDOW.setProperty("%s.%s.Resume" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Resume" % ('LazyTV', 'temp')))
  1034. WINDOW.setProperty("%s.%s.PercentPlayed" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.PercentPlayed" % ('LazyTV', 'temp')))
  1035. WINDOW.setProperty("%s.%s.CountWatchedEps" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.CountWatchedEps" % ('LazyTV', 'temp')))
  1036. WINDOW.setProperty("%s.%s.CountUnwatchedEps" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.CountUnwatchedEps" % ('LazyTV', 'temp')))
  1037. WINDOW.setProperty("%s.%s.CountonDeckEps" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.CountonDeckEps" % ('LazyTV', 'temp')))
  1038. WINDOW.setProperty("%s.%s.EpisodeID" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.EpisodeID" % ('LazyTV', 'temp')))
  1039. WINDOW.setProperty("%s.%s.odlist" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', 'temp')))
  1040. WINDOW.setProperty("%s.%s.offlist" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.offlist" % ('LazyTV', 'temp')))
  1041. WINDOW.setProperty("%s.%s.File" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.File" % ('LazyTV', 'temp')))
  1042.  
  1043. #WINDOW.setProperty("%s.%s.Watched" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.watched" % ('LazyTV', 'temp')))
  1044. #WINDOW.setProperty("%s.%s.Path" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Path" % ('LazyTV', 'temp')))
  1045. #WINDOW.setProperty("%s.%s.Play" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Play" % ('LazyTV', 'temp')))
  1046. #WINDOW.setProperty("%s.%s.VideoCodec" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.VideoCodec" % ('LazyTV', 'temp')))
  1047. #WINDOW.setProperty("%s.%s.VideoResolution" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.VideoResolution" % ('LazyTV', 'temp')))
  1048. #WINDOW.setProperty("%s.%s.VideoAspect" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.VideoAspect" % ('LazyTV', 'temp')))
  1049. #WINDOW.setProperty("%s.%s.AudioCodec" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.AudioCodec" % ('LazyTV', 'temp')))
  1050. #WINDOW.setProperty("%s.%s.AudioChannels" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.AudioChannels" % ('LazyTV', 'temp')))
  1051. #WINDOW.setProperty("%s.%s.Art(tvshow.banner)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.banner)" % ('LazyTV', 'temp')))
  1052. #WINDOW.setProperty("%s.%s.Art(tvshow.clearlogo)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.clearlogo)" % ('LazyTV', 'temp')))
  1053. #WINDOW.setProperty("%s.%s.Art(tvshow.clearart)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.clearart)" % ('LazyTV', 'temp')))
  1054. #WINDOW.setProperty("%s.%s.Art(tvshow.landscape)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.landscape)" % ('LazyTV', 'temp')))
  1055. #WINDOW.setProperty("%s.%s.Art(tvshow.characterart)"% ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.characterart)" % ('LazyTV', 'temp')))
  1056. #WINDOW.setProperty("%s.%s.Art(tvshow.fanart)" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Art(tvshow.fanart)" % ('LazyTV', 'temp')))
  1057. #WINDOW.setProperty("%s.%s.Rating" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Rating" % ('LazyTV', 'temp')))
  1058. #WINDOW.setProperty("%s.%s.Runtime" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Runtime" % ('LazyTV', 'temp')))
  1059. #WINDOW.setProperty("%s.%s.Premiered" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Premiered" % ('LazyTV', 'temp')))
  1060. #WINDOW.setProperty("%s.%s.Plot" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.Plot" % ('LazyTV', 'temp')))
  1061. #WINDOW.setProperty("%s.%s.DBID" % ('LazyTV', TVShowID_), WINDOW.getProperty("%s.%s.DBID" % ('LazyTV', 'temp')))
  1062.  
  1063. Main.update_smartplaylist(TVShowID_)
  1064.  
  1065. log('swapover_End')
  1066.  
  1067.  
  1068. @classmethod
  1069. def update_smartplaylist(self, tvshowid):
  1070.  
  1071. if maintainsmartplaylist:
  1072.  
  1073. log('updating playlist with: ' + str(tvshowid))
  1074.  
  1075. playlist_file = os.path.join(videoplaylistlocation,'LazyTV.xsp')
  1076.  
  1077. showname = WINDOW.getProperty("%s.%s.TVshowTitle" % ('LazyTV', tvshowid))
  1078. filename = os.path.basename(WINDOW.getProperty("%s.%s.File" % ('LazyTV', tvshowid)))
  1079.  
  1080. log(showname)
  1081. log(filename)
  1082.  
  1083. if showname:
  1084.  
  1085. # tries to read the file, if it cant it creates a new file
  1086. try:
  1087. f = open(playlist_file, 'r')
  1088. all_lines = f.readlines()
  1089. f.close()
  1090. except:
  1091. all_lines = []
  1092.  
  1093. content = []
  1094. line1 = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><smartplaylist type="episodes"><name>LazyTV</name><match>one</match>\n'
  1095. linex = '<order direction="ascending">random</order></smartplaylist>'
  1096. rawshowline = '<!--%s--><rule field="filename" operator="is"> <value>%s</value> </rule><!--END-->\n'
  1097.  
  1098. xbmc.sleep(10)
  1099.  
  1100. with open(playlist_file, 'w+') as g:
  1101.  
  1102. found = False
  1103.  
  1104. # creates the file if it doesnt exist or is empty
  1105. if not all_lines:
  1106. content.append(line1)
  1107. content.append(rawshowline % (showname, filename))
  1108. content.append(linex)
  1109.  
  1110. # this will only occur if the file had contents
  1111. for num, line in enumerate(all_lines):
  1112.  
  1113.  
  1114. # showname found in line, replacing the file
  1115. if ''.join(["<!--",showname,"-->"]) in line:
  1116. if filename:
  1117. log('playlist item updated: ' + str(showname) + ', ' + str(filename))
  1118.  
  1119. content.append(rawshowline % (showname, filename))
  1120.  
  1121. found = True
  1122.  
  1123. # no entry found and this is the last line, create a new entry and finish off the file
  1124. elif found == False and line == linex:
  1125. log('entry not found, adding')
  1126.  
  1127. content.append(rawshowline % (showname, filename))
  1128. content.append(line)
  1129.  
  1130. # showname not found, not final line, so just carry it over to the new file
  1131. else:
  1132. content.append(line)
  1133.  
  1134.  
  1135. # writes the new stuff to the file
  1136. guts = ''.join(content)
  1137. g.write(guts)
  1138.  
  1139. log('playlist update complete')
  1140.  
  1141.  
  1142.  
  1143. def grab_settings(firstrun = False):
  1144. global playlist_notifications
  1145. global resume_partials
  1146. global keep_logs
  1147. global nextprompt
  1148. global promptduration
  1149. global randos
  1150. global prevcheck
  1151. global maintainsmartplaylist
  1152. global promptdefaultaction
  1153.  
  1154. playlist_notifications = True if __setting__("notify") == 'true' else False
  1155. resume_partials = True if __setting__('resume_partials') == 'true' else False
  1156. keep_logs = True if __setting__('logging') == 'true' else False
  1157. nextprompt = True if __setting__('nextprompt') == 'true' else False
  1158. promptduration = int(__setting__('promptduration'))
  1159. prevcheck = True if __setting__('prevcheck') == 'true' else False
  1160. promptdefaultaction = True if __setting__('promptdefaultaction') == 'true' else False
  1161.  
  1162. if not maintainsmartplaylist:
  1163. maintainsmartplaylist = True if __setting__('maintainsmartplaylist') == 'true' else False
  1164. if maintainsmartplaylist and not firstrun:
  1165. for neep in Main.nepl:
  1166. Main.update_smartplaylist(neep)
  1167.  
  1168. else:
  1169. maintainsmartplaylist = True if __setting__('maintainsmartplaylist') == 'true' else False
  1170.  
  1171.  
  1172. try:
  1173. randos = ast.literal_eval(__setting__('randos'))
  1174. except:
  1175. randos = []
  1176.  
  1177. try:
  1178. old_randos = ast.literal_eval(WINDOW.getProperty("LazyTV.randos"))
  1179. except:
  1180. old_randos = []
  1181.  
  1182. if old_randos != randos and not firstrun:
  1183. for r in randos:
  1184. if r not in old_randos:
  1185. log('adding rando')
  1186. # if new rando, then add new randos to nepl and shuffle
  1187. Main.add_to_nepl(r)
  1188. Main.reshuffle_randos(sup_rand = [r])
  1189.  
  1190. for oar in old_randos:
  1191. if oar not in randos:
  1192. log('removing rando')
  1193. # if rando removed then check if rando has ondeck, if not then remove from nepl,
  1194. try:
  1195. has_ond = ast.literal_eval(WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', oar)))
  1196. log('odlist = ' + str(has_ond))
  1197. except:
  1198. has_ond = False
  1199.  
  1200. # if so, then store the next ep
  1201. if has_ond:
  1202. log('adding ondeck ep for removed rando')
  1203. retod = WINDOW.getProperty("%s.%s.odlist" % ('LazyTV', oar))
  1204. retoff = WINDOW.getProperty("%s.%s.offlist" % ('LazyTV', oar))
  1205. offd = ast.literal_eval(retoff)
  1206. ond = ast.literal_eval(retod)
  1207. tmp_wep = int(WINDOW.getProperty("%s.%s.CountWatchedEps" % ('LazyTV', oar)).replace("''",'0')) + 1
  1208. tmp_uwep = max(0, int(WINDOW.getProperty("%s.%s.CountUnwatchedEps" % ('LazyTV', oar)).replace("''",'0')) - 1)
  1209.  
  1210. Main.store_next_ep(ond[0], oar, ond, offd, tmp_uwep, tmp_wep)
  1211.  
  1212. else:
  1213. Main.remove_from_nepl(oar)
  1214.  
  1215. # finally, set the new stored randos
  1216. WINDOW.setProperty("LazyTV.randos", str(randos))
  1217.  
  1218. log('randos = ' + str(randos))
  1219.  
  1220. log('settings grabbed')
  1221.  
  1222.  
  1223. if ( __name__ == "__main__" ):
  1224. xbmc.sleep(000) #testing delay for clean system
  1225. log(' %s started' % str(__addonversion__))
  1226.  
  1227. grab_settings(firstrun = True) # gets the settings for the Addon
  1228.  
  1229. Main()
  1230.  
  1231. del Main
  1232. del LazyMonitor
  1233. del LazyPlayer
  1234.  
  1235. log(' %s stopped' % str(__addonversion__))
RAW Paste Data