def getTrailer(embyServer, itemId, itemObj, allowDirectPlay=True): # prefer local trailers if direct play is allowed if allowDirectPlay and itemObj.get( constants.PROPERTY_ITEM_LOCAL_TRAILER_COUNT, 0): localTrailers = Library.GetLocalTrailers(embyServer, itemId) if not localTrailers: log('failed to retrieve local trailers for item with ID {}'. format(itemId)) else: localTrailerUrl = Api.getPlaybackUrl( embyServer, itemId, localTrailers[0], allowDirectPlay=allowDirectPlay) if localTrailerUrl: return localTrailerUrl # otherwise use the first remote trailer if constants.PROPERTY_ITEM_REMOTE_TRAILERS in itemObj: remoteTrailers = itemObj.get( constants.PROPERTY_ITEM_REMOTE_TRAILERS) if remoteTrailers: return remoteTrailers[0].get( constants.PROPERTY_ITEM_REMOTE_TRAILERS_URL, None) return None
def settingOptionsFillerViews(handle, options): # retrieve the media provider mediaProvider = xbmcmediaimport.getProvider(handle) if not mediaProvider: log('cannot retrieve media provider', xbmc.LOGERROR) return # retrieve the media import mediaImport = xbmcmediaimport.getImport(handle) if not mediaImport: log('cannot retrieve media import', xbmc.LOGERROR) return # prepare the media provider settings if not mediaProvider.prepareSettings(): log('cannot prepare media provider settings', xbmc.LOGERROR) return embyServer = Server(mediaProvider) if not embyServer.Authenticate(): log('failed to authenticate on media provider {}'.format(mediaProvider2str(mediaProvider)), xbmc.LOGERROR) return libraryViews = Library.GetViews(embyServer, mediaImport.getMediaTypes()) views = [] for libraryView in libraryViews: views.append((libraryView.name, libraryView.id)) # get the import's settings settings = mediaImport.getSettings() # pass the list of views back to Kodi settings.setStringOptions(emby.constants.SETTING_IMPORT_VIEWS_SPECIFIC, views)
def _addExternalSubtitles(self): if not self._item: return # get the item's details to look for external subtitles itemObj = Library.GetItem(self._server, self._itemId) if not itemObj: Player.log('cannot retrieve details of "{}" ({}) from media provider {}' \ .format(self._item.getLabel(), self._file, mediaProvider2str(self._mediaProvider)), xbmc.LOGWARNING) return # extract the media source ID if not PROPERTY_ITEM_MEDIA_SOURCES in itemObj or not itemObj[ PROPERTY_ITEM_MEDIA_SOURCES]: Player.log('cannot add external subtitles for "{}" ({}) from media provider {} ' \ 'because it doesn\'t have a media source' \ .format(self._item.getLabel(), self._file, mediaProvider2str(self._mediaProvider)), xbmc.LOGDEBUG) return mediaSourceId = itemObj.get(PROPERTY_ITEM_MEDIA_SOURCES)[0].get( PROPERTY_ITEM_MEDIA_SOURCES_ID) # look for external subtitles for stream in itemObj.get(PROPERTY_ITEM_MEDIA_STREAMS): if stream.get(PROPERTY_ITEM_MEDIA_STREAM_TYPE ) != 'Subtitle' or not stream.get( PROPERTY_ITEM_MEDIA_STREAM_IS_EXTERNAL): continue # get the index of the subtitle index = stream.get(PROPERTY_ITEM_MEDIA_STREAM_INDEX) # determine the language and name name = stream.get( PROPERTY_ITEM_MEDIA_STREAM_DISPLAY_TITLE ) if PROPERTY_ITEM_MEDIA_STREAM_DISPLAY_TITLE in stream else '' language = stream.get( PROPERTY_ITEM_MEDIA_STREAM_LANGUAGE ) if PROPERTY_ITEM_MEDIA_STREAM_LANGUAGE in stream else '' # determine the stream URL if PROPERTY_ITEM_MEDIA_STREAM_DELIVERY_URL in stream and \ stream.get(PROPERTY_ITEM_MEDIA_STREAM_DELIVERY_URL).upper().startswith('/{}'.format(URL_VIDEOS)): url = self._server.BuildStreamDeliveryUrl( stream.get(PROPERTY_ITEM_MEDIA_STREAM_DELIVERY_URL)) else: url = self._server.BuildSubtitleStreamUrl( self._itemId, mediaSourceId, index, stream.get(PROPERTY_ITEM_MEDIA_STREAM_CODEC)) if not url: Player.log('cannot add external subtitle at index {} for "{}" ({}) from media provider {}' \ .format(index, self._item.getLabel(), self._file, mediaProvider2str(self._mediaProvider)), xbmc.LOGWARNING) continue self.addSubtitle(url, name, language, False) # TODO(Montellese): activate? Player.log('external subtitle "{}" [{}] at index {} added for "{}" ({}) from media provider {}' \ .format(name, language, index, self._item.getLabel(), self._file, mediaProvider2str(self._mediaProvider)))
def refreshMetadata(item, itemId, mediaProvider): # create an Emby server instance embyServer = Server(mediaProvider) # trigger a metadata refresh on the Emby server Library.RefreshItemMetadata(embyServer, itemId) log('[context/refresh] triggered metadata refresh for {} on {}'.format( listItem2str(item, itemId), mediaProvider2str(mediaProvider)))
def _GetItemDetails(self, itemId): # retrieve all details of the item itemObj = Library.GetItem(self._server, itemId) if not itemObj: ProviderObserver.log( 'cannot retrieve details of updated item with id "{}" from {}'. format(itemId, mediaProvider2str(self._mediaProvider)), xbmc.LOGERROR) return None return kodi.Api.toFileItem( self._server, itemObj, allowDirectPlay=self._settings.getBool( SETTING_PROVIDER_PLAYBACK_ALLOW_DIRECT_PLAY))
def getMatchingLibraryViews(embyServer, mediaTypes, selectedViews): if not embyServer: raise ValueError('invalid emby server') if not mediaTypes: raise ValueError('invalid mediaTypes') libraryViews = Library.GetViews(embyServer, mediaTypes) matchingLibraryViews = [] if not selectedViews: matchingLibraryViews = libraryViews else: matchingLibraryViews = [ libraryView for libraryView in libraryViews if libraryView.id in selectedViews ] return matchingLibraryViews
def getLibraryViews(embyServer, mediaTypes): if not embyServer: raise ValueError('invalid emby server') if not mediaTypes: raise ValueError('invalid mediaTypes') # check whether to include mixed libraries includeMixed = False for mediaType in mediaTypes: (_, _, mixed, _) = kodi.Api.getEmbyMediaType(mediaType) if mixed: includeMixed = True break return Library.GetViews(embyServer, mediaTypes, includeMixed=includeMixed)
def synchronizeItem(item, itemId, mediaProvider, embyServer, allowDirectPlay=True): # retrieve all details of the item itemObj = Library.GetItem(embyServer, itemId) if not itemObj: log( '[context/sync] cannot retrieve details of {} from {}'.format( listItem2str(item, itemId), mediaProvider2str(mediaProvider)), xbmc.LOGERROR) return None return kodi.Api.toFileItem(embyServer, itemObj, allowDirectPlay=allowDirectPlay)
def updateOnProvider(handle, options): # retrieve the media import mediaImport = xbmcmediaimport.getImport(handle) if not mediaImport: log('cannot retrieve media import', xbmc.LOGERROR) return # retrieve the media provider mediaProvider = mediaImport.getProvider() if not mediaProvider: log('cannot retrieve media provider', xbmc.LOGERROR) return # prepare and get the media import settings importSettings = mediaImport.prepareSettings() if not importSettings: log('cannot prepare media import settings', xbmc.LOGERROR) return item = xbmcmediaimport.getUpdatedItem(handle) if not item: log('cannot retrieve updated item', xbmc.LOGERROR) return log('updating "{}" ({}) on {}...'.format(item.getLabel(), item.getPath(), mediaProvider2str(mediaProvider))) itemVideoInfoTag = item.getVideoInfoTag() if not itemVideoInfoTag: log('updated item is not a video item', xbmc.LOGERROR) return # determine the item's identifier itemId = kodi.Api.getEmbyItemIdFromVideoInfoTag(itemVideoInfoTag) if not itemId: log('cannot determine the identifier of the updated item: "{}"'.format(itemVideoInfoTag.getPath()), xbmc.LOGERROR) return # prepare the media provider settings if not mediaProvider.prepareSettings(): log('cannot prepare media provider settings', xbmc.LOGERROR) return # create an Emby server instance embyServer = Server(mediaProvider) if not embyServer.Authenticate(): log('failed to authenticate on media provider {}'.format(mediaProvider2str(mediaProvider)), xbmc.LOGERROR) return # retrieve all details of the item itemObj = Library.GetItem(embyServer, itemId) if not itemObj: log('cannot retrieve details of updated item with id {}'.format(itemId), xbmc.LOGERROR) return if not emby.constants.PROPERTY_ITEM_USER_DATA in itemObj: log('cannot update item with id {} because it has no userdata'.format(itemId), xbmc.LOGERROR) return updateItemPlayed = False updatePlaybackPosition = False # retrieve playback states from the updated item playcount = itemVideoInfoTag.getPlayCount() watched = playcount > 0 lastPlayed = itemVideoInfoTag.getLastPlayed() # retrieve playback position from the updated item playbackPositionInSeconds = max(0.0, float(item.getProperty('resumetime'))) playbackPositionInTicks = kodi.Api.secondsToTicks(playbackPositionInSeconds) userDataObj = itemObj[emby.constants.PROPERTY_ITEM_USER_DATA] # check and update playcout if necessary if emby.constants.PROPERTY_ITEM_USER_DATA_PLAY_COUNT in userDataObj: # retrieve playcount from the original item itemPlayed = userDataObj[emby.constants.PROPERTY_ITEM_USER_DATA_PLAY_COUNT] > 0 if watched != itemPlayed: updateItemPlayed = True # check and update playback position if necessary if emby.constants.PROPERTY_ITEM_USER_DATA_PLAYBACK_POSITION_TICKS in userDataObj: # retrieve playback position from the original item itemPlaybackPositionInTicks = userDataObj[emby.constants.PROPERTY_ITEM_USER_DATA_PLAYBACK_POSITION_TICKS] if playbackPositionInTicks != itemPlaybackPositionInTicks: updatePlaybackPosition = True # nothing to do if no playback related properties have been changed if not updateItemPlayed and not updatePlaybackPosition: log('no playback related properties of "{}" ({}) have changed => nothing to update on {}'.format(item.getLabel(), item.getPath(), mediaProvider2str(mediaProvider))) return log('updating playback related properties of "{}" ({}) on {}...'.format(item.getLabel(), item.getPath(), mediaProvider2str(mediaProvider))) if not UserData.Update(embyServer, itemId, updateItemPlayed, updatePlaybackPosition, watched, playcount, lastPlayed, playbackPositionInTicks): log('updating playback related properties of "{}" ({}) on {} failed'.format(item.getLabel(), item.getPath(), mediaProvider2str(mediaProvider)), xbmc.LOGERROR) xbmcmediaimport.finishUpdateOnProvider(handle)
def play(item, itemId, mediaProvider): if item.isFolder(): log( '[context/play] cannot play folder item {}'.format( listItem2str(item, itemId)), xbmc.LOGERROR) return # create an Emby server instance embyServer = Server(mediaProvider) # retrieve all details of the item itemObj = Library.GetItem(embyServer, itemId) if not itemObj: log( '[context/play] cannot retrieve the details of {} from {}'.format( listItem2str(item, itemId), mediaProvider2str(mediaProvider)), xbmc.LOGERROR) return # cannot play folders if itemObj.get(emby.constants.PROPERTY_ITEM_IS_FOLDER): log( '[context/play] cannot play folder item {}'.format( listItem2str(item, itemId)), xbmc.LOGERROR) return playChoices = [] playChoicesUrl = [] # determine whether Direct Play is allowed mediaProviderSettings = mediaProvider.getSettings() allowDirectPlay = mediaProviderSettings.getBool( emby.constants.SETTING_PROVIDER_PLAYBACK_ALLOW_DIRECT_PLAY) # check if the item supports Direct Play and / or Direct Stream canDirectPlay = None directPlayUrl = None if allowDirectPlay: (canDirectPlay, directPlayUrl) = kodi.Api.getDirectPlayUrl(itemObj) if canDirectPlay and directPlayUrl: playChoices.append(localise(32101)) playChoicesUrl.append(directPlayUrl) (canDirectStream, directStreamUrl) = kodi.Api.getDirectStreamUrl(embyServer, itemId, itemObj) if canDirectStream: playChoices.append(localise(32102)) playChoicesUrl.append(directStreamUrl) # if there are no options something went wrong if not playChoices: log( '[context/play] cannot play {} from {}'.format( listItem2str(item, itemId), mediaProvider2str(mediaProvider)), xbmc.LOGERROR) return # ask the user how to play playChoice = Dialog().contextmenu(playChoices) if playChoice < 0 or playChoice >= len(playChoices): return playUrl = playChoicesUrl[playChoice] # play the item log('[context/play] playing {} using "{}" ({}) from {}'.format( listItem2str(item, itemId), playChoices[playChoice], playUrl, mediaProvider2str(mediaProvider))) # overwrite the dynamic path of the ListItem item.setDynamicPath(playUrl) xbmc.Player().play(playUrl, item)