diff options
Diffstat (limited to 'plugin.video.embycon/resources/lib/item_functions.py')
-rw-r--r-- | plugin.video.embycon/resources/lib/item_functions.py | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/plugin.video.embycon/resources/lib/item_functions.py b/plugin.video.embycon/resources/lib/item_functions.py new file mode 100644 index 0000000..3818613 --- /dev/null +++ b/plugin.video.embycon/resources/lib/item_functions.py @@ -0,0 +1,556 @@ + +import sys +import os +import urllib +import json +from collections import defaultdict + +import xbmc +import xbmcaddon +import xbmcgui + +from utils import getArt +from simple_logging import SimpleLogging +from translation import i18n +from downloadutils import DownloadUtils +from datamanager import DataManager + +log = SimpleLogging(__name__) +kodi_version = int(xbmc.getInfoLabel('System.BuildVersion')[:2]) + +addon_instance = xbmcaddon.Addon(id='plugin.video.embycon') +addon_path = addon_instance.getAddonInfo('path') +PLUGINPATH = xbmc.translatePath(os.path.join(addon_path)) + +download_utils = DownloadUtils() + +class ItemDetails(): + + name = None + id = None + path = None + is_folder = False + plot = None + series_name = None + episode_number = 0 + season_number = 0 + track_number = 0 + + art = None + + mpaa = None + rating = None + critic_rating = 0.0 + year = None + premiere_date = "" + date_added = "" + location_type = None + studio = None + genre = "" + play_count = 0 + director = "" + writer = "" + channels = "" + video_codec = "" + aspect_ratio = 0.0 + audio_codec = "" + height = 0 + width = 0 + cast = None + + resume_time = 0 + duration = 0 + recursive_item_count = 0 + recursive_unplayed_items_count = 0 + total_seasons = 0 + total_episodes = 0 + watched_episodes = 0 + unwatched_episodes = 0 + number_episodes = 0 + original_title = None + item_type = None + subtitle_lang = "" + subtitle_available = False + + song_artist = "" + album_artist = "" + album_name = "" + + favorite = "false" + overlay = "0" + + name_format = "" + mode = "" + +def extract_item_info(item, gui_options): + + item_details = ItemDetails() + + item_details.id = item["Id"] + item_details.is_folder = item["IsFolder"] + item_details.item_type = item["Type"] + item_details.location_type = item["LocationType"] + item_details.name = item["Name"] + item_details.original_title = item_details.name + + if item_details.item_type == "Episode": + item_details.episode_number = item["IndexNumber"] + + if item_details.item_type == "Episode": + item_details.season_number = item["ParentIndexNumber"] + elif item_details.item_type == "Season": + item_details.season_number = item["IndexNumber"] + + if item_details.season_number is None: + item_details.season_number = 0 + if item_details.episode_number is None: + item_details.episode_number = 0 + + if item_details.item_type == "Audio": + item_details.track_number = item["IndexNumber"] + item_details.album_name = item["Album"] + artists = item["Artists"] + if artists is not None and len(artists) > 0: + item_details.song_artist = artists[0] # get first artist + + if item_details.item_type == "MusicAlbum": + item_details.album_artist = item["AlbumArtist"] + item_details.album_name = item_details.name + + # set the item name + # override with name format string from request + name_format = gui_options["name_format"] + name_format_type = gui_options["name_format_type"] + + if name_format is not None and item_details.item_type == name_format_type: + nameInfo = {} + nameInfo["ItemName"] = item["Name"] + season_name = item["SeriesName"] + if season_name: + nameInfo["SeriesName"] = season_name + else: + nameInfo["SeriesName"] = "" + nameInfo["SeasonIndex"] = u"%02d" % item_details.season_number + nameInfo["EpisodeIndex"] = u"%02d" % item_details.episode_number + log.debug("FormatName: {0} | {1}", name_format, nameInfo) + item_details.name = unicode(name_format).format(**nameInfo).strip() + + year = item["ProductionYear"] + prem_date = item["PremiereDate"] + + if year is not None: + item_details.year = year + elif item_details.year is None and prem_date is not None: + item_details.year = int(prem_date[:4]) + + if prem_date is not None: + tokens = prem_date.split("T") + item_details.premiere_date = tokens[0] + + create_date = item["DateCreated"] + if create_date is not None: + item_details.date_added = create_date.split('.')[0].replace('T', " ") + + # add the premiered date for Upcoming TV + if item_details.location_type == "Virtual": + airtime = item["AirTime"] + item_details.name = item_details.name + ' - ' + item_details.premiere_date + ' - ' + str(airtime) + + # Process MediaStreams + mediaStreams = item["MediaStreams"] + if mediaStreams is not None: + for mediaStream in mediaStreams: + stream_type = mediaStream["Type"] + if stream_type == "Video": + item_details.video_codec = mediaStream["Codec"] + item_details.height = mediaStream["Height"] + item_details.width = mediaStream["Width"] + aspect = mediaStream["AspectRatio"] + if aspect is not None and len(aspect) >= 3: + try: + aspect_width, aspect_height = aspect.split(':') + item_details.aspect_ratio = float(aspect_width) / float(aspect_height) + except: + item_details.aspect_ratio = 1.85 + if stream_type == "Audio": + item_details.audio_codec = mediaStream["Codec"] + item_details.channels = mediaStream["Channels"] + if stream_type == "Subtitle": + item_details.subtitle_available = True + sub_lang = mediaStream["Language"] + if sub_lang is not None: + item_details.subtitle_lang = sub_lang + + # Process People + people = item["People"] + if people is not None: + cast = [] + for person in people: + person_type = person["Type"] + if person_type == "Director": + item_details.director = item_details.director + person["Name"] + ' ' + elif person_type == "Writing": + item_details.writer = person["Name"] + elif person_type == "Actor": + log.debug("Person: {0}", person) + person_name = person["Name"] + person_role = person["Role"] + person_id = person["Id"] + person_tag = person["PrimaryImageTag"] + if person_tag is not None: + person_thumbnail = download_utils.imageUrl(person_id, "Primary", 0, 400, 400, person_tag, server = gui_options["server"]) + else: + person_thumbnail = "" + person = {"name": person_name, "role": person_role, "thumbnail": person_thumbnail} + cast.append(person) + item_details.cast = cast + + # Process Studios + studios = item["Studios"] + if studios is not None: + for studio in studios: + if item_details.studio == "": # Just take the first one + studio_name = studio["Name"] + item_details.studio = studio_name + break + + # Process Genres + genres = item["Genres"] + if genres is not None: + for genre in genres: + item_details.genre = item_details.genre + " / " + genre + + # Process UserData + userData = item["UserData"] + if userData is None: + userData = defaultdict(lambda: None, {}) + + if userData["Played"] == True: + item_details.overlay = "6" + item_details.play_count = 1 + else: + item_details.overlay = "7" + item_details.play_count = 0 + + if userData["IsFavorite"] == True: + item_details.overlay = "5" + item_details.favorite = "true" + else: + item_details.favorite = "false" + + reasonableTicks = userData["PlaybackPositionTicks"] + if reasonableTicks is not None: + reasonableTicks = int(reasonableTicks) / 1000 + item_details.resume_time = int(reasonableTicks / 10000) + + item_details.series_name = item["SeriesName"] + item_details.plot = item["Overview"] + + runtime = item["RunTimeTicks"] + if item_details.is_folder == False and runtime is not None: + item_details.duration = long(runtime) / 10000000 + + child_count = item["ChildCount"] + if child_count is not None: + item_details.total_seasons = child_count + + recursive_item_count = item["RecursiveItemCount"] + if recursive_item_count is not None: + item_details.total_episodes = recursive_item_count + + unplayed_item_count = userData["UnplayedItemCount"] + if unplayed_item_count is not None: + item_details.unwatched_episodes = unplayed_item_count + item_details.watched_episodes = item_details.total_episodes - unplayed_item_count + + item_details.number_episodes = item_details.total_episodes + + item_details.art = getArt(item, gui_options["server"]) + item_details.rating = item["OfficialRating"] + item_details.mpaa = item["OfficialRating"] + item_details.critic_rating = item["CommunityRating"] + if item_details.critic_rating is None: + item_details.critic_rating = 0.0 + item_details.location_type = item["LocationType"] + item_details.recursive_item_count = item["RecursiveItemCount"] + item_details.recursive_unplayed_items_count = userData["UnplayedItemCount"] + + item_details.mode = "GET_CONTENT" + + return item_details + +def add_gui_item(url, item_details, display_options, folder=True): + + log.debug("Passed item_details: {0}", item_details.__dict__) + + if not item_details.name: + return + + if item_details.mode: + mode = "&mode=%s" % item_details.mode + else: + mode = "&mode=0" + + # Create the URL to pass to the item + if folder: + u = sys.argv[0] + "?url=" + urllib.quote(url) + mode + "&media_type=" + item_details.item_type + if item_details.name_format: + u += '&name_format=' + urllib.quote(item_details.name_format) + else: + u = sys.argv[0] + "?item_id=" + url + "&mode=PLAY" + + # Create the ListItem that will be displayed + thumbPath = item_details.art["thumb"] + + listItemName = item_details.name + item_type = item_details.item_type.lower() + is_video = item_type not in ['musicalbum', 'audio', 'music'] + + # calculate percentage + cappedPercentage = 0 + if item_details.resume_time > 0: + duration = float(item_details.duration) + if (duration > 0): + resume = float(item_details.resume_time) + percentage = int((resume / duration) * 100.0) + cappedPercentage = percentage + + totalItems = item_details.total_episodes + if totalItems != 0: + watched = float(item_details.watched_episodes) + percentage = int((watched / float(totalItems)) * 100.0) + cappedPercentage = percentage + + countsAdded = False + addCounts = display_options["addCounts"] + if addCounts and item_details.unwatched_episodes != 0: + countsAdded = True + listItemName = listItemName + (" (%s)" % item_details.unwatched_episodes) + + addResumePercent = display_options["addResumePercent"] + if (not countsAdded + and addResumePercent + and cappedPercentage not in [0, 100]): + listItemName = listItemName + (" (%s%%)" % cappedPercentage) + + subtitle_available = display_options["addSubtitleAvailable"] + if subtitle_available and item_details.subtitle_available: + listItemName += " (cc)" + + if kodi_version > 17: + list_item = xbmcgui.ListItem(listItemName, offscreen=True) + else: + list_item = xbmcgui.ListItem(listItemName, iconImage=thumbPath, thumbnailImage=thumbPath) + + log.debug("Setting thumbnail as: {0}", thumbPath) + + # calculate percentage + if (cappedPercentage != 0): + list_item.setProperty("complete_percentage", str(cappedPercentage)) + + list_item.setProperty('IsPlayable', 'false') + + if folder == False and is_video: + list_item.setProperty('TotalTime', str(item_details.duration)) + list_item.setProperty('ResumeTime', str(item_details.resume_time)) + + list_item.setArt(item_details.art) + + list_item.setProperty('fanart_image', item_details.art['fanart']) # back compat + list_item.setProperty('discart', item_details.art['discart']) # not avail to setArt + list_item.setProperty('tvshow.poster', item_details.art['tvshow.poster']) # not avail to setArt + + # add context menu + menu_items = add_context_menu(item_details, folder) + if len(menu_items) > 0: + list_item.addContextMenuItems(menu_items, True) + + # new way + info_labels = {} + + # add cast + if item_details.cast is not None: + if kodi_version >= 17: + list_item.setCast(item_details.cast) + else: + info_labels['cast'] = info_labels['castandrole'] = [(cast_member['name'], cast_member['role']) for cast_member in item_details.cast] + + info_labels["title"] = listItemName + info_labels["plot"] = item_details.plot + info_labels["Overlay"] = item_details.overlay + info_labels["playcount"] = str(item_details.play_count) + info_labels["TVShowTitle"] = item_details.series_name + + info_labels["duration"] = item_details.duration + info_labels["playcount"] = item_details.play_count + if item_details.favorite == 'true': + info_labels["top250"] = "1" + + info_labels["mpaa"] = item_details.mpaa + info_labels["rating"] = item_details.rating + info_labels["director"] = item_details.director + info_labels["writer"] = item_details.writer + info_labels["year"] = item_details.year + info_labels["premiered"] = item_details.premiere_date + info_labels["dateadded"] = item_details.date_added + info_labels["studio"] = item_details.studio + info_labels["genre"] = item_details.genre + + mediatype = 'video' + + if item_type == 'movie': + mediatype = 'movie' + elif item_type == 'boxset': + mediatype = 'set' + elif item_type == 'series': + mediatype = 'tvshow' + elif item_type == 'season': + mediatype = 'season' + elif item_type == 'episode': + mediatype = 'episode' + elif item_type == 'musicalbum': + mediatype = 'album' + elif item_type == 'musicartist': + mediatype = 'artist' + elif item_type == 'audio' or item_type == 'music': + mediatype = 'song' + + info_labels["mediatype"] = mediatype + + if mediatype == 'episode': + info_labels["episode"] = item_details.episode_number + + if (mediatype == 'season') or (mediatype == 'episode'): + info_labels["season"] = item_details.season_number + + if is_video: + list_item.setInfo('video', info_labels) + log.debug("info_labels: {0}", info_labels) + list_item.addStreamInfo('video', + {'duration': item_details.duration, + 'aspect': item_details.aspect_ratio, + 'codec': item_details.video_codec, + 'width': item_details.width, + 'height': item_details.height}) + list_item.addStreamInfo('audio', + {'codec': item_details.audio_codec, + 'channels': item_details.channels}) + + list_item.setProperty('TotalSeasons', str(item_details.total_seasons)) + list_item.setProperty('TotalEpisodes', str(item_details.total_episodes)) + list_item.setProperty('WatchedEpisodes', str(item_details.watched_episodes)) + list_item.setProperty('UnWatchedEpisodes', str(item_details.unwatched_episodes)) + list_item.setProperty('NumEpisodes', str(item_details.number_episodes)) + + if item_details.subtitle_lang != '': + list_item.addStreamInfo('subtitle', {'language': item_details.subtitle_lang}) + + list_item.setRating("imdb", item_details.critic_rating, 0, True) + list_item.setProperty('TotalTime', str(item_details.duration)) + + else: + info_labels["tracknumber"] = item_details.track_number + if item_details.album_artist: + info_labels["artist"] = item_details.album_artist + elif item_details.song_artist: + info_labels["artist"] = item_details.song_artist + info_labels["album"] = item_details.album_name + + log.debug("info_labels: {0}", info_labels) + list_item.setInfo('music', info_labels) + + list_item.setContentLookup(False) + list_item.setProperty('ItemType', item_details.item_type) + list_item.setProperty('id', item_details.id) + + return (u, list_item, folder) + + +def add_context_menu(item_details, folder): + commands = [] + + if item_details.id is None: + return commands + + scriptToRun = PLUGINPATH + "/default.py" + + if item_details.item_type == "Season" or item_details.item_type == "MusicAlbum": + argsToPass = "?mode=PLAY&item_id=" + item_details.id + commands.append((i18n('play_all'), "RunPlugin(plugin://plugin.video.embycon" + argsToPass + ")")) + + if not folder: + argsToPass = "?mode=PLAY&item_id=" + item_details.id + "&force_transcode=true" + commands.append((i18n('emby_force_transcode'), "RunPlugin(plugin://plugin.video.embycon" + argsToPass + ")")) + + if not folder and item_details.item_type == "Movie": + argsToPass = "?mode=playTrailer&id=" + item_details.id + commands.append((i18n('play_trailer'), "RunPlugin(plugin://plugin.video.embycon" + argsToPass + ")")) + + # watched/unwatched + if item_details.play_count == 0: + argsToPass = 'markWatched,' + item_details.id + commands.append((i18n('emby_mark_watched'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + else: + argsToPass = 'markUnwatched,' + item_details.id + commands.append((i18n('emby_mark_unwatched'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + + # favourite add/remove + if item_details.favorite == 'false': + argsToPass = 'markFavorite,' + item_details.id + commands.append((i18n('emby_set_favorite'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + else: + argsToPass = 'unmarkFavorite,' + item_details.id + commands.append((i18n('emby_unset_favorite'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + + # delete + argsToPass = 'delete,' + item_details.id + commands.append((i18n('emby_delete'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + + return commands + + +def get_next_episode(item): + + if item.get("Type", "na") != "Episode": + log.debug("Not an episode, can not get next") + return None + + parendId = item.get("ParentId", "na") + item_index = item.get("IndexNumber", -1) + + if parendId == "na": + log.debug("No parent id, can not get next") + return None + + if item_index == -1: + log.debug("No episode number, can not get next") + return None + + url = ( '{server}/emby/Users/{userid}/Items?' + + '?Recursive=true' + + '&ParentId=' + parendId + + '&IsVirtualUnaired=false' + + '&IsMissing=False' + + '&IncludeItemTypes=Episode' + + '&ImageTypeLimit=1' + + '&format=json') + + data_manager = DataManager() + items_result = data_manager.GetContent(url) + log.debug("get_next_episode, sibling list: {0}", items_result) + + if items_result is None: + log.debug("get_next_episode no results") + return None + + item_list = items_result.get("Items", []) + + for item in item_list: + index = item.get("IndexNumber", -1) + # find the very next episode in the season + if index == item_index + 1: + log.debug("get_next_episode, found next episode: {0}", item) + return item + + return None + |