# Gnu General Public License - see LICENSE.TXT import xbmcaddon import xbmcgui import xbmcplugin import xbmc import string import random import urllib import json import binascii import time from datetime import datetime import _strptime import calendar import re from .downloadutils import DownloadUtils from .simple_logging import SimpleLogging from .clientinfo import ClientInformation # hack to get datetime strptime loaded throwaway = time.strptime('20110101','%Y%m%d') # define our global download utils downloadUtils = DownloadUtils() log = SimpleLogging(__name__) def get_emby_url(base_url, params): params["format"] = "json" param_list = [] for key in params: if params[key] is not None: param_list.append(key + "=" + str(params[key])) param_string = "&".join(param_list) return base_url + "?" + param_string ########################################################################### class PlayUtils(): def getPlayUrl(self, id, media_source, force_transcode, play_session_id): log.debug("getPlayUrl") addonSettings = xbmcaddon.Addon() playback_type = addonSettings.getSetting("playback_type") server = downloadUtils.getServer() use_https = False if addonSettings.getSetting('protocol') == "1": use_https = True log.debug("use_https: {0}", use_https) verify_cert = addonSettings.getSetting('verify_cert') == 'true' log.debug("verify_cert: {0}", verify_cert) log.debug("playback_type: {0}", playback_type) if force_transcode: log.debug("playback_type: FORCED_TRANSCODE") playurl = None log.debug("play_session_id: {0}", play_session_id) media_source_id = media_source.get("Id") log.debug("media_source_id: {0}", media_source_id) force_transcode_codecs = [] if addonSettings.getSetting("force_transcode_h265") == "true": force_transcode_codecs.append("hevc") force_transcode_codecs.append("h265") if addonSettings.getSetting("force_transcode_mpeg2") == "true": force_transcode_codecs.append("mpeg2video") if addonSettings.getSetting("force_transcode_msmpeg4v3") == "true": force_transcode_codecs.append("msmpeg4v3") if addonSettings.getSetting("force_transcode_mpeg4") == "true": force_transcode_codecs.append("mpeg4") if len(force_transcode_codecs) > 0: codec_force_transcode = False codec_name = "" streams = media_source.get("MediaStreams", []) for stream in streams: if stream.get("Type", "") == "Video": codec_name = stream.get("Codec", "").lower() if codec_name in force_transcode_codecs: codec_force_transcode = True break if codec_force_transcode: log.debug("codec_force_transcode: {0}", codec_name) playback_type = "2" if force_transcode: playback_type = "2" # transcode if playback_type == "2": playback_bitrate = addonSettings.getSetting("playback_bitrate") log.debug("playback_bitrate: {0}", playback_bitrate) playback_max_width = addonSettings.getSetting("playback_max_width") playback_video_force_8 = addonSettings.getSetting("playback_video_force_8") == "true" clientInfo = ClientInformation() deviceId = clientInfo.getDeviceId() bitrate = int(playback_bitrate) * 1000 user_token = downloadUtils.authenticate() playurl = ("%s/emby/Videos/%s/master.m3u8" + "?MediaSourceId=%s" + "&PlaySessionId=%s" + "&VideoCodec=h264" + "&AudioCodec=ac3" + "&MaxAudioChannels=6" + "&deviceId=%s" + "&VideoBitrate=%s" + "&maxWidth=%s") playurl = playurl % (server, id, media_source_id, play_session_id, deviceId, bitrate, playback_max_width) if playback_video_force_8: playurl += "&MaxVideoBitDepth=8" playurl += "&api_key=" + user_token if use_https and not verify_cert: playurl += "|verifypeer=false" # do direct path playback elif playback_type == "0": playurl = media_source.get("Path") playurl = playurl.replace("\\", "/") playurl = playurl.strip() # handle DVD structure if media_source.get("VideoType") == "Dvd": playurl = playurl + "/VIDEO_TS/VIDEO_TS.IFO" elif media_source.get("VideoType") == "BluRay": playurl = playurl + "/BDMV/index.bdmv" if playurl.startswith("//"): smb_username = addonSettings.getSetting('smbusername') smb_password = addonSettings.getSetting('smbpassword') if not smb_username: playurl = "smb://" + playurl[2:] else: playurl = "smb://" + smb_username + ':' + smb_password + '@' + playurl[2:] # do direct http streaming playback elif playback_type == "1": playurl = ("%s/emby/Videos/%s/stream" + "?static=true" + "&PlaySessionId=%s" + "&MediaSourceId=%s") playurl = playurl % (server, id, play_session_id, media_source_id) user_token = downloadUtils.authenticate() playurl += "&api_key=" + user_token if use_https and not verify_cert: playurl += "|verifypeer=false" log.debug("Playback URL: {0}", playurl) return playurl, playback_type def getStrmDetails(self, media_source): playurl = None listitem_props = [] contents = media_source.get('Path').encode('utf-8') # contains contents of strm file with linebreaks line_break = '\r' if '\r\n' in contents: line_break = '\r\n' elif '\n' in contents: line_break = '\n' lines = contents.split(line_break) for line in lines: line = line.strip() log.debug("STRM Line: {0}", line) if line.startswith('#KODIPROP:'): match = re.search('#KODIPROP:(?P[^=]+?)=(?P.+)', line) if match: item_property = match.group('item_property') property_value = match.group('property_value') log.debug("STRM property found: {0} value: {1}", item_property, property_value) listitem_props.append((item_property, property_value)) else: log.debug("STRM #KODIPROP incorrect format") elif line.startswith('#'): # unrecognized, treat as comment log.debug("STRM unrecognized line identifier, ignored") elif line != '': playurl = line log.debug("STRM playback url found") log.debug("Playback URL: {0} ListItem Properties: {1}", playurl, listitem_props) return playurl, listitem_props def getChecksum(item): userdata = item['UserData'] checksum = "%s_%s_%s_%s_%s_%s_%s" % ( item['Etag'], userdata['Played'], userdata['IsFavorite'], userdata.get('Likes', "-"), userdata['PlaybackPositionTicks'], userdata.get('UnplayedItemCount', "-"), userdata.get("PlayedPercentage", "-") ) return checksum def getArt(item, server): art = { 'thumb': '', 'fanart': '', 'poster': '', 'banner': '', 'clearlogo': '', 'clearart': '', 'discart': '', 'landscape': '', 'tvshow.fanart': '', 'tvshow.poster': '', 'tvshow.clearart': '', 'tvshow.clearlogo': '', 'tvshow.banner': '', 'tvshow.landscape': '' } item_id = item["Id"] image_id = item_id imageTags = item["ImageTags"] if imageTags is not None and imageTags["Primary"] is not None: image_tag = imageTags["Primary"] art['thumb'] = downloadUtils.getArtwork(item, "Primary", server=server) item_type = item["Type"] if item_type == "Genre": art['poster'] = downloadUtils.getArtwork(item, "Primary", server=server) elif item_type == "Episode": art['tvshow.poster'] = downloadUtils.getArtwork(item, "Primary", parent=True, server=server) #art['poster'] = downloadUtils.getArtwork(item, "Primary", parent=True, server=server) art['tvshow.clearart'] = downloadUtils.getArtwork(item, "Art", parent=True, server=server) art['clearart'] = downloadUtils.getArtwork(item, "Art", parent=True, server=server) art['tvshow.clearlogo'] = downloadUtils.getArtwork(item, "Logo", parent=True, server=server) art['clearlogo'] = downloadUtils.getArtwork(item, "Logo", parent=True, server=server) art['tvshow.banner'] = downloadUtils.getArtwork(item, "Banner", parent=True, server=server) art['banner'] = downloadUtils.getArtwork(item, "Banner", parent=True, server=server) art['tvshow.landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=True, server=server) art['landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=True, server=server) art['tvshow.fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=True, server=server) art['fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=True, server=server) elif item_type == "Season": art['tvshow.poster'] = downloadUtils.getArtwork(item, "Primary", parent=True, server=server) art['season.poster'] = downloadUtils.getArtwork(item, "Primary", parent=False, server=server) art['poster'] = downloadUtils.getArtwork(item, "Primary", parent=False, server=server) art['tvshow.clearart'] = downloadUtils.getArtwork(item, "Art", parent=True, server=server) art['clearart'] = downloadUtils.getArtwork(item, "Art", parent=True, server=server) art['tvshow.clearlogo'] = downloadUtils.getArtwork(item, "Logo", parent=True, server=server) art['clearlogo'] = downloadUtils.getArtwork(item, "Logo", parent=True, server=server) art['tvshow.banner'] = downloadUtils.getArtwork(item, "Banner", parent=True, server=server) art['season.banner'] = downloadUtils.getArtwork(item, "Banner", parent=False, server=server) art['banner'] = downloadUtils.getArtwork(item, "Banner", parent=False, server=server) art['tvshow.landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=True, server=server) art['season.landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=False, server=server) art['landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=False, server=server) art['tvshow.fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=True, server=server) art['fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=True, server=server) elif item_type == "Series": art['tvshow.poster'] = downloadUtils.getArtwork(item, "Primary", parent=False, server=server) art['poster'] = downloadUtils.getArtwork(item, "Primary", parent=False, server=server) art['tvshow.clearart'] = downloadUtils.getArtwork(item, "Art", parent=False, server=server) art['clearart'] = downloadUtils.getArtwork(item, "Art", parent=False, server=server) art['tvshow.clearlogo'] = downloadUtils.getArtwork(item, "Logo", parent=False, server=server) art['clearlogo'] = downloadUtils.getArtwork(item, "Logo", parent=False, server=server) art['tvshow.banner'] = downloadUtils.getArtwork(item, "Banner", parent=False, server=server) art['banner'] = downloadUtils.getArtwork(item, "Banner", parent=False, server=server) art['tvshow.landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=False, server=server) art['landscape'] = downloadUtils.getArtwork(item, "Thumb", parent=False, server=server) art['tvshow.fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=False, server=server) art['fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=False, server=server) elif item_type == "Movie" or item_type == "BoxSet": art['poster'] = downloadUtils.getArtwork(item, "Primary", server=server) art['landscape'] = downloadUtils.getArtwork(item, "Thumb", server=server) art['banner'] = downloadUtils.getArtwork(item, "Banner", server=server) art['clearlogo'] = downloadUtils.getArtwork(item, "Logo", server=server) art['clearart'] = downloadUtils.getArtwork(item, "Art", server=server) art['discart'] = downloadUtils.getArtwork(item, "Disc", server=server) art['fanart'] = downloadUtils.getArtwork(item, "Backdrop", server=server) if not art['fanart']: art['fanart'] = downloadUtils.getArtwork(item, "Backdrop", parent=True, server=server) return art def id_generator(size=6, chars=string.ascii_uppercase + string.digits): return ''.join(random.choice(chars) for _ in range(size)) def double_urlencode(text): text = single_urlencode(text) text = single_urlencode(text) return text def single_urlencode(text): # urlencode needs a utf- string text = urllib.urlencode({'blahblahblah': text.encode('utf-8')}) text = text[13:] return text.decode('utf-8') #return the result again as unicode def send_event_notification(method, data): next_data = json.dumps(data) source_id = "embycon" data = '\\"[\\"{0}\\"]\\"'.format(binascii.hexlify(next_data)) command = 'XBMC.NotifyAll({0}.SIGNAL,{1},{2})'.format(source_id, method, data) log.debug("Sending notification event data: {0}", command) xbmc.executebuiltin(command) def datetime_from_string(time_string): if time_string[-1:] == "Z": time_string = re.sub("[0-9]{1}Z", " UTC", time_string) elif time_string[-6:] == "+00:00": time_string = re.sub("[0-9]{1}\+00:00", " UTC", time_string) log.debug("New Time String : {0}", time_string) start_time = time.strptime(time_string, "%Y-%m-%dT%H:%M:%S.%f %Z") dt = datetime(*(start_time[0:6])) timestamp = calendar.timegm(dt.timetuple()) local_dt = datetime.fromtimestamp(timestamp) local_dt.replace(microsecond=dt.microsecond) return local_dt