Play images and video from Synology PhotoStation server

addon.py 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. # -*- coding: utf-8 -*-
  2. try:
  3. import wingdbstub
  4. except:
  5. pass
  6. import os,os.path,sys, urllib, urlparse
  7. #import xbmc, xbmcgui, xbmcplugin, xbmcvfs, xbmcaddon
  8. from kodiswift import Plugin, ListItem, storage
  9. from kodiswift import xbmc, xbmcgui, xbmcplugin, xbmcvfs, xbmcaddon, CLI_MODE, SortMethod
  10. from resources.lib import photostation_api
  11. plugin = Plugin()
  12. handle = sys.argv[1]
  13. view_mode = plugin.get_setting("view_mode",str)
  14. server = plugin.get_setting("server", str)
  15. user = plugin.get_setting("user", str)
  16. password = plugin.get_setting("password", str)
  17. page_size = plugin.get_setting("page_size", str)
  18. page_size = -1 if page_size == "All" else int(page_size)
  19. sorting = plugin.get_setting("sorting", str)
  20. order = plugin.get_setting("order", str)
  21. video_quality = plugin.get_setting("video_quality", str)
  22. picture_quality = plugin.get_setting("picture_quality", str)
  23. thumbnail_quality = plugin.get_setting("thumbnail_quality", str)
  24. play_next = plugin.get_setting("play_next", bool)
  25. start_page = plugin.get_setting("start_page", str)
  26. ps = photostation_api.PhotoStationAPI("http://home.blue.lv/photo")
  27. try:
  28. ps.login(user, password)
  29. except Exception as e:
  30. print "Error while logging %s/%s"%(user,password)
  31. plugin.notify(str(e),"",10000)
  32. prefix = ""
  33. @plugin.route(".+" )
  34. def main():
  35. # plugin://xxx/
  36. global prefix
  37. prefix = "%s://%s/"%(plugin.request.scheme,plugin.request.netloc)
  38. data = plugin.request.url.replace(prefix,"")
  39. data = urllib.unquote(data)
  40. #default_oid = "album_323031372f323031372d30312d313320536c69646f73616e61"
  41. default_oid = "" #start_page
  42. if not data:
  43. data = default_oid
  44. oid = plugin.request.path[1:]
  45. if not oid:
  46. oid = default_oid
  47. qs = dict(urlparse.parse_qsl(plugin.request.query_string))
  48. if not "page" in qs:
  49. page = 1
  50. else:
  51. page = int(qs["page"])
  52. if not oid or oid.startswith("album") or oid.startswith("category"):
  53. plugin.set_content("images")
  54. content = []
  55. if not oid:
  56. categories = ps.get_categories()["categories"]
  57. for cat in categories:
  58. if cat["hidden"]:
  59. continue
  60. data2 = prefix + cat["id"]
  61. label = cat["name"]
  62. item = xbmcgui.ListItem(label, "", "", "", data2)
  63. item.setInfo("Image", {"title":label})
  64. item.setProperty("is_folder", "true")
  65. item.setProperty("url", data2)
  66. #items.append(item)
  67. xbmcplugin.addDirectoryItem(handle=plugin.handle, url=data2, listitem=item, isFolder=True)
  68. offset = 0 if page_size == -1 else (page - 1) * page_size
  69. limit = -1 if page_size == -1 else page_size
  70. if "category" in oid:
  71. content = ps.get_category_list(oid)
  72. else:
  73. content = ps.get_album_list(oid, offset=offset, limit=limit, sort_by=sorting, sort_direction=order )
  74. items = []
  75. for f in content["items"]:
  76. label = f["info"]["title"]
  77. if not label:
  78. continue
  79. label2 = f["additional"]["file_location"] if "file_location" in f["additional"] else ""
  80. type = f["type"]
  81. oid2 = f["id"]
  82. is_playable = "true" if type in ("video","photo") else ""
  83. is_folder = "" if type in ("video","photo") else "true"
  84. thumb_quality = thumbnail_quality if thumbnail_quality in f["thumbnail_status"] else "small"
  85. thumb_url = ps.get_thumb_url(f["id"],thumb_quality)
  86. #thumb_url = urllib.quote(thumb_url, ":/")
  87. data2 = prefix+f["id"]
  88. if type=="album":
  89. nfiles = int(f["additional"]["item_count"]["photo"]) + int(f["additional"]["item_count"]["video"]) if "item_count" in f["additional"] else None
  90. suf = "\n(%s)" % nfiles if nfiles else ""
  91. label2 = "%s photos, %s videos"%(f["additional"]["item_count"]["photo"],f["additional"]["item_count"]["video"]) if "item_count" in f["additional"] else ""
  92. label = label + suf
  93. li_type = "video" # pictures
  94. tags = {
  95. #"title":f["info"]["title"],
  96. "title": label,
  97. #"picturepath":f["additional"]["file_location"]
  98. "label": label,
  99. "plotline":f["additional"]["file_location"] + "\n" + label2 if "file_location" in f["additional"] else "",
  100. "plot":f["additional"]["file_location"] + "\n" + label2 if "file_location" in f["additional"] else "",
  101. "path": f["info"]["sharepath"] if "sharepath" in f["additional"] else "",
  102. }
  103. elif type == "photo":
  104. label = label + "\n" + f["info"]["takendate"]
  105. label2 = f["info"]["takendate"]
  106. image_url = ps.get_photo_url(oid2) if picture_quality == "original" else ps.get_thumb_url(oid2, picture_quality)
  107. data2 = image_url
  108. #print "image_url=", data2
  109. #data2 = urllib.quote(data2, ":/")
  110. li_type = "pictures"
  111. tags = {
  112. "title": label2, #f["info"]["title"],
  113. "date": f["info"]["takendate"],
  114. "picturepath": f["additional"]["file_location"],
  115. "exif:resolution": "%s,%s" % (f["info"]["resolutionx"], f["info"]["resolutiony"]),
  116. #"exif:path": f["additional"]["file_location"],
  117. #"exif:name": f["info"]["name"],
  118. #"exif:filename": f["additional"]["file_location"],
  119. #"exif:"
  120. # TODO pārejie EXIF u.c. dati
  121. }
  122. elif type=="video":
  123. label = label + "\n" + f["info"]["takendate"]
  124. label2 = f["info"]["takendate"]
  125. li_type = 'video'
  126. tags = {
  127. "title": label ,
  128. "plot": f["additional"]["file_location"],
  129. #TODO
  130. }
  131. if play_next:
  132. data2 = data2 + "&album=" + oid if "?" in data2 else data2 + "?album=" + oid
  133. #data2 = urllib.quote(data2, ":/")
  134. is_playable = ""
  135. else:
  136. if video_quality == "original":
  137. quality_id = ""
  138. else:
  139. quality_id = f["additional"]["video_quality"][0]["id"]
  140. data2 = ps.get_video_url(oid2, quality_id)
  141. #data2 = urllib.quote(data2, ":/")
  142. item = xbmcgui.ListItem(label=label, label2=label2, path=data2)
  143. item.setArt({
  144. "thumb": thumb_url,
  145. "icon": thumb_url,
  146. "fanart": thumb_url,
  147. })
  148. item.setInfo(li_type, tags)
  149. item.setProperty("is_folder", is_folder)
  150. item.setProperty('IsPlayable', is_playable)
  151. item.setProperty("url", data2)
  152. #items.append(item)
  153. xbmcplugin.addDirectoryItem(handle=plugin.handle, url=data2, listitem=item, isFolder=True if is_folder=="true" else False,
  154. totalItems=len(content["items"]))
  155. if page_size <> -1 and len(content["items"]) == page_size:
  156. data2 = prefix+oid+"?page=%s" % (page+1)
  157. #data2 = urllib.quote(data2, ":/")
  158. item = xbmcgui.ListItem("Next", "", "", "", data2)
  159. item.setInfo("Image", {"title":"Next"})
  160. item.setProperty("is_folder", "false")
  161. item.setProperty("url", data2)
  162. #items.append(item)
  163. xbmcplugin.addDirectoryItem(handle=plugin.handle, url=data2, listitem=item, isFolder=True,
  164. totalItems=len(content["items"]))
  165. view_mode_id = get_view_mode(view_mode)
  166. xbmc.executebuiltin('Container.SetViewMode(%s)' % view_mode_id)
  167. #sort_methods = [SortMethod.FILE, SortMethod.DATE, SortMethod.DATE_TAKEN]
  168. #xbmcplugin.addSortMethod( plugin.handle, sortMethod=xbmcplugin.SORT_METHOD_GENRE )
  169. xbmcplugin.endOfDirectory(plugin.handle, succeeded=True, updateListing=False, cacheToDisc=True)
  170. #return plugin.finish(items, sort_methods=None, view_mode=view_mode_id, cache_to_disc=True, update_listing=False)
  171. elif oid.startswith("photo"):
  172. print "play_photo ", oid
  173. try:
  174. url = ps.get_thumb_url(oid,"large")
  175. #thumb_url = ps.get_thumb_url(oid,"smalll")
  176. #js = ps.get_photo_info(oid)
  177. #title = js["info"]["name"]
  178. except Exception,e:
  179. plugin.notify(str(e),"",10000)
  180. return None
  181. print "set_resolved_url", url
  182. plugin.set_resolved_url(url)
  183. elif oid.startswith("video"):
  184. if play_next and "album" in qs: # play playlist
  185. print "play_playlist", data, qs
  186. album_id = qs["album"]
  187. try:
  188. items = ps.get_album_list(album_id)
  189. except Exception,e:
  190. plugin.notify(str(e),"",10000)
  191. return None
  192. if items:
  193. play_playlist(items["items"], oid)
  194. return None
  195. else:
  196. plugin.notify("No items found!",10000)
  197. return None
  198. else: # play one video
  199. print "play_video"
  200. try:
  201. streams = ps.get_video_streams(oid)
  202. js = ps.get_photo_info(oid)
  203. except Exception,e:
  204. plugin.notify(str(e),"",10000)
  205. return None
  206. if streams:
  207. play_video(streams)
  208. return None
  209. else:
  210. plugin.notify("No streams found!",10000)
  211. return None
  212. def get_view_mode(vm):
  213. modes = {
  214. #"skin.estuary.isl"
  215. "skin.estuary": {
  216. "None": None,
  217. "List": 50,
  218. "Poster": 51,
  219. "IconWall":52 ,
  220. "Shift": 53,
  221. "InfoWall": 54,
  222. "WideList": 55,
  223. "Wall": 500,
  224. "Banner": 501,
  225. "FanArt": 502
  226. },
  227. "skin.estuary.isl": {
  228. "None": None,
  229. "List": 50,
  230. "Poster": 51,
  231. "IconWall":52 ,
  232. "Shift": 53,
  233. "InfoWall": 54,
  234. "WideList": 55,
  235. "Wall": 500,
  236. "Banner": 501,
  237. "FanArt": 502
  238. },
  239. "skin.estuary.is": {
  240. "None": None,
  241. "List": 50,
  242. "Poster": 51,
  243. "IconWall":52 ,
  244. "Shift": 53,
  245. "InfoWall": 54,
  246. "WideList": 55,
  247. "Wall": 500,
  248. "Banner": 501,
  249. "FanArt": 502
  250. },
  251. }
  252. skin = xbmc.getSkinDir()
  253. if skin in modes and vm in modes[skin]:
  254. view_mode = modes[skin][vm]
  255. else:
  256. view_mode = 500
  257. return view_mode
  258. def play_playlist(items, oid):
  259. playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
  260. playlist.clear()
  261. pos = -1
  262. i = 0
  263. for f in items:
  264. if f["type"] in ("album","photo"):
  265. continue
  266. label = f["info"]["name"] + "\n" + f["info"]["takendate"]
  267. label2 = f["additional"]["file_location"]
  268. type = f["type"]
  269. oid2 = f["id"]
  270. if oid == oid2:
  271. pos = i
  272. #is_playable = True if type in ("video","photo") else False
  273. is_folder = False if type in ("video","photo") else True
  274. thumb_quality = thumbnail_quality if thumbnail_quality in f["thumbnail_status"] else "small"
  275. thumb_url = ps.get_thumb_url(f["id"],thumb_quality)
  276. data2 = prefix+f["id"]
  277. item = xbmcgui.ListItem(label, label2, path=data2)
  278. item.setArt({
  279. "thumb": thumb_url,
  280. "icon": thumb_url,
  281. "fanart": thumb_url,
  282. })
  283. item.setLabel2(label2)
  284. item.setInfo(
  285. 'video', {
  286. "title": label,
  287. "plot": f["additional"]["file_location"],
  288. #TODO
  289. }
  290. )
  291. if video_quality == "original":
  292. quality_id = ""
  293. else:
  294. quality_id = f["additional"]["video_quality"][0]["id"]
  295. data2 = ps.get_video_url(oid2, quality_id)
  296. #data2 = urllib.quote(data2, ":/")
  297. item.setProperty("is_folder", "")
  298. item.setProperty('IsPlayable', 'true')
  299. #item.setPath(data2)
  300. item.setProperty("url", data2)
  301. playlist.add(data2, item)
  302. i += 1
  303. xbmc.Player().play(playlist, startpos=pos)
  304. def play_video(streams):
  305. stream = streams[0]
  306. subfiles = []
  307. print "play_video ",stream["url"]
  308. item = ListItem(label=stream["name"], thumbnail=stream["img"], path=stream["url"])
  309. item.set_info("video",{"plot":stream["desc"]})
  310. item.is_folder = False
  311. #item.set_is_playable(True)
  312. #plugin.play_video(item)
  313. item2 = xbmcgui.ListItem("label", "label2", path=stream["url"])
  314. item2.setProperty('IsPlayable', 'true')
  315. xbmc.Player().play(item=stream["url"], listitem=item2)
  316. #xbmcplugin.setResolvedUrl(plugin.handle, True, listitem=item2)
  317. if __name__ == '__main__':
  318. if CLI_MODE:
  319. from kodiswift.cli.cli import main as start
  320. start()
  321. else:
  322. plugin.run()