123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- 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
|