2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
import xbmc
|
|
|
|
import xbmcplugin
|
|
|
|
import xbmcgui
|
|
|
|
import xbmcaddon
|
|
|
|
import urllib
|
|
|
|
import datetime
|
|
|
|
import time
|
|
|
|
import json as json
|
|
|
|
import inspect
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from DownloadUtils import DownloadUtils
|
|
|
|
from PlayUtils import PlayUtils
|
2015-03-24 18:41:46 +00:00
|
|
|
from ReadKodiDB import ReadKodiDB
|
2015-03-25 16:01:13 +00:00
|
|
|
from ReadEmbyDB import ReadEmbyDB
|
2015-03-28 01:34:09 +00:00
|
|
|
import Utils as utils
|
2015-03-13 21:24:59 +00:00
|
|
|
from API import API
|
|
|
|
import Utils as utils
|
2015-03-22 03:19:26 +00:00
|
|
|
import os
|
|
|
|
import xbmcvfs
|
2015-03-13 21:24:59 +00:00
|
|
|
|
2015-03-25 17:37:21 +00:00
|
|
|
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
2015-03-22 03:19:26 +00:00
|
|
|
addondir = xbmc.translatePath(addon.getAddonInfo('profile'))
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
WINDOW = xbmcgui.Window( 10000 )
|
|
|
|
|
|
|
|
class PlaybackUtils():
|
|
|
|
|
|
|
|
settings = None
|
2015-03-28 01:12:51 +00:00
|
|
|
language = addon.getLocalizedString
|
2015-03-13 21:24:59 +00:00
|
|
|
logLevel = 0
|
2015-03-28 11:16:55 +00:00
|
|
|
downloadUtils = DownloadUtils()
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
def __init__(self, *args):
|
|
|
|
pass
|
|
|
|
|
2015-05-02 21:40:30 +00:00
|
|
|
def PLAY(self, result, setup="service"):
|
2015-04-07 14:21:54 +00:00
|
|
|
xbmc.log("PLAY Called")
|
2015-04-13 18:56:36 +00:00
|
|
|
WINDOW = xbmcgui.Window(10000)
|
|
|
|
|
|
|
|
username = WINDOW.getProperty('currUser')
|
|
|
|
userid = WINDOW.getProperty('userId%s' % username)
|
|
|
|
server = WINDOW.getProperty('server%s' % username)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
2015-05-03 07:24:23 +00:00
|
|
|
try:
|
|
|
|
id = result["Id"]
|
|
|
|
except:
|
|
|
|
return
|
2015-03-13 21:24:59 +00:00
|
|
|
|
2015-06-06 16:19:53 +00:00
|
|
|
userData = result['UserData']
|
|
|
|
resume_result = 0
|
|
|
|
seekTime = 0
|
|
|
|
|
|
|
|
if userData.get("PlaybackPositionTicks") != 0:
|
|
|
|
reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000
|
|
|
|
seekTime = reasonableTicks / 10000
|
|
|
|
|
|
|
|
itemsToPlay = []
|
|
|
|
# Check for intros
|
|
|
|
if seekTime == 0:
|
|
|
|
# if we have any play them when the movie/show is not being resumed
|
|
|
|
# We can add the option right here
|
|
|
|
url = "{server}/mediabrowser/Users/{UserId}/Items/%s/Intros?format=json&ImageTypeLimit=1&Fields=Etag" % id
|
|
|
|
intros = self.downloadUtils.downloadUrl(url)
|
|
|
|
if intros[u'TotalRecordCount'] == 0:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
for intro in intros[u'Items']:
|
|
|
|
introId = intro[u'Id']
|
|
|
|
itemsToPlay.append(introId)
|
|
|
|
|
|
|
|
# Add original item
|
|
|
|
itemsToPlay.append(id)
|
|
|
|
|
2015-05-09 06:44:02 +00:00
|
|
|
# For split movies
|
|
|
|
if u'PartCount' in result:
|
|
|
|
partcount = result[u'PartCount']
|
|
|
|
# Get additional parts/playurl
|
|
|
|
url = "{server}/mediabrowser/Videos/%s/AdditionalParts" % id
|
|
|
|
parts = self.downloadUtils.downloadUrl(url)
|
|
|
|
for part in parts[u'Items']:
|
|
|
|
partId = part[u'Id']
|
2015-06-06 16:19:53 +00:00
|
|
|
itemsToPlay.append(partId)
|
2015-05-02 00:26:06 +00:00
|
|
|
|
2015-06-06 16:19:53 +00:00
|
|
|
if len(itemsToPlay) > 1:
|
|
|
|
# Let's play the playlist
|
|
|
|
return self.AddToPlaylist(itemsToPlay)
|
2015-06-05 14:46:17 +00:00
|
|
|
|
2015-03-13 21:24:59 +00:00
|
|
|
playurl = PlayUtils().getPlayUrl(server, id, result)
|
2015-05-07 06:11:20 +00:00
|
|
|
if playurl == False:
|
2015-05-07 06:50:34 +00:00
|
|
|
#xbmcgui.Dialog().ok('Warning', 'Failed to launch playback.')
|
2015-05-07 06:11:20 +00:00
|
|
|
xbmc.log("Failed to retrieve the playback path/url.")
|
|
|
|
return
|
2015-05-07 06:19:14 +00:00
|
|
|
|
2015-03-14 18:17:16 +00:00
|
|
|
thumbPath = API().getArtwork(result, "Primary")
|
2015-03-22 03:19:26 +00:00
|
|
|
|
2015-05-06 15:02:16 +00:00
|
|
|
#if the file is a virtual strm file, we need to override the path by reading it's contents
|
|
|
|
if playurl.endswith(".strm"):
|
|
|
|
xbmc.log("virtual strm file file detected, starting playback with 3th party addon...")
|
|
|
|
StrmTemp = "special://temp/temp.strm"
|
|
|
|
xbmcvfs.copy(playurl, StrmTemp)
|
|
|
|
playurl = open(xbmc.translatePath(StrmTemp), 'r').readline()
|
|
|
|
|
2015-03-22 03:19:26 +00:00
|
|
|
listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath)
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
# Can not play virtual items
|
|
|
|
if (result.get("LocationType") == "Virtual"):
|
2015-03-28 01:12:51 +00:00
|
|
|
xbmcgui.Dialog().ok(self.language(30128), self.language(30129))
|
2015-03-13 21:24:59 +00:00
|
|
|
|
2015-04-13 18:56:36 +00:00
|
|
|
watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id)
|
|
|
|
positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, id)
|
|
|
|
deleteurl = "%s/mediabrowser/Items/%s" % (server, id)
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
# set the current playing info
|
|
|
|
WINDOW.setProperty(playurl+"watchedurl", watchedurl)
|
|
|
|
WINDOW.setProperty(playurl+"positionurl", positionurl)
|
|
|
|
WINDOW.setProperty(playurl+"deleteurl", "")
|
|
|
|
WINDOW.setProperty(playurl+"deleteurl", deleteurl)
|
|
|
|
|
|
|
|
if result.get("Type")=="Episode":
|
|
|
|
WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId"))
|
|
|
|
else:
|
|
|
|
WINDOW.setProperty(playurl+"refresh_id", id)
|
|
|
|
|
|
|
|
WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks")))
|
|
|
|
WINDOW.setProperty(playurl+"type", result.get("Type"))
|
|
|
|
WINDOW.setProperty(playurl+"item_id", id)
|
|
|
|
|
|
|
|
mediaSources = result.get("MediaSources")
|
|
|
|
if(mediaSources != None):
|
2015-06-08 03:48:28 +00:00
|
|
|
mediaStream = mediaSources[0].get('MediaStreams')
|
|
|
|
defaultsubs = ""
|
|
|
|
for stream in mediaStream:
|
|
|
|
if u'Subtitle' in stream[u'Type'] and stream[u'IsDefault']:
|
2015-06-08 07:31:13 +00:00
|
|
|
if u'Language' in stream:
|
|
|
|
defaultsubs = stream[u'Language']
|
|
|
|
else:
|
|
|
|
defaultsubs = stream[u'Codec']
|
2015-06-08 03:48:28 +00:00
|
|
|
WINDOW.setProperty("%ssubs" % playurl, defaultsubs.encode('utf-8'))
|
2015-03-13 21:24:59 +00:00
|
|
|
if mediaSources[0].get('DefaultAudioStreamIndex') != None:
|
|
|
|
WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0].get('DefaultAudioStreamIndex')))
|
|
|
|
if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
|
|
|
|
WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex')))
|
|
|
|
|
2015-05-06 15:02:16 +00:00
|
|
|
#launch the playback - only set the listitem props if we're not using the setresolvedurl approach
|
2015-05-02 21:40:30 +00:00
|
|
|
if setup == "service":
|
2015-05-06 15:02:16 +00:00
|
|
|
self.setListItemProps(server, id, listItem, result)
|
2015-05-02 21:40:30 +00:00
|
|
|
xbmc.Player().play(playurl,listItem)
|
|
|
|
elif setup == "default":
|
2015-07-20 01:35:14 +00:00
|
|
|
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
def setArt(self, list,name,path):
|
|
|
|
if name=='thumb' or name=='fanart_image' or name=='small_poster' or name=='tiny_poster' or name == "medium_landscape" or name=='medium_poster' or name=='small_fanartimage' or name=='medium_fanartimage' or name=='fanart_noindicators':
|
|
|
|
list.setProperty(name, path)
|
|
|
|
else:
|
|
|
|
list.setArt({name:path})
|
|
|
|
return list
|
|
|
|
|
|
|
|
def setListItemProps(self, server, id, listItem, result):
|
|
|
|
# set up item and item info
|
|
|
|
thumbID = id
|
|
|
|
eppNum = -1
|
|
|
|
seasonNum = -1
|
|
|
|
tvshowTitle = ""
|
|
|
|
|
|
|
|
if(result.get("Type") == "Episode"):
|
|
|
|
thumbID = result.get("SeriesId")
|
|
|
|
seasonNum = result.get("ParentIndexNumber")
|
|
|
|
eppNum = result.get("IndexNumber")
|
|
|
|
tvshowTitle = result.get("SeriesName")
|
|
|
|
|
2015-03-14 18:17:16 +00:00
|
|
|
self.setArt(listItem,'poster', API().getArtwork(result, "Primary"))
|
|
|
|
self.setArt(listItem,'tvshow.poster', API().getArtwork(result, "SeriesPrimary"))
|
|
|
|
self.setArt(listItem,'clearart', API().getArtwork(result, "Art"))
|
|
|
|
self.setArt(listItem,'tvshow.clearart', API().getArtwork(result, "Art"))
|
|
|
|
self.setArt(listItem,'clearlogo', API().getArtwork(result, "Logo"))
|
|
|
|
self.setArt(listItem,'tvshow.clearlogo', API().getArtwork(result, "Logo"))
|
|
|
|
self.setArt(listItem,'discart', API().getArtwork(result, "Disc"))
|
|
|
|
self.setArt(listItem,'fanart_image', API().getArtwork(result, "Backdrop"))
|
|
|
|
self.setArt(listItem,'landscape', API().getArtwork(result, "Thumb"))
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
listItem.setProperty('IsPlayable', 'true')
|
|
|
|
listItem.setProperty('IsFolder', 'false')
|
|
|
|
|
|
|
|
# Process Studios
|
2015-03-14 18:17:16 +00:00
|
|
|
studios = API().getStudios(result)
|
2015-03-18 20:49:49 +00:00
|
|
|
if studios == []:
|
|
|
|
studio = ""
|
|
|
|
else:
|
|
|
|
studio = studios[0]
|
2015-03-13 21:24:59 +00:00
|
|
|
listItem.setInfo('video', {'studio' : studio})
|
|
|
|
|
|
|
|
details = {
|
2015-05-06 15:02:16 +00:00
|
|
|
'title' : result.get("Name", "Missing Name"),
|
2015-03-13 21:24:59 +00:00
|
|
|
'plot' : result.get("Overview")
|
|
|
|
}
|
|
|
|
|
|
|
|
if(eppNum > -1):
|
|
|
|
details["episode"] = str(eppNum)
|
|
|
|
|
|
|
|
if(seasonNum > -1):
|
|
|
|
details["season"] = str(seasonNum)
|
|
|
|
|
|
|
|
if tvshowTitle != None:
|
2015-04-13 18:56:36 +00:00
|
|
|
details["TVShowTitle"] = tvshowTitle
|
2015-03-13 21:24:59 +00:00
|
|
|
|
|
|
|
listItem.setInfo( "Video", infoLabels=details )
|
|
|
|
|
|
|
|
people = API().getPeople(result)
|
|
|
|
|
|
|
|
# Process Genres
|
|
|
|
genre = API().getGenre(result)
|
|
|
|
|
|
|
|
listItem.setInfo('video', {'director' : people.get('Director')})
|
|
|
|
listItem.setInfo('video', {'writer' : people.get('Writer')})
|
|
|
|
listItem.setInfo('video', {'mpaa': result.get("OfficialRating")})
|
2015-05-06 15:02:16 +00:00
|
|
|
listItem.setInfo('video', {'genre': API().getGenre(result)})
|
2015-03-23 04:54:16 +00:00
|
|
|
|
2015-03-28 01:34:09 +00:00
|
|
|
def seekToPosition(self, seekTo):
|
|
|
|
|
|
|
|
#Set a loop to wait for positive confirmation of playback
|
|
|
|
count = 0
|
|
|
|
while not xbmc.Player().isPlaying():
|
|
|
|
count = count + 1
|
|
|
|
if count >= 10:
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
xbmc.sleep(500)
|
|
|
|
|
|
|
|
#Jump to resume point
|
2015-07-20 01:35:14 +00:00
|
|
|
jumpBackSec = int(addon.getSetting("resumeJumpBack"))
|
2015-03-28 01:34:09 +00:00
|
|
|
seekToTime = seekTo - jumpBackSec
|
|
|
|
count = 0
|
|
|
|
while xbmc.Player().getTime() < (seekToTime - 5) and count < 11: # only try 10 times
|
|
|
|
count = count + 1
|
|
|
|
#xbmc.Player().pause
|
|
|
|
#xbmc.sleep(100)
|
|
|
|
xbmc.Player().seekTime(seekToTime)
|
|
|
|
xbmc.sleep(100)
|
|
|
|
#xbmc.Player().play()
|
|
|
|
|
|
|
|
def PLAYAllItems(self, items, startPositionTicks):
|
|
|
|
utils.logMsg("PlayBackUtils", "== ENTER: PLAYAllItems ==")
|
|
|
|
utils.logMsg("PlayBackUtils", "Items : " + str(items))
|
2015-04-13 18:56:36 +00:00
|
|
|
WINDOW = xbmcgui.Window(10000)
|
|
|
|
|
|
|
|
username = WINDOW.getProperty('currUser')
|
|
|
|
userid = WINDOW.getProperty('userId%s' % username)
|
|
|
|
server = WINDOW.getProperty('server%s' % username)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
|
|
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
|
|
|
playlist.clear()
|
|
|
|
started = False
|
|
|
|
|
|
|
|
for itemID in items:
|
|
|
|
|
|
|
|
utils.logMsg("PlayBackUtils", "Adding Item to Playlist : " + itemID)
|
2015-04-25 23:51:07 +00:00
|
|
|
item_url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json" % itemID
|
|
|
|
jsonData = self.downloadUtils.downloadUrl(item_url)
|
2015-04-13 18:56:36 +00:00
|
|
|
|
2015-04-25 23:51:07 +00:00
|
|
|
item_data = jsonData
|
2015-03-28 01:34:09 +00:00
|
|
|
added = self.addPlaylistItem(playlist, item_data, server, userid)
|
|
|
|
if(added and started == False):
|
|
|
|
started = True
|
|
|
|
utils.logMsg("PlayBackUtils", "Starting Playback Pre")
|
|
|
|
xbmc.Player().play(playlist)
|
|
|
|
|
|
|
|
if(started == False):
|
|
|
|
utils.logMsg("PlayBackUtils", "Starting Playback Post")
|
|
|
|
xbmc.Player().play(playlist)
|
|
|
|
|
|
|
|
#seek to position
|
|
|
|
seekTime = 0
|
|
|
|
if(startPositionTicks != None):
|
|
|
|
seekTime = (startPositionTicks / 1000) / 10000
|
|
|
|
|
|
|
|
if seekTime > 0:
|
|
|
|
self.seekToPosition(seekTime)
|
2015-04-07 14:21:54 +00:00
|
|
|
|
|
|
|
def PLAYAllEpisodes(self, items):
|
2015-04-13 18:56:36 +00:00
|
|
|
WINDOW = xbmcgui.Window(10000)
|
|
|
|
|
|
|
|
username = WINDOW.getProperty('currUser')
|
|
|
|
userid = WINDOW.getProperty('userId%s' % username)
|
|
|
|
server = WINDOW.getProperty('server%s' % username)
|
2015-04-07 14:21:54 +00:00
|
|
|
|
|
|
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
|
|
|
playlist.clear()
|
|
|
|
|
|
|
|
for item in items:
|
|
|
|
|
2015-04-25 23:51:07 +00:00
|
|
|
item_url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json&ImageTypeLimit=1" % item["Id"]
|
|
|
|
jsonData = self.downloadUtils.downloadUrl(item_url)
|
2015-04-07 14:21:54 +00:00
|
|
|
|
2015-04-25 23:51:07 +00:00
|
|
|
item_data = jsonData
|
2015-04-07 14:21:54 +00:00
|
|
|
self.addPlaylistItem(playlist, item_data, server, userid)
|
|
|
|
|
|
|
|
xbmc.Player().play(playlist)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
|
|
|
def AddToPlaylist(self, itemIds):
|
|
|
|
utils.logMsg("PlayBackUtils", "== ENTER: PLAYAllItems ==")
|
2015-04-13 18:56:36 +00:00
|
|
|
WINDOW = xbmcgui.Window(10000)
|
|
|
|
|
|
|
|
username = WINDOW.getProperty('currUser')
|
|
|
|
userid = WINDOW.getProperty('userId%s' % username)
|
|
|
|
server = WINDOW.getProperty('server%s' % username)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
|
|
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
|
|
|
|
|
|
|
for itemID in itemIds:
|
|
|
|
|
|
|
|
utils.logMsg("PlayBackUtils", "Adding Item to Playlist : " + itemID)
|
2015-04-25 23:51:07 +00:00
|
|
|
item_url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json" % itemID
|
|
|
|
jsonData = self.downloadUtils.downloadUrl(item_url)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
2015-04-25 23:51:07 +00:00
|
|
|
item_data = jsonData
|
2015-03-28 01:34:09 +00:00
|
|
|
self.addPlaylistItem(playlist, item_data, server, userid)
|
|
|
|
|
|
|
|
return playlist
|
|
|
|
|
|
|
|
def addPlaylistItem(self, playlist, item, server, userid):
|
|
|
|
|
|
|
|
id = item.get("Id")
|
|
|
|
|
|
|
|
playurl = PlayUtils().getPlayUrl(server, id, item)
|
|
|
|
utils.logMsg("PlayBackUtils", "Play URL: " + playurl)
|
|
|
|
thumbPath = API().getArtwork(item, "Primary")
|
|
|
|
listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath)
|
|
|
|
self.setListItemProps(server, id, listItem, item)
|
|
|
|
|
2015-04-13 18:56:36 +00:00
|
|
|
WINDOW = xbmcgui.Window(10000)
|
|
|
|
|
|
|
|
username = WINDOW.getProperty('currUser')
|
|
|
|
userid = WINDOW.getProperty('userId%s' % username)
|
|
|
|
server = WINDOW.getProperty('server%s' % username)
|
|
|
|
|
2015-03-28 01:34:09 +00:00
|
|
|
# Can not play virtual items
|
|
|
|
if (item.get("LocationType") == "Virtual") or (item.get("IsPlaceHolder") == True):
|
|
|
|
|
|
|
|
xbmcgui.Dialog().ok(self.language(30128), self.language(30129))
|
|
|
|
return False
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
2015-04-13 18:56:36 +00:00
|
|
|
watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id)
|
|
|
|
positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, id)
|
|
|
|
deleteurl = "%s/mediabrowser/Items/%s" % (server, id)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
|
|
|
# set the current playing info
|
|
|
|
WINDOW = xbmcgui.Window( 10000 )
|
|
|
|
WINDOW.setProperty(playurl + "watchedurl", watchedurl)
|
|
|
|
WINDOW.setProperty(playurl + "positionurl", positionurl)
|
|
|
|
WINDOW.setProperty(playurl + "deleteurl", "")
|
|
|
|
|
2015-07-04 15:04:04 +00:00
|
|
|
if item.get("Type") == "Episode" and addon.getSetting("offerDeleteTV")=="true":
|
2015-03-28 01:34:09 +00:00
|
|
|
WINDOW.setProperty(playurl + "deleteurl", deleteurl)
|
2015-07-04 15:04:04 +00:00
|
|
|
if item.get("Type") == "Movie" and addon.getSetting("offerDeleteMovies")=="true":
|
2015-07-20 01:35:14 +00:00
|
|
|
WINDOW.setProperty(playurl + "deleteurl", deleteurl)
|
2015-03-28 01:34:09 +00:00
|
|
|
|
|
|
|
WINDOW.setProperty(playurl + "runtimeticks", str(item.get("RunTimeTicks")))
|
|
|
|
WINDOW.setProperty(playurl+"type", item.get("Type"))
|
|
|
|
WINDOW.setProperty(playurl + "item_id", id)
|
|
|
|
|
|
|
|
if (item.get("Type") == "Episode"):
|
|
|
|
WINDOW.setProperty(playurl + "refresh_id", item.get("SeriesId"))
|
|
|
|
else:
|
|
|
|
WINDOW.setProperty(playurl + "refresh_id", id)
|
|
|
|
|
|
|
|
utils.logMsg("PlayBackUtils", "PlayList Item Url : " + str(playurl))
|
|
|
|
|
|
|
|
playlist.add(playurl, listItem)
|
|
|
|
|
2015-03-28 11:16:55 +00:00
|
|
|
return True
|