Пример #1
0
def play_trailers():
    # type: () -> None
    """

    :return:
    """
    my_trailer_dialog = None
    black_background = None
    exiting_playing_movie = False
    try:
        black_background = BlackBackground.get_instance()
        black_background.show()
        legal_info = LegalInfo('legal.xml', Constants.ADDON_PATH, 'Default')
        legal_info.show()
        Monitor.throw_exception_if_abort_requested(timeout=10.0)
        legal_info.close()
        legal_info.destroy()
        my_trailer_dialog = TrailerDialog('script-trailerwindow.xml',
                                          Constants.ADDON_PATH, 'Default')
        exiting_playing_movie = my_trailer_dialog.doModal()
    finally:
        if my_trailer_dialog is not None:
            del my_trailer_dialog
            my_trailer_dialog = None
        if black_background is not None:
            black_background.destroy()
            del black_background
            black_background = None
        if exiting_playing_movie:
            if logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
                logger.debug('ReplaceWindow(12005)')
            xbmc.executebuiltin('ReplaceWindow(12005)')
    def returned_trailer(cls, data):
        # type: (Any) -> None
        """
            Front-end receives trailer from back-end

        :param data:
        :return:
        """
        try:
            Monitor.throw_exception_if_abort_requested()
            cls._next_trailer = data.get('trailer', None)
            cls._status = data.get('status', None)
            if cls._status == FrontendBridgeStatus.BUSY:
                Monitor.throw_exception_if_abort_requested(timeout=2.0)
            elif cls._logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
                if cls._next_trailer is None:
                    title = 'No Trailer Received'
                else:
                    title = cls._next_trailer.get(Movie.TITLE, 'No Title')
                cls._logger.debug_extra_verbose('status:', cls._status,
                                                'received trailer for:', title)
        except AbortException:
            reraise(*sys.exc_info())
        except Exception as e:
            cls._logger.exception('')
    def run_worker(self) -> None:
        clz = RunCommand
        rc = 0
        env = os.environ.copy()
        try:
            if xbmc.getCondVisibility('System.Platform.Windows'):
                # Prevent console for ffmpeg from opening

                self.process = subprocess.Popen(
                    self.args, stdin=None, stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE, shell=False, universal_newlines=True, env=env,
                    close_fds=True, creationflags=subprocess.DETACHED_PROCESS)
            else:
                self.process = subprocess.Popen(
                    self.args, stdin=None, stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE, shell=False, universal_newlines=True, env=env,
                    close_fds=True)
            self.stdout_thread = threading.Thread(target=self.stdout_reader,
                                                  name='normalize stdout reader')
            Monitor.throw_exception_if_abort_requested()
            self.stdout_thread.start()

            self.stderr_thread = threading.Thread(target=self.stderr_reader,
                                                  name='normalize stderr reader')
            self.stderr_thread.start()
        except AbortException as e:
            pass  # Let thread die
        except Exception as e:
            clz.logger.exception(e)
    def save_cache(cls):
        # type: () -> None
        """

        :return:
        """

        path = os.path.join(Settings.get_remote_db_cache_path(), 'index',
                            'tmdb_discovery_parameters.json')
        path = xbmcvfs.validatePath(path)
        parent_dir, file_name = os.path.split(path)
        if not os.path.exists(parent_dir):
            DiskUtils.create_path_if_needed(parent_dir)

        with CacheIndex.lock:
            try:
                Monitor.throw_exception_if_abort_requested()

                with io.open(
                        path,
                        mode='wt',
                        newline=None,
                        encoding='utf-8',
                ) as cacheFile:
                    json_text = cls.to_json()
                    cacheFile.write(json_text)
                    cacheFile.flush()
            except AbortException:
                reraise(*sys.exc_info())
            except (IOError) as e:
                cls._logger.exception('')
            except Exception as e:
                cls._logger.exception('')
    def get(self,
            block: bool = True,
            timeout: Optional[float] = None) -> Union[MovieType, None]:
        """

        :param block:
        :param timeout:
        :return:
        """
        if not block:
            timeout = 0

        if timeout is None:
            timeout = float(60 * 60 * 24 * 365)  # A year
        time_remaining = timeout
        time_chunk = 0.01
        finished = False
        item = None
        while not finished:
            try:
                with self._lock:
                    item = self._wrapped_queue.get(block=False)
                finished = True
            except KodiQueue.Empty:
                Monitor.throw_exception_if_abort_requested(timeout=time_chunk)
                time_remaining -= time_chunk
                if time_remaining <= 0:
                    raise KodiQueue.Empty

        return item
def load_trailers() -> None:
    """
        Start up the configured trailer discovery threads.

        Called whenever settings have changed to start any threads
        that have just ben enabled.

    :return:
    """

    module_logger.enter()

    if Settings.get_include_library_trailers():
        lib_instance = DiscoverLibraryMovies()
        lib_instance.discover_basic_information()

    # Manufacture trailer entries for folders which contain trailer
    # files. Note that files are assumed to be videos.
    if Settings.get_include_trailer_folders():
        DiscoverFolderTrailers().discover_basic_information()

    if Settings.get_include_itunes_trailers():
        DiscoverItunesMovies().discover_basic_information()

    if Settings.get_include_tmdb_trailers():
        DiscoverTmdbMovies().discover_basic_information()

    if Settings.is_include_tfh_trailers():
        DiscoverTFHMovies().discover_basic_information()

    Monitor.throw_exception_if_abort_requested(timeout=1.0)
    Monitor.set_startup_complete()
Пример #7
0
    def get_from_fetch_queue(self, player_starving: bool = False) -> MovieType:
        """

        :return:
        """
        clz = AbstractMovieData
        # if self.logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
        #     self.logger.debug_extra_verbose('starving:', player_starving)
        self.load_fetch_queue()
        trailer = None
        if self._trailers_to_fetch_queue.empty():
            if self.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
                self.logger.debug_verbose(': empty')
        while trailer is None:
            try:
                if player_starving:
                    trailer = self.get_from_starvation_queue()
                if trailer is None:
                    trailer = self._trailers_to_fetch_queue.get(timeout=0.5)
            except KodiQueue.Empty:
                Monitor.throw_exception_if_abort_requested()

        if self.logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
            self.logger.debug_extra_verbose(
                'Got:', trailer[Movie.TITLE], 'from fetch queue')

        return trailer
Пример #8
0
    def delay_between_transactions(cls, source: str, video: bool) -> None:
        if video:
            delay_range = DOWNLOAD_VIDEO_DELAY_BY_SOURCE[source]
        else:
            delay_range = DOWNLOAD_INFO_DELAY_BY_SOURCE[source]
        delay = cls.get_delay(delay_range)
        # min_time_between_requests = datetime.timedelta(seconds=10.0)

        try:
            cls.get_lock(source)  # Block new transaction
            # HAVE LOCK
            if source == Movie.ITUNES_SOURCE:
                waited: datetime.timedelta = (
                    datetime.datetime.now() -
                    cls._last_itunes_request_timestamp)
            else:
                waited: datetime.timedelta = (
                    datetime.datetime.now() -
                    cls._last_youtube_request_timestamp)
            time_to_wait = delay - waited.total_seconds()
            if time_to_wait > 0.0:
                Monitor.throw_exception_if_abort_requested(time_to_wait)

        finally:
            cls.release_lock(source)

        # LOCK RELEASED

        if source == Movie.ITUNES_SOURCE:
            cls._last_itunes_request_timestamp = datetime.datetime.now()
        else:
            cls._last_youtube_request_timestamp = datetime.datetime.now()
Пример #9
0
    def status_hook(self, status: Dict[str, str]) -> None:
        clz = BaseInfoHook
        if Monitor.is_abort_requested():
            self._callback._error = 99
            # Kill YoutubeDL
            Monitor.throw_exception_if_abort_requested()

        status_str = status.get('status', 'missing status')
        if status_str is None:
            clz._logger.debug('Missing status indication')
        elif status_str == 'downloading':
            self._download_eta = status.get('eta', 0)  # In seconds
        elif status_str == 'error':
            clz._logger.error('Status:', str(status))
            self.error_lines.append('Error downloading')
            self._error = VideoDownloader.DOWNLOAD_ERROR
        elif status_str == 'finished':
            filename = status.get('filename')
            tmpfilename = status.get('tmpfilename')
            downloaded_bytes = status.get('downloaded_bytes')
            total_bytes = status.get('total_bytes')
            total_bytes_estimate = status.get('total_bytes_estimate')
            elapsed = status.get('elapsed')
            eta = status.get('eta')
            speed = status.get('speed')
            fragment_index = status.get('fragment_index')
            fragment_count = status.get('fragment_count')

            clz._logger.debug('Finished')
    def load_unprocessed_movie_cache(cls):
        # type: () -> None
        """

        :return:
        """
        path = os.path.join(Settings.get_remote_db_cache_path(), 'index',
                            'tmdb_unprocessed_movies.json')
        path = xbmcvfs.validatePath(path)
        try:
            parent_dir, file_name = os.path.split(path)
            DiskUtils.create_path_if_needed(parent_dir)
            with CacheIndex.lock:
                if os.path.exists(path):
                    with io.open(path,
                                 mode='rt',
                                 newline=None,
                                 encoding='utf-8') as cacheFile:
                        cls._unprocessed_movies = json.load(
                            cacheFile,
                            encoding='utf-8',
                            object_hook=CacheIndex.datetime_parser)
                        cls.last_saved_movie_timestamp = None
                        cls._unprocessed_movie_changes = 0
                else:
                    cls._unprocessed_movies = {}
            Monitor.throw_exception_if_abort_requested()
        except AbortException:
            reraise(*sys.exc_info())
        except IOError as e:
            CacheIndex.logger().exception('')
        except JSONDecodeError as e:
            os.remove(path)
        except Exception as e:
            CacheIndex.logger().exception('')
    def play(self, item="", listitem=None, windowed=False, startpos=-1):
        # type: (Union[PlayList], 'xbmcgui.ListItem', bool, int) ->None
        """
        Play a item.

        :param item: [opt] string - filename, url or playlist
        :param listitem: [opt] listitem - used with setInfo() to set different
            infolabels.
        :param windowed: [opt] bool - true=play video windowed,
            false=play users preference.(default)
        :param startpos: [opt] int - starting position when playing a playlist.
            Default = -1

        If item is not given then the Player will try to play the current item
        in the current playlist. You can use the above as keywords for arguments
        and skip certain optional arguments. Once you use a keyword,
        all following arguments require the keyword.

        Example::

            listitem = xbmcgui.ListItem('Ironman')
            listitem.setInfo('video', {'Title': 'Ironman', 'Genre': 'Science Fiction'})
            xbmc.Player().play(url, listitem, windowed)
            xbmc.Player().play(playlist, listitem, windowed, startpos)
        """
        local_class = AdvancedPlayer

        Monitor.throw_exception_if_abort_requested()

        if type(self).DEBUG_MONITOR:
            local_class._logger.enter()
        super().play(item, listitem, windowed, startpos)
        self.enableAdvancedMonitoring()
    def __next__(self):
        # type: () -> Union[dict, None]
        """

        :return:
        """
        movie = None
        try:
            finished = False
            attempt = 0
            while not finished:
                try:
                    attempt += 1
                    movie = self._do_next()
                    finished = True
                except RestartDiscoveryException:
                    Monitor.throw_exception_if_abort_requested(timeout=0.10)
                    if self.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
                        self.logger.debug_verbose(
                            'Rediscovery in progress. attempt:', attempt)
        except Exception as e:
            self.logger.exception('')
            reraise(*sys.exc_info())

        return movie
    def save_unprocessed_movie_cache(cls, flush=False):
        # type: (bool) -> None
        """
        :param flush:
        :return:
        """

        #  TODO: Should use lock here, review locking
        with cls.lock:
            if cls._unprocessed_movie_changes == 0:
                return

            if (not flush and
                    # Constants.TRAILER_CACHE_FLUSH_UPDATES)
                    (cls._unprocessed_movie_changes < 10)
                    and
                    (datetime.datetime.now() - \
                     cls._last_saved_unprocessed_movie_timestamp)
                    < datetime.timedelta(minutes=5)):
                return

            path = os.path.join(Settings.get_remote_db_cache_path(), 'index',
                                'tmdb_unprocessed_movies.json')
            path = xbmcvfs.validatePath(path)
            parent_dir, file_name = os.path.split(path)
            if not os.path.exists(parent_dir):
                DiskUtils.create_path_if_needed(parent_dir)

            try:
                with io.open(
                        path,
                        mode='wt',
                        newline=None,
                        encoding='utf-8',
                ) as cacheFile:

                    # TODO: Need ability to interrupt when ABORT. Object_handler
                    # not a valid arg to dumps

                    json_text = json.dumps(cls.get_unprocessed_movies(),
                                           encoding='utf-8',
                                           ensure_ascii=False,
                                           default=CacheIndex.handler,
                                           indent=3,
                                           sort_keys=True)
                    cacheFile.write(json_text)
                    cacheFile.flush()
                    cls._last_saved_unprocessed_movie_timestamp = datetime.datetime.now(
                    )
                    cls._unprocessed_movie_changes = 0

                    Monitor.throw_exception_if_abort_requested()

            except AbortException:
                reraise(*sys.exc_info())
            except IOError as e:
                cls.logger().exception('')
            except Exception as e:
                cls.logger().exception('')
    def abort_checker(dct: Dict[str, Any]) -> Dict[str, Any]:
        """

        :param dct:
        :return:
        """
        Monitor.throw_exception_if_abort_requested()
        return dct
    def add_to_ready_to_play_queue(self, movie: MovieType) -> None:
        """

        :param movie:
        :return:
        """
        clz = PlayableTrailersContainer
        if clz.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
            if Movie.TITLE not in movie:
                clz.logger.warning('Invalid movie entry. Missing title: ',
                                   str(movie))
            Debug.validate_detailed_movie_properties(movie, stack_trace=False)
        try:
            title = movie[Movie.TITLE]
            if title not in clz._recently_played_trailers:
                clz._recently_played_trailers[title] = movie
                if len(clz._recently_played_trailers) > 10:
                    clz._recently_played_trailers.popitem()
            else:
                if clz.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
                    clz.logger.debug_verbose(
                        f'Movie: {title} played recently, skipping')

                return
        except Exception as e:
            clz.logger.exception(e)

        if clz.logger.isEnabledFor(LazyLogger.DEBUG):
            clz.logger.debug_verbose('movie:', movie[Movie.TITLE],
                                     'queue empty:',
                                     self._ready_to_play_queue.empty(),
                                     'full:', self._ready_to_play_queue.full())

        finished = False
        waited = 0
        while not finished:
            try:
                self._ready_to_play_queue.put(movie, block=True, timeout=0.05)
                finished = True
                self._number_of_added_trailers += 1
            except (queue.Full):
                waited += 1

            Monitor.throw_exception_if_abort_requested(timeout=0.5)

        if not clz._any_trailers_available_to_play.isSet():
            if clz.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
                clz.logger.debug_verbose(
                    'Setting _any_trailers_available_to_play')
            clz._any_trailers_available_to_play.set()

        self._is_playable_trailers.set()

        if clz.logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
            clz.logger.debug_extra_verbose('readyToPlayQueue size:',
                                           self._ready_to_play_queue.qsize(),
                                           'waited:', waited)
        return
    def monitor(self):
        Monitor.throw_exception_if_abort_requested()
        if not self._monitor_thread or not self._monitor_thread.isAlive():
            if self._monitor_thread:
                self._monitor_thread.join()

            self._monitor_thread = threading.Thread(
                target=self._monitor, name='AdvancedPlayer:MONITOR')
            self._monitor_thread.start()
    def save_search_pages(self, flush=False):
        # type: (bool) -> None
        """

        :return:
        """
        with CacheIndex.lock:
            if (not flush and self.get_number_of_unsaved_changes() <
                    Constants.TRAILER_CACHE_FLUSH_UPDATES
                    and self.get_time_since_last_save() <
                    datetime.timedelta(minutes=5)):
                return
            saved_pages = len(self._cached_page_by_key.items())
            path = xbmcvfs.validatePath(self._path)
            temp_path = xbmcvfs.validatePath(self._temp_path)
            try:
                parent_dir, file_name = os.path.split(path)
                DiskUtils.create_path_if_needed(parent_dir)

                Monitor.throw_exception_if_abort_requested()
                with io.open(temp_path,
                             mode='wt',
                             newline=None,
                             encoding='utf-8') as cacheFile:
                    json_dict = self.to_json()

                    # TODO: Need ability to interrupt when ABORT. Object_handler
                    # not a valid arg to dumps

                    json_text = json.dumps(json_dict,
                                           encoding='utf-8',
                                           ensure_ascii=False,
                                           default=CacheIndex.handler,
                                           indent=3,
                                           sort_keys=True)
                    cacheFile.write(json_text)
                    cacheFile.flush()
                    self._number_of_unsaved_changes = 0
                    self._time_of_last_save = datetime.datetime.now()

                try:
                    os.replace(temp_path, path)
                except OSError:
                    self._logger.exception(
                        f'Failed to replace move information'
                        f' planned for download: {path}')
                Monitor.throw_exception_if_abort_requested()
            except AbortException:
                reraise(*sys.exc_info())
            except IOError as e:
                self._logger.exception('')
            except JSONDecodeError as e:
                os.remove(path)
            except Exception as e:
                self._logger.exception('')

        self._logger.debug_verbose("Entries Saved: ", saved_pages)
Пример #18
0
    def get_lock(cls, source: str):
        lock_source = cls.get_lock_source(source)
        if cls._logger.isEnabledFor(LazyLogger.DISABLED):
            cls._logger.debug_extra_verbose(f'Getting Lock: {lock_source} '
                                            f'for {source}')

        while not cls.locks[source].acquire(blocking=False):
            Monitor.throw_exception_if_abort_requested(timeout=0.5)

        if cls._logger.isEnabledFor(LazyLogger.DISABLED):
            cls._logger.debug_extra_verbose(f'Got Lock: {source}')
Пример #19
0
    def warning(self, line: str) -> None:
        if Monitor.is_abort_requested():
            self._callback._error = 99
            # Kill YoutubeDL
            Monitor.throw_exception_if_abort_requested()

        if 'merged' in line:
            # str: Requested formats are incompatible for merge and will be merged into
            # mkv.
            pass
        else:
            self.warning_lines.append(line)
Пример #20
0
    def wait_if_too_many_requests(cls, source: str, video: bool) -> None:
        if source == Movie.ITUNES_SOURCE:
            return

        delay = cls.get_youtube_wait_seconds()
        if delay <= 0.0:
            return

        cls._logger.debug(f'Waiting for TOO_MANY_REQUESTS: {delay} seconds.')
        delay = cls.get_youtube_wait_seconds()
        if delay > 0.0:
            Monitor.throw_exception_if_abort_requested(delay)
            cls._logger.debug('Wait for TOO_MANY_REQUESTS complete')
Пример #21
0
    def handler(obj: Any) -> Any:
        """

        :param obj:
        :return:
        """
        Monitor.throw_exception_if_abort_requested()
        if hasattr(obj, 'isoformat'):
            return obj.isoformat()
        else:
            raise TypeError(
                'Object of type %s with value of %s is not JSON serializable' %
                (type(obj), repr(obj)))
    def read_cached_value_from_disk(cls):
        # type: () -> CacheParameters
        """

        :return:
        """

        path = os.path.join(Settings.get_remote_db_cache_path(), 'index',
                            'tmdb_discovery_parameters.json')
        path = xbmcvfs.validatePath(path)
        parent_dir, file_name = os.path.split(path)
        if not os.path.exists(parent_dir):
            DiskUtils.create_path_if_needed(parent_dir)

        saved_preferences = None
        with CacheIndex.lock:
            try:
                if not os.access(path, os.R_OK):
                    cls._logger.error(
                        Messages.get_formatted_msg(Messages.CAN_NOT_READ_FILE,
                                                   path))
                    return None

                file_mod_time = datetime.datetime.fromtimestamp(
                    os.path.getmtime(path))
                now = datetime.datetime.now()
                expiration_time = now - datetime.timedelta(
                    Settings.get_expire_remote_db_cache_entry_days())

                if file_mod_time < expiration_time:
                    if cls._logger.isEnabledFor(LazyLogger.DEBUG):
                        cls._logger.debug('cache file EXPIRED for:', path)
                    return None

                Monitor.throw_exception_if_abort_requested()

                with io.open(path, mode='rt', newline=None,
                             encoding='utf-8') as cacheFile:
                    saved_preferences = json.load(cacheFile, encoding='utf-8')
                    saved_preferences = CacheParameters(saved_preferences)
            except AbortException:
                reraise(*sys.exc_info())
            except IOError as e:
                cls._logger.exception('')
                exception_occurred = True
            except Exception as e:
                cls._logger.exception('')
                exception_occurred = True

        return saved_preferences
Пример #23
0
    def unregister_slot(cls, signaler_id, signal):
        # type: (str, str) -> None
        """

        :param signaler_id:
        :param signal:
        :return:
        """

        Monitor.throw_exception_if_abort_requested()
        try:
            AddonSignals.unRegisterSlot(signaler_id, signal)
        except Exception:
            pass
    def save_found_trailer_ids_cache(cls, flush=False):
        # type: (bool) -> None
        """
        :param flush:
        :return:
        """
        with cls.lock:
            if cls._unsaved_trailer_changes == 0:
                return

            if (not flush and (cls._unsaved_trailer_changes <
                               Constants.TRAILER_CACHE_FLUSH_UPDATES) and
                (datetime.datetime.now() - cls._last_saved_trailer_timestamp) <
                    datetime.timedelta(minutes=5)):
                return

            path = os.path.join(Settings.get_remote_db_cache_path(), 'index',
                                'tmdb_found_trailers.json')
            path = xbmcvfs.validatePath(path)
            parent_dir, file_name = os.path.split(path)
            if not os.path.exists(parent_dir):
                DiskUtils.create_path_if_needed(parent_dir)
                try:
                    with io.open(
                            path,
                            mode='wt',
                            newline=None,
                            encoding='utf-8',
                    ) as cacheFile:
                        found_trailer_id_list = list(
                            cls._found_tmdb_trailer_ids)
                        json_text = json.dumps(found_trailer_id_list,
                                               encoding='utf-8',
                                               ensure_ascii=False,
                                               default=CacheIndex.handler,
                                               indent=3,
                                               sort_keys=True)
                        cacheFile.write(json_text)
                        cacheFile.flush()
                        cls._last_saved_trailer_timestamp = datetime.datetime.now(
                        )
                        cls._unsaved_trailer_changes = 0

                    Monitor.throw_exception_if_abort_requested()
                except AbortException:
                    reraise(*sys.exc_info())
                except IOError as e:
                    CacheIndex.logger().exception('')
                except Exception as e:
                    CacheIndex.logger().exception('')
    def throw_exception_on_forced_to_stop(self,
                                          movie_data: AbstractMovieData = None,
                                          delay: float = 0) -> None:
        """

        :param movie_data:
        :param delay:
        :return:
        """
        Monitor.throw_exception_if_abort_requested(timeout=delay)
        if movie_data is not None and movie_data.restart_discovery_event.isSet(
        ):
            if self.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE):
                self.logger.debug_verbose('RestartDiscoveryException source:',
                                          movie_data.get_movie_source())
            raise RestartDiscoveryException()
    def shuffle_discovered_trailers(self, mark_unplayed=False):
        # type: (bool) -> None
        """

        :param mark_unplayed:
        :return:
        """
        clz = AbstractMovieData

        Monitor.throw_exception_if_abort_requested()
        # clz.logger.debug('before self.lock')

        with self._discovered_trailers_lock:
            # clz.logger.debug('Have discovered_trailers_lock')

            if self._discovered_trailers.len() == 0:
                return

            self._discovered_trailers.shuffle()
            if mark_unplayed:
                for trailer in self._discovered_trailers.get_trailers():
                    trailer[Movie.TRAILER_PLAYED] = False

            self._last_shuffled_index = self._discovered_trailers.len() - 1
            self._last_shuffle_time = datetime.datetime.now()

            # Drain anything previously in queue

            self._discovered_trailers_queue.clear()

            Monitor.throw_exception_if_abort_requested()
            # clz.logger.debug('reloading _discovered_trailers_queue')
            for trailer in self._discovered_trailers.get_trailers():
                if not trailer[Movie.TRAILER_PLAYED]:
                    # if clz.logger.isEnabledFor(LazyLogger.DEBUG):
                    #   clz.logger.debug('adding', trailer[Movie.TITLE],
                    #                      'id:', hex(id(trailer)),
                    #                      'to discovered_trailers_queue',
                    #                      'state:', trailer[Movie.DISCOVERY_STATE])
                    self._discovered_trailers_queue.put(trailer)

            if clz.logger.isEnabledFor(LazyLogger.DISABLED):
                clz.logger.debug_extra_verbose(
                    '_discoveredTrailerQueue length:',
                    self._discovered_trailers_queue.qsize(),
                    '_discovered_trailers length:',
                    len(self._discovered_trailers))
    def throw_exception_on_forced_to_stop(self, delay=0):
        # type: (float) -> None
        """

        :param delay:
        :return:
        """
        clz = BaseDiscoverMovies

        try:
            Monitor.throw_exception_if_abort_requested(timeout=delay)
            if self._movie_data.restart_discovery_event.isSet():
                raise RestartDiscoveryException()
        except AbortException:
            if clz.logger.is_trace_enabled(Trace.TRACE_PLAY_STATS):
                PlayStatistics.report_play_count_stats()
            reraise(*sys.exc_info())
Пример #28
0
    def register_slot(cls, signaler_id, signal, callback):
        # type: (str, str, Callable[[Any], None]) -> None
        """

        :param signaler_id:
        :param signal:
        :param callback:
        :return:
        """
        if PluginBridge._logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
            PluginBridge._logger.debug_extra_verbose('signaler_id:',
                                                     signaler_id, 'signal:',
                                                     signal, 'callback:',
                                                     callback.__name__)
        Monitor.throw_exception_if_abort_requested()
        AddonSignals.registerSlot(signaler_id, signal, callback)
        PluginBridge._registered_slots.append((signaler_id, signal))
    def get_next_trailer(cls):
        # type: () -> (Union[str, None], Union[Dict[str, Any], None])
        """
         front-end requests a trailer from the back-end and waits for
            response.

        :return:
        """
        try:
            signal_payload = {}
            cls.send_signal('get_next_trailer',
                            data=signal_payload,
                            source_id=Constants.BACKEND_ID)

            # It can take some time before we get responses back
            # Wait max 30 seconds

            # TODO: handle case where there are NO trailers to play
            # Also, server should send ack on receipt of this request

            cls._status = FrontendBridgeStatus.BUSY
            count = 0
            while cls._status == FrontendBridgeStatus.BUSY and count < 300:
                Monitor.throw_exception_if_abort_requested(timeout=0.10)
                count += 1

            if count >= 300:
                cls._logger.error('Timed out waiting on get_next_trailer')
                cls._next_trailer = None
                cls._status = FrontendBridgeStatus.TIMED_OUT

            trailer = cls._next_trailer
            status = cls._status
            cls._next_trailer = None
            cls._status = FrontendBridgeStatus.IDLE
            if trailer is not None:
                if cls._logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
                    cls._logger.debug_extra_verbose('returning status:',
                                                    status, 'title:',
                                                    trailer[Movie.TITLE])
            return status, trailer
        except AbortException:
            cls.delete_instance()
            reraise(*sys.exc_info())
        except Exception as e:
            cls._logger.exception('')
Пример #30
0
    def wrap_text(cls, movies_with_same_count: List[str],
                  include_source: bool = False) -> None:
        """

        :param logger:
        :param movies_with_same_count:
        :param include_source:
        :return:
        """
        clz = PlayStatistics

        movies_in_line: List[str] = []
        line_length = 3  # Initial spaces
        movie_title: str = ''
        for key in movies_with_same_count:
            Monitor.throw_exception_if_abort_requested()
            try:
                movie: Optional[MovieType] = cls._key_to_movie.get(key, None)
                if movie is not None:
                    movie_title = movie.get(Movie.TITLE, 'unknown')
                else:
                    movie_title = 'Not in dictionary'
                if include_source:
                    movie_title = movie_title + f': {movie.get(Movie.SOURCE)}'

                if line_length + len(movie_title) >= clz.MAX_LINE_LENGTH:
                    line = '   {}\n'.format(', '.join(movies_in_line))
                    cls.report.write(line)
                    del movies_in_line[:]
                    line_length = 3  # Initial spaces

            except AbortException:
                reraise(*sys.exc_info())

            except Exception as e:
                clz.logger.exception()

            movies_in_line.append(movie_title)
            line_length += len(movie_title) + 2  # Slightly inaccurate

        if len(movies_in_line) > 0:
            try:
                line = '   {}\n'.format(', '.join(movies_in_line))
                cls.report.write(line)
            except Exception as e:
                clz.logger.exception()