VERSION = "0.1.1" CHANNEL_NAME = "PlayStream" PREFIX = '/video/playstream' DEV = True if Platform.MachineIdentifier == 'Unit testing' else False ART = "art-default.jpg" ICON = "icon-default.png" BACK = "back.png" FOLDER = "folder.png" VIDEO = "video.png" SEARCH = "folder_search.png" PREFS = "prefs.png" import sys, os, re import traceback, glob, inspect, urllib import content from content.ContentSources import ContentSources from content import util import Framework #from Framework.api.objectkit import * from DumbTools import DumbKeyboard, DumbPrefs sources_directory = os.path.join(os.path.dirname(inspect.getsourcefile(content)), "sources") sources = ContentSources(sources_directory) data0 = None title0 = None history = [] view_modes = { "List": 65586, "InfoList": 65592, "MediaPreview": 458803, "Showcase": 458810, "Coverflow": 65591, "PanelStream": 131124, "WallStream": 131125, "Songs": 65593, "Seasons": 65593, "Albums": 131123, "Episodes": 65590,"ImageStream":458809,"Pictures":131123 } ''' for source in sources.plugins: if not ("options" in dir(sources.plugins[source]) and sources.plugins[source].options): continue options = sources.plugins[source].options if not options: continue for option in options: key="%s_%s"%(source,option) if key in ("viaplay_device"): continue # exception list, value = plugin.get_setting(key) options[option] = value sources.plugins[source].options_write(options) prefix = "" ''' ################################################################################################### def Start(): ObjectContainer.title1 = CHANNEL_NAME ObjectContainer.art = R(ART) Plugin.AddViewGroup("InfoList", viewMode="InfoList", mediaType="items") Plugin.AddViewGroup("List", viewMode="List", mediaType="items") #DirectoryObject.thumb = R(ICON) #DirectoryObject.art = R(ART) #EpisodeObject.thumb = R(ICON) #EpisodeObject.art = R(ART) #VideoClipObject.thumb = R(ICON) #VideoClipObject.art = R(ART) #HTTP.CacheTime = CACHE_1DAY #HTTP.Headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36' def ValidatePrefs(): #preferences = Prefs._sandbox.preferences.get() for source in sources.plugins: if not ("options" in dir(sources.plugins[source]) and sources.plugins[source].options): continue options = sources.plugins[source].options if not options: continue for option in options: key="%s_%s"%(source,option) if key in ("viaplay_device"): continue # exception list, value = Prefs[key] options[option] = value if not DEV: sources.plugins[source].options_write(options) #################################################################################################### @handler(PREFIX, CHANNEL_NAME, art=ART, thumb=ICON) def Main(): data = "config::home" oc = Menu(data, "Home") oc.view_group = "InfoList" ValidatePrefs() return oc #################################################################################################### @route(PREFIX+'/{data}/') def Menu2(data, title): return Menu(data, title) @route(PREFIX+'/search') def Search(query, data, title): #data = data.replace("%2F", "/") Log("Search data="+data) Log("Search query="+query) data2 = data.format(query) return Menu(data2, title) @route(PREFIX+'/{data}') def Menu(data, title, **kwargs): #includeBandwidths=1, checkFiles=0, includeConcerts=0, includeExtras=0, includeOnDeck=0, includePopularLeaves=1&includeChapters=1&checkFiles=1): global data0, title0, history #sources.plugins["config"].read_streams() Log("[playstream] ** Menu call: %s - %s" % ( data, title)) if not data: data = u"config::home" # Process history if data == "back": data = history[-1][0].replace("/", "%2F") if history and history[-1][0] else "config::home" title = history[-1][1] if history and history[-1][0] else "Home" if data == data0 or (len(history) > 2 and data == history[-2]): # fake call, skipped Log("history skipped") else: if history and history[-1][0] and data == history[-1][0]: history.pop() Log("history poped") else: history.append((data0, title0)) Log("history added %s" % data0) data0 = data title0 = title data = data.replace("%2F", "/") hst = "" for h in history: hst += "\n%s" % h[0] #Log("[playstream] history="+hst) ### Processig call ### Log("[playstream] processing data=%s"%data) try: is_video = sources.is_video(data) except: Log(traceback.format_exc()) return ObjectContainer(header="Error", message=unicode(e)) ### Video handling ### if is_video: try: streams = sources.get_streams(data) except Exception,e: Log(traceback.format_exc()) return ObjectContainer(header="Error", message=unicode(e)) if streams: data2 = data.replace("/", "%2F") title = streams[0]["name"] if isinstance(streams[0]["name"] , unicode) else streams[0]["name"].decode("utf8") if not title: title = "Title" desc = streams[0]["desc"] if isinstance(streams[0]["desc"] , unicode) else streams[0]["desc"] .decode("utf8") img = streams[0]["img"] if isinstance(streams[0]["img"] , unicode) else streams[0]["img"] .decode("utf8") vco = VideoClipObject( key=Callback(Menu, data=data2, title=title ), rating_key=data2, title=title, summary=desc, thumb=thumb_data(img, video=True) ) for stream in streams: vco.add(MediaObject( #bitraate=0, #container=Container.MPEGTS optimized_for_streaming = True, parts=[PartObject(key=HTTPLiveStreamURL(stream["url"]))] )) include_container = True return ObjectContainer(objects = [vco]) if include_container else vco else: return ObjectContainer(header="Error", message="No streams found!") ### List handling ### oc = ObjectContainer(title2=title) oc.view_group = "InfoList" try: content = sources.get_content(data) except Exception,e: Log(traceback.format_exc()) return ObjectContainer(header="Error", message=unicode(e)) Log( "[playstream] %s items returned"%len(content)) for item in content: data2 = item[1] #data2 = urllib.quote(data2, safe="") data2 = data2.replace("/", "%2F") title = item[0] if isinstance(item[0], unicode) else item[0].decode("utf8") if not title: title = "Title" img = item[2] #if isinstance(item[2], unicode) else item[2].decode("utf8") desc = item[3] if isinstance(item[3], unicode) else item[3].decode("utf8") # Search item # if "{0}" in data2: #q = "aaa" # TODO InputDirectoryObject ##data = data.format(q) if Client.Product in DumbKeyboard.clients: DumbKeyboard(PREFIX, oc, Search, dktitle = title, dkthumb = thumb_data(SEARCH), title=title, data=data2 ) else: oc.add(InputDirectoryObject( key=Callback(Search, data=data2, title=title), title = title, thumb = thumb_data(img), #Resource.ContentsOfURLWithFallback(img, fallback=R(ICON)), prompt=desc, summary =desc )) # Video item # elif sources.is_video(item[1]): oc.add(VideoClipObject( key=Callback(Menu, data=data2, title=title), title = title, thumb = thumb_data(img, video=True), #Resource.ContentsOfURLWithFallback(img, fallback=R(ICON)), summary = desc, rating_key=data2 )) # List object # else: oc.add(DirectoryObject( key=Callback(Menu, data=data2, title=title), title = title, thumb = thumb_data(img) if not data2=="back" else R(BACK), summary =desc )) if data == "config::home": if Client.Product in DumbPrefs.clients: DumbPrefs(PREFIX, oc, title = "Plugin options", thumb = R(PREFS)) else: oc.add(PrefsObject( title="Plugin options", summary="Update plugin options", thumb=R(PREFS), art=R(ART) )) ValidatePrefs() return oc def thumb_data(img, video=False): default = R(VIDEO) if video else R(FOLDER) if img.startswith('http'): img2 = Resource.ContentsOfURLWithFallback(img, default) elif img in ("default", ""): img2 = default else: img2 = R(img) return img2