def _on_playback_started(self): player_id = _get_player_id() self._notify_all(ActionManager.call_on_playback_started, self._get_player_state(player_id)) if LOG.is_enabled and G.ADDON.getSettingBool('show_codec_info'): common.json_rpc('Input.ExecuteAction', {'action': 'codecinfo'}) self.active_player_id = player_id
def initialize(self, data): self.is_kodi_forced_subtitles_only = common.get_kodi_subtitle_language() == 'forced_only' self.is_prefer_alternative_lang = G.ADDON.getSettingBool('prefer_alternative_lang') self.is_prefer_sub_impaired = common.json_rpc('Settings.GetSettingValue', {'setting': 'accessibility.subhearing'}).get('value') self.is_prefer_audio_impaired = common.json_rpc('Settings.GetSettingValue', {'setting': 'accessibility.audiovisual'}).get('value')
def remove_watched_status(self, videoid): """Remove the watched status from the Netflix service""" if not ui.ask_for_confirmation( common.get_local_string(30168), common.get_local_string(30300).format( xbmc.getInfoLabel('ListItem.Label'))): return if not api.remove_watched_status(videoid): ui.show_notification( 'The operation was cancelled due to an unexpected error') return # Check if item is in the cache videoid_exists, list_id = common.make_http_call( 'get_continuewatching_videoid_exists', {'video_id': str(videoid.value)}) if videoid_exists: # Try to remove the videoid from the list in the cache try: video_list_sorted_data = G.CACHE.get(cache_utils.CACHE_COMMON, list_id) del video_list_sorted_data.videos[videoid.value] G.CACHE.add(cache_utils.CACHE_COMMON, list_id, video_list_sorted_data) common.json_rpc( 'Input.Down') # Avoids selection back to the top except CacheMiss: pass common.container_refresh()
def my_list(self, videoid, pathitems): """Add or remove an item from my list""" operation = pathitems[1] api.update_my_list(videoid, operation, self.params) sync_library(videoid, operation) if operation == 'remove' and common.WndHomeProps[common.WndHomeProps.CURRENT_DIRECTORY_MENU_ID] == 'myList': common.json_rpc('Input.Down') # Avoids selection back to the top common.container_refresh()
def _on_playback_started(self): player_id = _get_player_id() self._notify_all(PlaybackActionManager.on_playback_started, self._get_player_state(player_id)) if common.is_debug_verbose() and g.ADDON.getSettingBool( 'show_codec_info'): common.json_rpc('Input.ExecuteAction', {'action': 'codecinfo'}) self.active_player_id = player_id
def _raspberry_disable_omxplayer(): """Check and disable OMXPlayer (not compatible with Netflix video streams)""" # Only Kodi 18 has this property, from Kodi 19 OMXPlayer has been removed if not g.KODI_VERSION.is_major_ver('18'): return value = common.json_rpc('Settings.GetSettingValue', {'setting': 'videoplayer.useomxplayer'}) if value.get('value'): common.json_rpc('Settings.SetSettingValue', {'setting': 'videoplayer.useomxplayer', 'value': False})
def _set_kodi_settings(system): """Method for self-configuring Kodi settings""" if system == 'android': # Media Codec hardware acceleration is mandatory, otherwise only the audio stream is played try: json_rpc('Settings.SetSettingValue', {'setting': 'videoplayer.usemediacodecsurface', 'value': True}) json_rpc('Settings.SetSettingValue', {'setting': 'videoplayer.usemediacodec', 'value': True}) except IOError as exc: LOG.error('Changing Kodi settings caused the following error: {}', exc)
def _on_playback_started(self, data): # When UpNext addon play a video while we are inside Netflix addon and # not externally like Kodi library, the playerid become -1 this id does not exist player_id = data['player'][ 'playerid'] if data['player']['playerid'] > -1 else 1 self.active_player_id = player_id self._notify_all(PlaybackActionManager.on_playback_started, self._get_player_state()) if common.is_debug_verbose() and g.ADDON.getSettingBool( 'show_codec_info'): common.json_rpc('Input.ExecuteAction', {'action': 'codecinfo'})
def _remove_from_kodi_library(videoid): """Remove an item from the Kodi library.""" common.info('Removing {} videoid from Kodi library', videoid) try: kodi_library_items = [get_item(videoid)] if videoid.mediatype == common.VideoId.SHOW or videoid.mediatype == common.VideoId.SEASON: # Retrieve the all episodes in the export folder filters = { 'and': [{ 'field': 'path', 'operator': 'startswith', 'value': os.path.dirname(kodi_library_items[0]['file']) }, { 'field': 'filename', 'operator': 'endswith', 'value': '.strm' }] } if videoid.mediatype == common.VideoId.SEASON: # Add a season filter in case we just want to remove a season filters['and'].append({ 'field': 'season', 'operator': 'is', 'value': str(kodi_library_items[0]['season']) }) kodi_library_items = common.get_library_items( common.VideoId.EPISODE, filters) for item in kodi_library_items: rpc_params = { 'movie': ['VideoLibrary.RemoveMovie', 'movieid'], # We should never remove an entire show # 'show': ['VideoLibrary.RemoveTVShow', 'tvshowid'], # Instead we delete all episodes listed in the JSON query above 'show': ['VideoLibrary.RemoveEpisode', 'episodeid'], 'season': ['VideoLibrary.RemoveEpisode', 'episodeid'], 'episode': ['VideoLibrary.RemoveEpisode', 'episodeid'] }[videoid.mediatype] common.debug(item) common.json_rpc(rpc_params[0], {rpc_params[1]: item[rpc_params[1]]}) except ItemNotFound: common.warn('Cannot remove {} from Kodi library, item not present', videoid) except KeyError as exc: ui.show_notification(common.get_local_string(30120), time=7500) common.warn( 'Cannot remove {} from Kodi library, Kodi does not support this (yet)', exc)
def _find_subtitle_stream(self, audio_language, audio_list): # Check if there is an audio track available in the preferred audio language if not any(audio_track['language'] == audio_language for audio_track in audio_list): # No audio available for the preferred audio language, # then try find a regular subtitle in the preferred audio language subtitles_list = self.player_state.get(STREAMS['subtitle']['list']) # Take in account if a user have enabled Kodi impaired subtitles preference is_prefer_impaired = common.json_rpc( 'Settings.GetSettingValue', { 'setting': 'accessibility.subhearing' }).get('value') stream = next((subtitle_track for subtitle_track in subtitles_list if subtitle_track['language'] == audio_language and not subtitle_track['isforced'] and subtitle_track['isimpaired']), None) if is_prefer_impaired else None if not stream: stream = next((subtitle_track for subtitle_track in subtitles_list if subtitle_track['language'] == audio_language and not subtitle_track['isforced'] and not subtitle_track['isimpaired']), None) return stream return None
def _get_player_state(self, player_id=None): try: player_state = common.json_rpc( 'Player.GetProperties', { 'playerid': self.active_player_id or player_id, 'properties': [ 'audiostreams', 'currentaudiostream', 'currentvideostream', 'subtitles', 'currentsubtitle', 'subtitleenabled', 'percentage', 'time' ] }) except IOError: return {} # Sometime may happen that when you stop playback, a player status without data is read, # so all dict values are returned with a default empty value, # then return an empty status instead of fake data if not player_state['audiostreams']: return {} # convert time dict to elapsed seconds player_state['elapsed_seconds'] = ( player_state['time']['hours'] * 3600 + player_state['time']['minutes'] * 60 + player_state['time']['seconds']) return player_state
def _get_default_audio_language(manifest): channelList = {'1.0': '1', '2.0': '2'} channelListDolby = {'5.1': '6', '7.1': '8'} # Read language in kodi settings audio_language = common.json_rpc('Settings.GetSettingValue', {'setting': 'locale.audiolanguage'}) audio_language = xbmc.convertLanguage(audio_language['value'], xbmc.ISO_639_1) audio_language = audio_language if audio_language else xbmc.getLanguage(xbmc.ISO_639_1, False) audio_language = audio_language if audio_language else 'en' # Try to find the preferred language with the right channels if g.ADDON.getSettingBool('enable_dolby_sound'): for index, audio_track in enumerate(manifest['audio_tracks']): if audio_track['language'] == audio_language and audio_track['channels'] in channelListDolby: return index break # If dolby audio track not exists check other channels list for index, audio_track in enumerate(manifest['audio_tracks']): if audio_track['language'] == audio_language and audio_track['channels'] in channelList: return index break # If there is no matches to preferred language, try to sets the original language track as default # Check if the dolby audio track in selected language exists if g.ADDON.getSettingBool('enable_dolby_sound'): for index, audio_track in enumerate(manifest['audio_tracks']): if audio_track['isNative'] and audio_track['channels'] in channelListDolby: return index break # If dolby audio track not exists check other channels list for index, audio_track in enumerate(manifest['audio_tracks']): if audio_track['isNative'] and audio_track['channels'] in channelList: return index break return 0
def _remove_from_kodi_library(videoid): """Remove an item from the Kodi library.""" common.debug('Removing {} videoid from Kodi library'.format(videoid)) try: kodi_library_item = get_item(videoid) rpc_params = { 'movie': ['VideoLibrary.RemoveMovie', 'movieid'], 'show': ['VideoLibrary.RemoveTVShow', 'tvshowid'], 'episode': ['VideoLibrary.RemoveEpisode', 'episodeid'] }[videoid.mediatype] common.json_rpc(rpc_params[0], {rpc_params[1]: kodi_library_item[rpc_params[1]]}) except ItemNotFound: common.debug( 'Cannot remove {} from Kodi library, item not present'.format( videoid)) except KeyError as exc: ui.show_notification(common.get_local_string(30120), time=7500) common.warn('Cannot remove {} from Kodi library, ' 'Kodi does not support this (yet)'.format(exc))
def auto_scroll(list_data): """ Auto scroll the current viewed list to select the last partial watched or next episode to be watched, works only with Sync of watched status with netflix """ # A sad implementation to a Kodi feature available only for the Kodi library if not g.ADDON.getSettingBool( 'ProgressManager_enabled') or not g.ADDON.getSettingBool( 'select_first_unwatched'): return total_items = len(list_data) if total_items: # Delay a bit to wait for the completion of the screen update xbmc.sleep(100) if not g.KODI_VERSION.is_major_ver( '18'): # These infoLabel not works on Kodi 18.x # Check if view sort method is "Episode" (ID 23 = SortByEpisodeNumber) is_sort_method_episode = xbmc.getCondVisibility( 'Container.SortMethod(23)') if not is_sort_method_episode: return # Check if a selection is already done (CurrentItem return the index) if int(xbmc.getInfoLabel('ListItem.CurrentItem') or 2) > 1: return # Check if all items are already watched watched_items = sum(dict_item['info'].get('PlayCount', '0') != '0' for dict_item in list_data) to_resume_items = sum( dict_item.get('ResumeTime', '0') != '0' for dict_item in list_data) if total_items == watched_items or (watched_items + to_resume_items) == 0: return steps = _find_index_last_watched(total_items, list_data) # Get the sort order of the view is_sort_descending = xbmc.getCondVisibility( 'Container.SortDirection(descending)') if is_sort_descending: steps = (total_items - 1) - steps gui_sound_mode = common.json_rpc( 'Settings.GetSettingValue', {'setting': 'audiooutput.guisoundmode'})['value'] if gui_sound_mode != 0: # Disable GUI sounds to avoid squirting sound with item selections common.json_rpc('Settings.SetSettingValue', { 'setting': 'audiooutput.guisoundmode', 'value': 0 }) # Auto scroll the list for _ in range(0, steps + 1): common.json_rpc('Input.Down') if gui_sound_mode != 0: # Restore GUI sounds common.json_rpc('Settings.SetSettingValue', { 'setting': 'audiooutput.guisoundmode', 'value': gui_sound_mode })
def _get_player_id(): try: retry = 10 while retry: result = common.json_rpc('Player.GetActivePlayers') if result: return result[0]['playerid'] time.sleep(0.1) retry -= 1 LOG.warn('Player ID not obtained, fallback to ID 1') except IOError: LOG.error('Player ID not obtained, fallback to ID 1') return 1
def on_playback_stopped(self, player_state): # It could happen that Kodi does not assign as watched a video, # this because the credits can take too much time, then the point where playback is stopped # falls in the part that kodi recognizes as unwatched (playcountminimumpercent 90% + no-mans land 2%) # https://kodi.wiki/view/HOW-TO:Modify_automatic_watch_and_resume_points#Settings_explained # In these cases we try change/fix manually the watched status of the video by using netflix offset data if int(player_state['percentage']) > 92: return if not self.watched_threshold or not player_state[ 'elapsed_seconds'] > self.watched_threshold: return if G.ADDON.getSettingBool( 'sync_watched_status') and not self.is_played_from_strm: # This have not to be applied with our custom watched status of Netflix sync, within the addon return if self.is_played_from_strm: # The current video played is a STRM, then generate the path of a STRM file file_path = G.SHARED_DB.get_episode_filepath( self.videoid.tvshowid, self.videoid.seasonid, self.videoid.episodeid) url = xbmcvfs.translatePath(file_path) common.json_rpc('Files.SetFileDetails', { "file": url, "media": "video", "resume": None, "playcount": 1 }) else: url = common.build_url( videoid=self.videoid, mode=G.MODE_PLAY, params={'profile_guid': G.LOCAL_DB.get_active_profile_guid()}) common.json_rpc('Files.SetFileDetails', { "file": url, "media": "video", "resume": None, "playcount": 1 }) LOG.info('Has been fixed the watched status of the video: {}', url)
def auto_scroll(dir_items): """ Auto scroll the current viewed list to select the last partial watched or next episode to be watched, works only with Sync of watched status with netflix """ # A sad implementation to a Kodi feature available only for the Kodi library if G.ADDON.getSettingBool( 'sync_watched_status') and G.ADDON.getSettingBool( 'select_first_unwatched'): total_items = len(dir_items) if total_items: # Delay a bit to wait for the completion of the screen update xbmc.sleep(200) if not _auto_scroll_init_checks(): return # Check if all items are already watched watched_items = 0 to_resume_items = 0 for _, list_item, _ in dir_items: watched_items += list_item.getVideoInfoTag().getPlayCount( ) != 0 to_resume_items += float( list_item.getProperty('ResumeTime')) != 0 if total_items == watched_items or (watched_items + to_resume_items) == 0: return steps = _find_index_last_watched(total_items, dir_items) # Get the sort order of the view is_sort_descending = xbmc.getCondVisibility( 'Container.SortDirection(descending)') if is_sort_descending: steps = (total_items - 1) - steps gui_sound_mode = common.json_rpc( 'Settings.GetSettingValue', {'setting': 'audiooutput.guisoundmode'})['value'] if gui_sound_mode != 0: # Disable GUI sounds to avoid squirting sound with item selections common.json_rpc('Settings.SetSettingValue', { 'setting': 'audiooutput.guisoundmode', 'value': 0 }) # Auto scroll the list for _ in range(0, steps + 1): common.json_rpc('Input.Down') if gui_sound_mode != 0: # Restore GUI sounds common.json_rpc('Settings.SetSettingValue', { 'setting': 'audiooutput.guisoundmode', 'value': gui_sound_mode })
def _get_default_subtitle_language(manifest): subtitle_language = common.json_rpc('Settings.GetSettingValue', {'setting': 'locale.subtitlelanguage'}) if subtitle_language['value'] == 'forced_only': # Leave the selection of forced subtitles to kodi return -1 else: subtitle_language = xbmc.convertLanguage(subtitle_language['value'].encode('utf-8'), xbmc.ISO_639_1) subtitle_language = subtitle_language if subtitle_language else xbmc.getLanguage(xbmc.ISO_639_1, False) subtitle_language = subtitle_language if subtitle_language else 'en' for index, text_track in enumerate(manifest['timedtexttracks']): if text_track['isNoneTrack']: continue if not text_track.get('isForcedNarrative') and text_track['language'] == subtitle_language: return index return -1
def _get_player_state(self, player_id=None, time_override=None): try: player_state = common.json_rpc( 'Player.GetProperties', { 'playerid': self.active_player_id if player_id is None else player_id, 'properties': [ 'audiostreams', 'currentaudiostream', 'currentvideostream', 'subtitles', 'currentsubtitle', 'subtitleenabled', 'percentage', 'time' ] }) except IOError as exc: LOG.warn('_get_player_state: {}', exc) return {} # convert time dict to elapsed seconds player_state['elapsed_seconds'] = ( player_state['time']['hours'] * 3600 + player_state['time']['minutes'] * 60 + player_state['time']['seconds']) if time_override: player_state['time'] = time_override elapsed_seconds = (time_override['hours'] * 3600 + time_override['minutes'] * 60 + time_override['seconds']) player_state[ 'percentage'] = player_state['percentage'] / player_state[ 'elapsed_seconds'] * elapsed_seconds player_state['elapsed_seconds'] = elapsed_seconds # Sometimes may happen that when you stop playback the player status is partial, # this is because the Kodi player stop immediately but the stop notification (from the Monitor) # arrives late, meanwhile in this interval of time a service tick may occur. if ((player_state['audiostreams'] and player_state['elapsed_seconds']) or (player_state['audiostreams'] and not player_state['elapsed_seconds'] and not self._last_player_state)): # save player state self._last_player_state = player_state else: # use saved player state player_state = self._last_player_state return player_state
def _seasons(self, videoid, pathitems): """Show the seasons list of a tv show""" call_args = { 'pathitems': pathitems, 'tvshowid_dict': videoid.to_dict(), 'perpetual_range_start': self.perpetual_range_start, } list_data, extra_data = common.make_call('get_seasons', call_args) if len(list_data) == 1: # Check if Kodi setting "Flatten TV show seasons" is enabled value = common.json_rpc('Settings.GetSettingValue', {'setting': 'videolibrary.flattentvshows'}).get('value') if value != 0: # Values: 0=never, 1=if one season, 2=always # If there is only one season, load and show the episodes now pathitems = list_data[0]['url'].replace(G.BASE_URL, '').strip('/').split('/')[1:] videoid = common.VideoId.from_path(pathitems) self._episodes(videoid, pathitems) return self._seasons_directory(list_data, extra_data)
def _get_player_state(self): try: player_state = common.json_rpc( 'Player.GetProperties', { 'playerid': self.active_player_id, 'properties': [ 'audiostreams', 'currentaudiostream', 'subtitles', 'currentsubtitle', 'subtitleenabled', 'percentage', 'time' ] }) except IOError: return {} # convert time dict to elapsed seconds player_state['elapsed_seconds'] = ( player_state['time']['hours'] * 3600 + player_state['time']['minutes'] * 60 + player_state['time']['seconds']) return player_state
def play(videoid): """Play an episode or movie as specified by the path""" is_upnext_enabled = g.ADDON.getSettingBool('UpNextNotifier_enabled') # For db settings 'upnext_play_callback_received' and 'upnext_play_callback_file_type' see action_controller.py is_upnext_callback_received = g.LOCAL_DB.get_value( 'upnext_play_callback_received', False) is_upnext_callback_file_type_strm = g.LOCAL_DB.get_value( 'upnext_play_callback_file_type', '') == 'strm' # This is the only way found to know if the played item come from the add-on itself or from Kodi library # also when Up Next Add-on is used is_played_from_addon = not g.IS_ADDON_EXTERNAL_CALL or ( g.IS_ADDON_EXTERNAL_CALL and is_upnext_callback_received and not is_upnext_callback_file_type_strm) common.info('Playing {} from {} (Is Up Next Add-on call: {})', videoid, 'add-on' if is_played_from_addon else 'external call', is_upnext_callback_received) metadata = [{}, {}] try: metadata = api.get_metadata(videoid) common.debug('Metadata is {}', metadata) except MetadataNotAvailable: common.warn('Metadata not available for {}', videoid) # Parental control PIN pin_result = _verify_pin(metadata[0].get('requiresPin', False)) if not pin_result: if pin_result is not None: ui.show_notification(common.get_local_string(30106), time=8000) xbmcplugin.endOfDirectory(g.PLUGIN_HANDLE, succeeded=False) return list_item = get_inputstream_listitem(videoid) resume_position = None info_data = None event_data = {} videoid_next_episode = None if not is_played_from_addon or is_upnext_enabled: if is_upnext_enabled and videoid.mediatype == common.VideoId.EPISODE: # When UpNext is enabled, get the next episode to play videoid_next_episode = _upnext_get_next_episode_videoid( videoid, metadata) info_data = infolabels.get_info_from_netflix( [videoid, videoid_next_episode] if videoid_next_episode else [videoid]) info, arts = info_data[videoid.value] # When a item is played from Kodi library or Up Next add-on is needed set info and art to list_item list_item.setInfo('video', info) list_item.setArt(arts) if not is_played_from_addon: # Workaround for resuming strm files from library resume_position = ( infolabels.get_resume_info_from_library(videoid).get('position') if g.ADDON.getSettingBool('ResumeManager_enabled') else None) if resume_position: index_selected = (ui.ask_for_resume(resume_position) if g.ADDON.getSettingBool('ResumeManager_dialog') else None) if index_selected == -1: xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE, succeeded=False, listitem=list_item) return if index_selected == 1: resume_position = None if (g.ADDON.getSettingBool('ProgressManager_enabled') and videoid.mediatype in [common.VideoId.MOVIE, common.VideoId.EPISODE] and is_played_from_addon): # Enable the progress manager only when: # - It is not an add-on external call # - It is an external call, but the played item is not a STRM file # Todo: # in theory to enable in Kodi library need implement the update watched status code for items of Kodi library # by using JSON RPC Files.SetFileDetails https://github.com/xbmc/xbmc/pull/17202 # that can be used only on Kodi 19.x event_data = _get_event_data(videoid) event_data['videoid'] = videoid.to_dict() event_data['is_played_by_library'] = not is_played_from_addon if 'raspberrypi' in common.get_system_platform( ) and g.KODI_VERSION.is_major_ver('18'): # OMX Player is not compatible with netflix video streams # Only Kodi 18 has this property, on Kodi 19 Omx Player has been removed value = common.json_rpc('Settings.GetSettingValue', {'setting': 'videoplayer.useomxplayer'}) if value.get('value'): common.json_rpc('Settings.SetSettingValue', { 'setting': 'videoplayer.useomxplayer', 'value': False }) xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE, succeeded=True, listitem=list_item) g.LOCAL_DB.set_value('last_videoid_played', videoid.to_dict(), table=TABLE_SESSION) common.debug('Sending initialization signal') common.send_signal(common.Signals.PLAYBACK_INITIATED, { 'videoid': videoid.to_dict(), 'videoid_next_episode': videoid_next_episode.to_dict() if videoid_next_episode else None, 'metadata': metadata, 'info_data': info_data, 'is_played_from_addon': is_played_from_addon, 'resume_position': resume_position, 'event_data': event_data, 'is_upnext_callback_received': is_upnext_callback_received }, non_blocking=True)
def play(videoid): """Play an episode or movie as specified by the path""" common.info('Playing {}', videoid) is_up_next_enabled = g.ADDON.getSettingBool('UpNextNotifier_enabled') metadata = [{}, {}] try: metadata = api.metadata(videoid) common.debug('Metadata is {}', metadata) except MetadataNotAvailable: common.warn('Metadata not available for {}', videoid) # Parental control PIN pin_result = _verify_pin(metadata[0].get('requiresPin', False)) if not pin_result: if pin_result is not None: ui.show_notification(common.get_local_string(30106), time=10000) xbmcplugin.endOfDirectory(g.PLUGIN_HANDLE, succeeded=False) return list_item = get_inputstream_listitem(videoid) infos, art = infolabels.add_info_for_playback( videoid, list_item, is_up_next_enabled, skip_set_progress_status=True) resume_position = {} event_data = {} if g.IS_SKIN_CALL: # Workaround for resuming strm files from library resume_position = infos.get('resume', {}).get('position') \ if g.ADDON.getSettingBool('ResumeManager_enabled') else None if resume_position: index_selected = ui.ask_for_resume( resume_position) if g.ADDON.getSettingBool( 'ResumeManager_dialog') else None if index_selected == -1: xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE, succeeded=False, listitem=list_item) return if index_selected == 1: resume_position = None elif (g.ADDON.getSettingBool('ProgressManager_enabled') and videoid.mediatype in [common.VideoId.MOVIE, common.VideoId.EPISODE]): # To now we have this limits: # - enabled only with items played inside the addon then not Kodi library, need impl. JSON-RPC lib update code event_data = _get_event_data(videoid) event_data['videoid'] = videoid.to_dict() event_data['is_played_by_library'] = g.IS_SKIN_CALL # Todo: UpNext addon is incompatible with netflix watched status sync feature # Problems: # - Need to modify the cache (to update the watched status) on every played item # - Modifying the cache after the stop, is wrong due to below problems # - The new fast play, 'play_url' method, cause problems with the Player callbacks, after press play next is missing the Stop event in the controller! # - To verify possibility problems of data mixing of controller._get_player_state() # - The call of next video from UpNext is recognized as Skin call, because it's an external addon call, so it causes several operating problems is_up_next_enabled = False if 'raspberrypi' in common.get_system_platform( ) and '18' in common.GetKodiVersion().version: # OMX Player is not compatible with netflix video streams # Only Kodi 18 has this property, on Kodi 19 Omx Player has been removed value = common.json_rpc('Settings.GetSettingValue', {'setting': 'videoplayer.useomxplayer'}) if value.get('value'): common.json_rpc('Settings.SetSettingValue', { 'setting': 'videoplayer.useomxplayer', 'value': False }) xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE, succeeded=True, listitem=list_item) upnext_info = get_upnext_info(videoid, (infos, art), metadata) if is_up_next_enabled else None g.LOCAL_DB.set_value('last_videoid_played', videoid.to_dict(), table=TABLE_SESSION) common.debug('Sending initialization signal') common.send_signal(common.Signals.PLAYBACK_INITIATED, { 'videoid': videoid.to_dict(), 'infos': infos, 'art': art, 'timeline_markers': get_timeline_markers(metadata[0]), 'upnext_info': upnext_info, 'resume_position': resume_position, 'event_data': event_data }, non_blocking=True)
def search_remove(row_id): """Remove a search item""" LOG.debug('Removing search item with ID {}', row_id) G.LOCAL_DB.delete_search_item(row_id) common.json_rpc('Input.Down') # Avoids selection back to the top common.container_refresh()