def get_listitem(name="", icon="", fanart="", channel={}, no_puls4=True): if channel: listitem = ListItem(channel["name"]) listitem.setProperty('IsPlayable', 'true') if no_puls4: listitem.setLabel(listitem.getLabel().replace("Puls4 ", "")) images = json.loads(channel["images_json"]) if images: if "image_base" in images and images["image_base"]: listitem.setArt({'icon':images["image_base"], 'thumb':images["image_base"], 'poster':images["image_base"]}) else: listitem.setArt({'icon':images["icon_1"], 'thumb':images["icon_1"], 'poster':images["icon_1"]}) if "next_program" in channel: #'Title': channel["name"] listitem.setInfo(type='Video', infoLabels={'Title': listitem.getLabel(), 'Plot': channel["next_program"]["name"]+'[CR]'+channel["next_program"]["description"], 'mediatype': 'video'}) program_images = json.loads(channel["next_program"]["images_json"]) if program_images: listitem.setArt({'fanart' : program_images["image_base"]}) else: listitem = ListItem(name) listitem.setProperty('IsPlayable', 'true') listitem.setInfo(type='Video', infoLabels={'mediatype': 'video'}) if icon != "": listitem.setArt({'icon':icon, 'thumb':icon, 'poster':icon}) if fanart != "": listitem.setArt({'fanart':fanart}) return listitem
def _add_listitem(self, parsed_item): # type: (ParsedItem) -> None is_folder = parsed_item.url.get("mode") == "collection" _LOGGER.debug("Add ListItem %s", parsed_item) listitem = ListItem(label=self._localize(parsed_item.label), offscreen=True) if not parsed_item.info.get("plot"): parsed_item.info["plot"] = listitem.getLabel() listitem.setInfo("video", parsed_item.info) # Set fallback fanart parsed_item.art.setdefault("fanart", self._ADDON_FANART) listitem.setArt(parsed_item.art) # Add context menu for alternate stream versions if parsed_item.url.get("mode") == "watch": self._add_video_context_menu(listitem, str(parsed_item.url["id"])) for key, value in list(parsed_item.properties.items()): listitem.setProperty(key, value) xbmcplugin.addDirectoryItem( self._handle, update_url_params(self._base_url, **parsed_item.url), listitem, isFolder=is_folder, )
def toFileItem(plexServer, plexItem, mediaType=None, plexLibType=None): # determine the matching Plex library type if possible checkMediaType = mediaType is not None if checkMediaType and not plexLibType: mappedMediaType = Api.getPlexMediaType(mediaType) if not mappedMediaType: log( 'cannot import unsupported media type "{}"'.format( mediaType), xbmc.LOGERROR) return None plexLibType = mappedMediaType['libtype'] # make sure the item matches the media type if plexLibType is not None and not Api.validatePlexLibraryItemType( plexItem, plexLibType): log( 'cannot import {} item from invalid Plex library item: {}'. format(mediaType, plexItem), xbmc.LOGERROR) return None # determine the Kodi media type based on the Plex library type if not checkMediaType: plexLibType = plexItem.type mappedMediaTypes = Api.getKodiMediaTypesFromPlexLibraryTpe( plexLibType) if not mappedMediaTypes: log( 'cannot import unsupported Plex library type "{}"'.format( plexLibType), xbmc.LOGERROR) return None if len(mappedMediaTypes) > 1: log( '{} supported media type for Plex library type "{}"'. format(len(mappedMediaTypes), plexLibType), xbmc.LOGDEBUG) mediaType = mappedMediaTypes[0]['kodi'] itemId = plexItem.ratingKey if not itemId: log('cannot import {} item without identifier'.format(mediaType), xbmc.LOGERROR) return None item = ListItem(label=plexItem.title) # fill video details Api.fillVideoInfos(plexServer, itemId, plexItem, mediaType, item) if not item.getPath(): log( 'failed to retrieve a path for {} item "{}"'.format( mediaType, item.getLabel()), xbmc.LOGWARNING) return None return item
def show_category(category_id): #setContent(plugin.handle, 'albums') if category_id == "livestream": channels = get_url(ids.overview_url) json_data = {} if channels != "": json_data = json.loads(channels) else: kodiutils.notification("ERROR GETTING LIVESTREAM INFO", "using saved values") # current = ListItem("ORF 1") # current.setInfo(type="Video") # current.setProperty('IsPlayable', 'true') # orf1 channel = get_channel(json_data, "orf1") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "orf1"), listitem=get_listitem(name="ORF 1", channel=channel)) channel = get_channel(json_data, "orf2") addDirectoryItem(plugin.handle, plugin.url_for( play_livestream, "orf2"), get_listitem(name="ORF 2", channel=channel)) channel = get_channel(json_data, "Puls4") addDirectoryItem(plugin.handle, plugin.url_for( play_livestream, "puls4_at"), get_listitem(name="PULS 4", channel=channel, no_puls4=False)) channel = get_channel(json_data, "Popup") addDirectoryItem(plugin.handle, plugin.url_for( play_livestream, "popuptv"), get_listitem(name="Popup TV", channel=channel, no_puls4=False)) channel = get_channel(json_data, "ATV") addDirectoryItem(plugin.handle, plugin.url_for( play_livestream, "atv"), get_listitem(name="ATV", channel=channel)) channel = get_channel(json_data, "ATV2") addDirectoryItem(plugin.handle, plugin.url_for( play_livestream, "atv2"), get_listitem(name="ATV 2", channel=channel)) addDirectoryItem(plugin.handle, plugin.url_for( show_category, "austria"), ListItem(kodiutils.get_string(32026)), True) addDirectoryItem(plugin.handle, plugin.url_for( show_category, "germany"), ListItem(kodiutils.get_string(32027)), True) addDirectoryItem(plugin.handle, plugin.url_for( show_category, "switzerland"), ListItem(kodiutils.get_string(32028)), True) elif category_id == "austria": channels = get_url(ids.overview_url) json_data = {} if channels != "": json_data = json.loads(channels) else: kodiutils.notification("ERROR GETTING LIVESTREAM INFO", "using saved values") channel = get_channel(json_data, "kabel eins") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "kabeleins_at"), listitem=get_listitem(name="Kabel eins AT", channel=channel)) channel = get_channel(json_data, "Kabel1Doku") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "kabeleinsdoku_at"), listitem=get_listitem(name="Kabel1Doku AT", channel=channel)) channel = get_channel(json_data, "ProSieben") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "prosieben_at"), listitem=get_listitem(name="ProSieben AT", channel=channel)) channel = get_channel(json_data, "ProSiebenMaxx") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "prosiebenmaxx_at"), listitem=get_listitem(name="ProSiebenMaxx AT", channel=channel)) channel = get_channel(json_data, "SAT.1") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "sat1_at"), listitem=get_listitem(name="SAT.1 AT", channel=channel)) channel = get_channel(json_data, "SAT.1 Gold") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "sat1gold_at"), listitem=get_listitem(name="SAT.1 Gold AT", channel=channel)) channel = get_channel(json_data, "Sixx") addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "sixx_at"), listitem=get_listitem(name="Sixx AT", channel=channel)) elif category_id == "germany" or category_id == "switzerland": if category_id == "germany": id = "_de" name = " DE" else: id = "_ch" name = " CH" listitem = get_listitem(name="Kabel eins"+name) listitem.setArt({'icon': icon_path.format("kabeleins"), 'thumb': icon_path.format("kabeleins"), 'poster': icon_path.format("kabeleins")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "kabeleins"+id), listitem=listitem) listitem = get_listitem(name="Kabel1Doku"+name) listitem.setArt({'icon': icon_path.format("kabeleinsdoku"), 'thumb': icon_path.format("kabeleinsdoku"), 'poster': icon_path.format("kabeleinsdoku")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "kabeleinsdoku"+id), listitem=listitem) listitem = get_listitem(name="ProSieben"+name) listitem.setArt({'icon': icon_path.format("prosieben"), 'thumb': icon_path.format("prosieben"), 'poster': icon_path.format("prosieben")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "prosieben"+id), listitem=listitem) listitem = get_listitem(name="ProSiebenMaxx"+name) listitem.setArt({'icon': icon_path.format("prosiebenmaxx"), 'thumb': icon_path.format("prosiebenmaxx"), 'poster': icon_path.format("prosiebenmaxx")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "prosiebenmaxx"+id), listitem=listitem) listitem = get_listitem(name="SAT.1"+name) listitem.setArt({'icon': icon_path.format("sat1"), 'thumb': icon_path.format("sat1"), 'poster': icon_path.format("sat1")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "sat1"+id), listitem=listitem) listitem = get_listitem(name="SAT.1 Gold"+name) listitem.setArt({'icon': icon_path.format("sat1gold"), 'thumb': icon_path.format("sat1gold"), 'poster': icon_path.format("sat1gold")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "sat1gold"+id), listitem=listitem) listitem = get_listitem(name="Sixx"+name) listitem.setArt({'icon': icon_path.format("sixx"), 'thumb': icon_path.format("sixx"), 'poster': icon_path.format("sixx")}) addDirectoryItem(plugin.handle, url=plugin.url_for( play_livestream, "sixx"+id), listitem=listitem) elif category_id == "favorites": xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_LABEL) global favorites if not favorites and xbmcvfs.exists(favorites_file_path): favorites_file = xbmcvfs.File(favorites_file_path) favorites = json.load(favorites_file) favorites_file.close() for item in favorites: listitem = ListItem(favorites[item]["name"]) listitem.setArt({'icon': favorites[item]["icon"], 'thumb':favorites[item]["icon"], 'poster':favorites[item]["icon"], 'fanart' : favorites[item]["fanart"]}) addDirectoryItem(plugin.handle, url=item, listitem=listitem, isFolder=True) elif category_id == "tvprogramm": channels = get_url(ids.collections_request_url.format(id=ids.epg_id, page = "1"), critical=True) channels_json = json.loads(channels) xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_LABEL) for channel in channels_json["results"]: listitem = ListItem(channel["name"]) if listitem.getLabel() != "Puls4 TV": listitem.setLabel(listitem.getLabel().replace("Puls4 ", "")) images = json.loads(channel["images_json"]) icon = "" if "image_base" in images and images["image_base"]: icon = images["image_base"] else: icon = images["icon_1"] listitem.setArt({'icon': icon, 'thumb': icon, 'poster': icon}) addDirectoryItem(plugin.handle, url=plugin.url_for( show_epg, channel_id=channel["id"], icon=quote(icon)), listitem=listitem, isFolder=True) else: addDirectoryItem(plugin.handle, "", ListItem(kodiutils.get_string(32004)), False) endOfDirectory(plugin.handle)
def fillVideoInfos( plexServer: plexapi.server.PlexServer, itemId: int, plexItem: video.Video, mediaType: str, item: ListItem ): """ Populate the provided ListItem object with existing data from plexItem and additional detail pulled from the provided plexServer :param plexServer: Plex server to gather additional details from :type plexServer: plexapi.server.PlexServer :param itemId: Unique ID of the plex Video object item :type itemId: int :param plexItem: Plex object populated with information about the item :type plexItem: video.Video :param mediaType: Kodi Media type object :type mediaType: str :param item: Instantiated Kodi ListItem to populate with additional details :type item: :class:`ListItem` """ info = { 'mediatype': mediaType, 'path': '', 'filenameandpath': '', 'title': item.getLabel() or '', 'sorttitle': '', 'originaltitle': '', 'plot': plexItem.summary or '', 'dateadded': Api.convertDateTimeToDbDateTime(plexItem.addedAt), 'year': 0, 'set': '', 'rating': 0.0, 'userrating': 0.0, 'mpaa': '', 'duration': 0, 'playcount': 0, 'lastplayed': '', 'director': [], 'writer': [], 'genre': [], 'country': [], 'tag': [] } date = None isFolder = False resumePoint = { 'totaltime': 0, 'resumetime': 0 } artwork = {} collections = [] media = [] locations = [] roles = [] if isinstance(plexItem, video.Video): info.update({ 'sorttitle': plexItem.titleSort, 'playcount': plexItem.viewCount, 'lastplayed': Api.convertDateTimeToDbDateTime(plexItem.lastViewedAt), }) info['tag'].append(plexItem.librarySectionTitle) if isinstance(plexItem, video.Movie): info.update({ 'mpaa': plexItem.contentRating or '', 'duration': Api.MillisecondsToSeconds(plexItem.duration), 'originaltitle': plexItem.originalTitle or '', 'premiered': Api.convertDateTimeToDbDate(plexItem.originallyAvailableAt), 'rating': plexItem.rating or 0.0, 'studio': Api.ListFromString(plexItem.studio), 'tagline': plexItem.tagline or '', 'userrating': plexItem.userRating or 0.0, 'year': plexItem.year or 0, 'country': Api.ListFromMediaTags(plexItem.countries), 'director': Api.ListFromMediaTags(plexItem.directors), 'genre': Api.ListFromMediaTags(plexItem.genres), 'writer': Api.ListFromMediaTags(plexItem.writers), }) date = info['premiered'] resumePoint['resumetime'] = Api.MillisecondsToSeconds(plexItem.viewOffset) collections = plexItem.collections media = plexItem.media roles = plexItem.roles elif isinstance(plexItem, library.Collections): isFolder = True elif isinstance(plexItem, video.Show): info.update({ 'mpaa': plexItem.contentRating or '', 'duration': Api.MillisecondsToSeconds(plexItem.duration), 'premiered': Api.convertDateTimeToDbDate(plexItem.originallyAvailableAt), 'rating': plexItem.rating or 0.0, 'studio': Api.ListFromString(plexItem.studio), 'year': plexItem.year or 0, 'genre': Api.ListFromMediaTags(plexItem.genres), }) date = info['premiered'] isFolder = True locations = plexItem.locations collections = plexItem.collections roles = plexItem.roles banner = plexItem.banner if banner: artwork['banner'] = plexServer.url(banner, includeToken=True) elif isinstance(plexItem, video.Season): info.update({ 'tvshowtitle': plexItem.parentTitle or '', 'season': plexItem.index, }) isFolder = True elif isinstance(plexItem, video.Episode): info.update({ 'tvshowtitle': plexItem.grandparentTitle or '', 'season': plexItem.parentIndex, 'episode': plexItem.index, 'mpaa': plexItem.contentRating or '', 'duration': Api.MillisecondsToSeconds(plexItem.duration), 'aired': Api.convertDateTimeToDbDate(plexItem.originallyAvailableAt), 'rating': plexItem.rating or 0.0, 'year': plexItem.year or 0, 'director': Api.ListFromMediaTags(plexItem.directors), 'writer': Api.ListFromMediaTags(plexItem.writers), }) date = info['aired'] resumePoint['resumetime'] = Api.MillisecondsToSeconds(plexItem.viewOffset) media = plexItem.media # handle collections / sets collections = Api.ListFromMediaTags(collections) if collections: # Kodi can only store one set per media item info['set'] = collections[0] # set the item's datetime if available if date: item.setDateTime(date) # specify whether the item is a folder or not item.setIsFolder(isFolder) # add the item's ID as a unique ID belonging to Plex item.getVideoInfoTag().setUniqueIDs({ PLEX_PROTOCOL: itemId }, PLEX_PROTOCOL) # handle actors / cast cast = [] for index, role in enumerate(roles): cast.append({ 'name': role.tag.strip(), 'role': role.role.strip(), 'order': index }) if cast: item.setCast(cast) # handle resume point if resumePoint['resumetime'] > 0 and info['duration'] > 0: resumePoint['totaltime'] = info['duration'] item.setProperties(resumePoint) # handle stream details mediaPart = None for mediaStream in media: for part in mediaStream.parts: # pick the first MediaPart with a valid file and stream URL if mediaPart is None and part.file is not None and part.key is not None: mediaPart = part for videoStream in part.videoStreams(): item.addStreamInfo('video', { 'codec': videoStream.codec, 'language': videoStream.language, 'width': videoStream.width, 'height': videoStream.height, 'duration': info['duration'] }) for audioStream in part.audioStreams(): item.addStreamInfo( 'audio', { 'codec': audioStream.codec, 'language': audioStream.language, 'channels': audioStream.channels } ) for subtitleStream in part.subtitleStreams(): item.addStreamInfo( 'subtitle', { 'language': subtitleStream.language } ) if mediaPart: # extract the absolute / actual path and the stream URL from the selected MediaPart info['path'] = mediaPart.file item.setPath(plexServer.url(mediaPart.key, includeToken=True)) elif isFolder: # for folders use locations for the path if locations: info['path'] = locations[0] item.setPath(plexServer.url(plexItem.key, includeToken=True)) info['filenameandpath'] = item.getPath() # set all the video infos item.setInfo('video', info) # handle artwork poster = None fanart = None if isinstance(plexItem, video.Video): poster = plexItem.thumbUrl fanart = plexItem.artUrl elif isinstance(plexItem, library.Collections) and plexItem.thumb: poster = plexServer.url(plexItem.thumb, includeToken=True) if poster: artwork['poster'] = poster if fanart: artwork['fanart'] = fanart if artwork: item.setArt(artwork)
def createVideoInfoItemWithVideoSetters(embyServer, itemId, itemPath, itemObj, mediaType, libraryView='', allowDirectPlay=True): item = ListItem(path=itemPath, label=itemObj.get(constants.PROPERTY_ITEM_NAME, ''), offscreen=True) item.setIsFolder(itemObj.get(constants.PROPERTY_ITEM_IS_FOLDER, False)) # handle date premiereDate = itemObj.get(constants.PROPERTY_ITEM_PREMIERE_DATE) if premiereDate: item.setDateTime(premiereDate) videoInfoTag = item.getVideoInfoTag() userdata = {} if constants.PROPERTY_ITEM_USER_DATA in itemObj: userdata = itemObj[constants.PROPERTY_ITEM_USER_DATA] duration = int( Api.ticksToSeconds( itemObj.get(constants.PROPERTY_ITEM_RUN_TIME_TICKS, 0))) videoInfoTag.setMediaType(mediaType) videoInfoTag.setPath(itemObj.get(constants.PROPERTY_ITEM_PATH, '')) videoInfoTag.setFilenameAndPath(item.getPath()) videoInfoTag.setTitle(item.getLabel() or '') videoInfoTag.setSortTitle( itemObj.get(constants.PROPERTY_ITEM_SORT_NAME, '')) videoInfoTag.setOriginalTitle( itemObj.get(constants.PROPERTY_ITEM_ORIGINAL_TITLE, '')) videoInfoTag.setPlot( Api._mapOverview(itemObj.get(constants.PROPERTY_ITEM_OVERVIEW, ''))) videoInfoTag.setPlotOutline( itemObj.get(constants.PROPERTY_ITEM_SHORT_OVERVIEW, '')) videoInfoTag.setDateAdded( Api.convertDateTimeToDbDateTime( itemObj.get(constants.PROPERTY_ITEM_DATE_CREATED, ''))) videoInfoTag.setYear( itemObj.get(constants.PROPERTY_ITEM_PRODUCTION_YEAR, 0)) videoInfoTag.setMpaa( Api._mapMpaa( itemObj.get(constants.PROPERTY_ITEM_OFFICIAL_RATING, ''))) videoInfoTag.setDuration(duration) videoInfoTag.setPlaycount( userdata.get(constants.PROPERTY_ITEM_USER_DATA_PLAY_COUNT, 0 ) if userdata. get(constants.PROPERTY_ITEM_USER_DATA_PLAYED, False) else 0) videoInfoTag.setLastPlayed( Api.convertDateTimeToDbDateTime( userdata.get( constants.PROPERTY_ITEM_USER_DATA_LAST_PLAYED_DATE, ''))) videoInfoTag.setArtists( itemObj.get(constants.PROPERTY_ITEM_ARTISTS, [])) videoInfoTag.setAlbum(itemObj.get(constants.PROPERTY_ITEM_ALBUM, '')) videoInfoTag.setGenres(itemObj.get(constants.PROPERTY_ITEM_GENRES, [])) videoInfoTag.setCountries( itemObj.get(constants.PROPERTY_ITEM_PRODUCTION_LOCATIONS, [])) # process ratings if constants.PROPERTY_ITEM_COMMUNITY_RATING in itemObj: defaultRating = itemObj.get( constants.PROPERTY_ITEM_COMMUNITY_RATING) videoInfoTag.setRating(defaultRating, isDefault=True) # handle critic rating as rotten tomato rating if constants.PROPERTY_ITEM_CRITIC_RATING in itemObj: criticRating = float( itemObj.get(constants.PROPERTY_ITEM_CRITIC_RATING)) / 10.0 videoInfoTag.setRating(criticRating, type='tomatometerallcritics') # handle unique / provider IDs uniqueIds = \ {key.lower(): value for key, value in iteritems(itemObj.get(constants.PROPERTY_ITEM_PROVIDER_IDS, {}))} defaultUniqueId = Api._mapDefaultUniqueId(uniqueIds, mediaType) # add the item's ID as a unique ID belonging to Emby uniqueIds[constants.EMBY_PROTOCOL] = itemId videoInfoTag.setUniqueIDs(uniqueIds, defaultUniqueId) # process tags tags = [] if constants.PROPERTY_ITEM_TAG_ITEMS in itemObj: tags = [ tag.get(constants.PROPERTY_ITEM_TAG_ITEMS_NAME) for tag in itemObj.get(constants.PROPERTY_ITEM_TAG_ITEMS) if constants.PROPERTY_ITEM_TAG_ITEMS_NAME in tag ] # add the library view as a tag if libraryView: tags.append(libraryView) videoInfoTag.setTags(tags) # handle aired / premiered if premiereDate: pos = premiereDate.find('T') if pos >= 0: premiereDate = premiereDate[:pos] if mediaType == xbmcmediaimport.MediaTypeEpisode: videoInfoTag.setFirstAired(premiereDate) else: videoInfoTag.setPremiered(premiereDate) # handle trailers trailerUrl = Api.getTrailer(embyServer, itemId, itemObj, allowDirectPlay=allowDirectPlay) if trailerUrl: videoInfoTag.setTrailer(trailerUrl) # handle taglines embyTaglines = itemObj.get(constants.PROPERTY_ITEM_TAGLINES, []) if embyTaglines: videoInfoTag.setTagLine(embyTaglines[0]) # handle studios studios = [] for studio in itemObj.get(constants.PROPERTY_ITEM_STUDIOS, []): studios.append(Api._mapStudio(studio['Name'])) videoInfoTag.setStudios(studios) # handle tvshow, season and episode specific properties if mediaType == xbmcmediaimport.MediaTypeTvShow: videoInfoTag.setTvShowTitle(videoInfoTag.getTitle()) videoInfoTag.setTvShowStatus( itemObj.get(constants.PROPERTY_ITEM_STATUS, '')) elif mediaType in (xbmcmediaimport.MediaTypeSeason, xbmcmediaimport.MediaTypeEpisode): videoInfoTag.setTvShowTitle( itemObj.get(constants.PROPERTY_ITEM_SERIES_NAME, '')) index = itemObj.get(constants.PROPERTY_ITEM_INDEX_NUMBER, 0) if mediaType == xbmcmediaimport.MediaTypeSeason: videoInfoTag.setSeason(index) # ATTENTION # something is wrong with the SortName property for seasons which interfers with Kodi # abusing sorttitle for custom season titles videoInfoTag.setSortTitle('') else: videoInfoTag.setSeason( itemObj.get(constants.PROPERTY_ITEM_PARENT_INDEX_NUMBER, 0)) videoInfoTag.setEpisode(index) # handle resume point videoInfoTag.setResumePoint( Api.ticksToSeconds( userdata.get( constants.PROPERTY_ITEM_USER_DATA_PLAYBACK_POSITION_TICKS, 0)), duration) # handle actors / cast cast = [] writers = [] directors = [] for index, person in enumerate( itemObj.get(constants.PROPERTY_ITEM_PEOPLE, [])): name = person.get(constants.PROPERTY_ITEM_PEOPLE_NAME, '') castType = person.get(constants.PROPERTY_ITEM_PEOPLE_TYPE, '') if castType == constants.PROPERTY_ITEM_PEOPLE_TYPE_ACTOR: role = person.get(constants.PROPERTY_ITEM_PEOPLE_ROLE, '') # determine the thumbnail (if available) thumbnail = '' personId = person.get(constants.PROPERTY_ITEM_PEOPLE_ID, None) primaryImageTag = person.get( constants.PROPERTY_ITEM_PEOPLE_PRIMARY_IMAGE_TAG, '') if personId and primaryImageTag: thumbnail = \ embyServer.BuildImageUrl(personId, constants.PROPERTY_ITEM_IMAGE_TAGS_PRIMARY, primaryImageTag) cast.append(xbmc.Actor(name, role, index, thumbnail)) elif castType == constants.PROPERTY_ITEM_PEOPLE_TYPE_WRITER: writers.append(name) elif castType == constants.PROPERTY_ITEM_PEOPLE_TYPE_DIRECTOR: directors.append(name) videoInfoTag.setCast(cast) videoInfoTag.setWriters(writers) videoInfoTag.setDirectors(directors) # stream details for stream in itemObj.get(constants.PROPERTY_ITEM_MEDIA_STREAMS, []): streamType = stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_TYPE, '') if streamType == 'video': details = Api._mapVideoStream({ 'codec': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_CODEC, ''), 'profile': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_PROFILE, ''), 'language': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_LANGUAGE, ''), 'width': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_WIDTH, 0), 'height': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_HEIGHT, 0), 'aspect': stream.get( constants.PROPERTY_ITEM_MEDIA_STREAM_ASPECT_RATIO, '0'), 'stereomode': stream.get( constants.PROPERTY_ITEM_MEDIA_STREAM_VIDEO_3D_FORMAT, 'mono'), 'duration': duration }) videoInfoTag.addVideoStream( xbmc.VideoStreamDetail( width=details['width'], height=details['height'], aspect=details['aspect'], duration=details['duration'], codec=details['codec'], stereoMode=details['stereomode'], language=details['language'], )) elif streamType == 'audio': details = Api._mapAudioStream({ 'codec': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_CODEC, ''), 'profile': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_PROFILE, ''), 'language': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_LANGUAGE, ''), 'channels': stream.get(constants.PROPERTY_ITEM_MEDIA_STREAM_CHANNELS, 2) }) videoInfoTag.addAudioStream( xbmc.AudioStreamDetail( channels=details['channels'], codec=details['codec'], language=details['language'], )) elif streamType == 'subtitle': videoInfoTag.addSubtitleStream( xbmc.SubtitleStreamDetail(language=stream.get( constants.PROPERTY_ITEM_MEDIA_STREAM_LANGUAGE, ''), )) return item
def fillVideoInfos(plexServer: server.PlexServer, itemId: int, plexItem: video.Video, mediaType: str, item: ListItem, allowDirectPlay: bool = False): """ Populate the provided ListItem object with existing data from plexItem and additional detail pulled from the provided plexServer :param plexServer: Plex server to gather additional details from :type plexServer: server.PlexServer :param itemId: Unique ID of the plex Video object item :type itemId: int :param plexItem: Plex object populated with information about the item :type plexItem: video.Video :param mediaType: Kodi Media type object :type mediaType: str :param item: Instantiated Kodi ListItem to populate with additional details :type item: :class:`ListItem` :param allowDirectPlay: Settings definition on provider if directPlay is allowed :type allowDirectPlay: bool, optional """ videoInfoTag = item.getVideoInfoTag() videoInfoTag.setMediaType(mediaType) videoInfoTag.setTitle(item.getLabel() or '') date = None isFolder = False resumeTime = 0.0 duration = 0.0 artwork = {} collections = [] media = [] locations = [] roles = [] if isinstance(plexItem, video.Video): videoInfoTag.setSortTitle(plexItem.titleSort or '') videoInfoTag.setPlot(plexItem.summary or '') videoInfoTag.setDateAdded( Api.convertDateTimeToDbDateTime(plexItem.addedAt)) videoInfoTag.setPlaycount(plexItem.viewCount or 0) videoInfoTag.setLastPlayed( Api.convertDateTimeToDbDateTime(plexItem.lastViewedAt)) videoInfoTag.setTags([plexItem.librarySectionTitle]) if isinstance(plexItem, video.Movie): date = Api.convertDateTimeToDbDate(plexItem.originallyAvailableAt) duration = Api.MillisecondsToSeconds(plexItem.duration) resumeTime = Api.MillisecondsToSeconds(plexItem.viewOffset) collections = plexItem.collections or [] media = plexItem.media or [] roles = plexItem.roles or [] videoInfoTag.setMpaa(plexItem.contentRating or '') videoInfoTag.setDuration(int(duration)) videoInfoTag.setOriginalTitle(plexItem.originalTitle or '') videoInfoTag.setPremiered(date) videoInfoTag.setRating(plexItem.rating or 0.0) videoInfoTag.setTagLine(plexItem.tagline or '') videoInfoTag.setUserRating(int(plexItem.userRating or 0)) videoInfoTag.setYear(plexItem.year or 0) videoInfoTag.setStudios(Api.ListFromString(plexItem.studio)) videoInfoTag.setCountries(Api.ListFromMediaTags( plexItem.countries)) videoInfoTag.setGenres(Api.ListFromMediaTags(plexItem.genres)) videoInfoTag.setDirectors(Api.ListFromMediaTags( plexItem.directors)) videoInfoTag.setWriters(Api.ListFromMediaTags(plexItem.writers)) elif isinstance(plexItem, collection.Collection): # ignore empty collections if plexItem.childCount <= 0: return isFolder = True videoInfoTag.setPlot(plexItem.summary or '') videoInfoTag.setDateAdded( Api.convertDateTimeToDbDateTime(plexItem.addedAt)) elif isinstance(plexItem, video.Show): isFolder = True date = Api.convertDateTimeToDbDate(plexItem.originallyAvailableAt) duration = Api.MillisecondsToSeconds(plexItem.duration) locations = plexItem.locations or [] collections = plexItem.collections or [] roles = plexItem.roles or [] banner = plexItem.banner if banner: artwork['banner'] = plexServer.url(banner, includeToken=True) videoInfoTag.setMpaa(plexItem.contentRating or '') videoInfoTag.setDuration(int(duration)) videoInfoTag.setOriginalTitle(plexItem.originalTitle or '') videoInfoTag.setPremiered(date) videoInfoTag.setRating(plexItem.rating or 0.0) videoInfoTag.setTagLine(plexItem.tagline or '') videoInfoTag.setYear(plexItem.year or 0) videoInfoTag.setStudios(Api.ListFromString(plexItem.studio)) videoInfoTag.setGenres(Api.ListFromMediaTags(plexItem.genres)) elif isinstance(plexItem, video.Season): isFolder = True videoInfoTag.setTvShowTitle(plexItem.parentTitle or '') videoInfoTag.setSeason(plexItem.index) elif isinstance(plexItem, video.Episode): date = Api.convertDateTimeToDbDate(plexItem.originallyAvailableAt) resumeTime = Api.MillisecondsToSeconds(plexItem.viewOffset) duration = Api.MillisecondsToSeconds(plexItem.duration) media = plexItem.media or [] videoInfoTag.setTvShowTitle(plexItem.grandparentTitle or '') videoInfoTag.setSeason(int(plexItem.parentIndex)) videoInfoTag.setEpisode(plexItem.index) videoInfoTag.setMpaa(plexItem.contentRating or '') videoInfoTag.setDuration(int(duration)) videoInfoTag.setFirstAired(date) videoInfoTag.setRating(plexItem.rating or 0.0) videoInfoTag.setYear(plexItem.year or 0) videoInfoTag.setDirectors(Api.ListFromMediaTags( plexItem.directors)) videoInfoTag.setWriters(Api.ListFromMediaTags(plexItem.writers)) # handle collections / sets collections = Api.ListFromMediaTags(collections) if collections: # Kodi can only store one set per media item videoInfoTag.setSet(collections[0]) # set the item's datetime if available if date: item.setDateTime(date) # specify whether the item is a folder or not item.setIsFolder(isFolder) # add the item's ID as a unique ID belonging to Plex uniqueIDs = {PLEX_PROTOCOL: str(itemId)} # retrieve and map GUIDS from Plex if isinstance(plexItem, (video.Movie, video.Show, video.Season, video.Episode)): guids = Api._mapGuids(plexItem.guids) if guids: uniqueIDs = {**guids, **uniqueIDs} videoInfoTag.setUniqueIDs(uniqueIDs, PLEX_PROTOCOL) # handle actors / cast cast = [] for index, role in enumerate(roles): actor = xbmc.Actor(role.tag.strip(), (role.role or '').strip(), index, role.thumb) cast.append(actor) if cast: videoInfoTag.setCast(cast) # handle resume point if resumeTime > 0 and duration > 0.0: videoInfoTag.setResumePoint(resumeTime, duration) # handle stream details path = None for mediaStream in media: for part in mediaStream.parts: # pick the first MediaPart with a valid file and stream URL if not path and part.file and part.key: path = part.file for videoStream in part.videoStreams(): videoInfoTag.addVideoStream( xbmc.VideoStreamDetail(width=videoStream.width or 0, height=videoStream.height or 0, codec=videoStream.codec or '', duration=int(duration), language=videoStream.language or '')) for audioStream in part.audioStreams(): videoInfoTag.addAudioStream( xbmc.AudioStreamDetail(channels=audioStream.channels or 2, codec=audioStream.codec or '', language=audioStream.language or '')) for index, subtitleStream in enumerate(part.subtitleStreams()): videoInfoTag.addSubtitleStream( xbmc.SubtitleStreamDetail( language=subtitleStream.language or f"[{index}]")) if isFolder: # for folders use locations for the path if locations: path = locations[0] item.setPath(plexServer.url(plexItem.key, includeToken=True)) else: # determine if directPlay is enabled and possible if allowDirectPlay: directPlayUrl = Api.getDirectPlayUrlFromPlexItem(plexItem) if directPlayUrl: item.setPath(directPlayUrl) # otherwise determine the stream URL if not item.getPath(): item.setPath(Api.getStreamUrlFromPlexItem( plexItem, plexServer)) if path: videoInfoTag.setPath(path) videoInfoTag.setFilenameAndPath(item.getPath()) # handle artwork poster = None fanart = None if isinstance(plexItem, video.Video): poster = plexItem.thumbUrl fanart = plexItem.artUrl elif isinstance(plexItem, collection.Collection) and plexItem.thumb: poster = plexServer.url(plexItem.thumb, includeToken=True) if poster: artwork['poster'] = poster if fanart: artwork['fanart'] = fanart if artwork: item.setArt(artwork)