Exemple #1
0
    def _process_events(self, status: dict, last_status: dict):
        if not status:
            self._fire_event(TorrentRemovedEvent(**last_status))
            return

        if not last_status:
            self._fire_event(TorrentQueuedEvent(**status))

        progress = status.get('progress', 0)
        name = status.get('name')
        start_date = status.get('start_date')
        finish_date = status.get('finish_date')
        is_active = status.get('is_active')

        if name and not last_status.get('name'):
            self._fire_event(TorrentDownloadedMetadataEvent(**status))

        if start_date and not last_status.get('start_date'):
            self._fire_event(TorrentDownloadStartEvent(**status))

        if is_active and not last_status.get('is_active'):
            self._fire_event(TorrentResumedEvent(**status))
        elif not is_active and last_status.get('is_active'):
            self._fire_event(TorrentPausedEvent(**status))

        if progress > 0:
            if progress > last_status.get('progress', 0):
                self._fire_event(TorrentDownloadProgressEvent(**status))

        if finish_date and not last_status.get('finish_date'):
            self._fire_event(TorrentDownloadCompletedEvent(**status))
Exemple #2
0
        def thread():
            files = []
            last_status = None
            download_started = False
            metadata_downloaded = False

            while not transfer.is_finished():
                if torrent not in self.transfers:
                    self.logger.info(
                        'Torrent {} has been stopped and removed'.format(
                            torrent))
                    self._fire_event(TorrentDownloadStopEvent(url=torrent),
                                     event_hndl)
                    break

                status = transfer.status()
                torrent_file = transfer.torrent_file()

                if torrent_file:
                    self.torrent_state[torrent][
                        'size'] = torrent_file.total_size()
                    files = [
                        os.path.join(download_dir,
                                     torrent_file.files().file_path(i))
                        for i in range(0,
                                       torrent_file.files().num_files())
                    ]

                    if is_media:
                        from platypush.plugins.media import MediaPlugin
                        # noinspection PyProtectedMember
                        files = [
                            f for f in files if MediaPlugin._is_video_file(f)
                        ]

                self.torrent_state[torrent][
                    'download_rate'] = status.download_rate
                self.torrent_state[torrent]['name'] = status.name
                self.torrent_state[torrent]['num_peers'] = status.num_peers
                self.torrent_state[torrent]['paused'] = status.paused
                self.torrent_state[torrent]['progress'] = round(
                    100 * status.progress, 2)
                self.torrent_state[torrent]['state'] = status.state.name
                self.torrent_state[torrent]['title'] = status.name
                self.torrent_state[torrent]['torrent'] = torrent
                self.torrent_state[torrent]['upload_rate'] = status.upload_rate
                self.torrent_state[torrent]['url'] = torrent
                self.torrent_state[torrent]['files'] = files

                if transfer.has_metadata() and not metadata_downloaded:
                    self._fire_event(
                        TorrentDownloadedMetadataEvent(
                            **self.torrent_state[torrent]), event_hndl)
                    metadata_downloaded = True

                if status.state == status.downloading and not download_started:
                    self._fire_event(
                        TorrentDownloadStartEvent(
                            **self.torrent_state[torrent]), event_hndl)
                    download_started = True

                if last_status and status.progress != last_status.progress:
                    self._fire_event(
                        TorrentDownloadProgressEvent(
                            **self.torrent_state[torrent]), event_hndl)

                if not last_status or status.state != last_status.state:
                    self._fire_event(
                        TorrentStateChangeEvent(**self.torrent_state[torrent]),
                        event_hndl)

                if last_status and status.paused != last_status.paused:
                    if status.paused:
                        self._fire_event(
                            TorrentPausedEvent(**self.torrent_state[torrent]),
                            event_hndl)
                    else:
                        self._fire_event(
                            TorrentResumedEvent(**self.torrent_state[torrent]),
                            event_hndl)

                last_status = status
                time.sleep(self._MONITOR_CHECK_INTERVAL)

            if transfer and transfer.is_finished():
                self._fire_event(
                    TorrentDownloadCompletedEvent(
                        **self.torrent_state[torrent]), event_hndl)

            self.remove(torrent)
            return files
Exemple #3
0
        def _thread():
            if not self._webtorrent_process:
                return

            ######
            state = TorrentState.IDLE
            bus = get_bus()
            webtorrent_url = None
            output_dir = None
            media_file = None

            poll = select.poll()
            poll.register(self._webtorrent_process.stdout, select.POLLIN)

            # First wait for the metadata to be ready and the streaming started
            while True:
                result = poll.poll(0)
                if not result:
                    continue

                if not self._is_process_alive():
                    break

                line = self._read_process_line()

                if 'fetching torrent metadata from' in line.lower() \
                        and state == TorrentState.IDLE:
                    # IDLE -> DOWNLOADING_METADATA
                    state = TorrentState.DOWNLOADING_METADATA
                    bus.post(TorrentDownloadedMetadataEvent(resource=resource))
                elif 'downloading: ' in line.lower() \
                        and media_file is None:
                    # Find video files in torrent directory
                    output_dir = os.path.join(
                        download_dir,
                        re.search('downloading: (.+?)$',
                                  line,
                                  flags=re.IGNORECASE).group(1))

                elif 'server running at: ' in line.lower() \
                        and webtorrent_url is None:
                    # Streaming started
                    webtorrent_url = re.search('server running at: (.+?)$',
                                               line,
                                               flags=re.IGNORECASE).group(1)
                    webtorrent_url = webtorrent_url.replace(
                        'http://localhost', 'http://' + get_ip_or_hostname())

                    self._torrent_stream_urls[resource] = webtorrent_url
                    self._download_started_event.set()
                    self.logger.info(
                        'Torrent stream started on {}'.format(webtorrent_url))

                if output_dir and not media_file:
                    media_files = sorted(
                        find_files_by_ext(
                            output_dir, *self._media_plugin.video_extensions))

                    if media_files:
                        # TODO support for queueing multiple media
                        media_file = os.path.join(output_dir, media_files[0])
                    else:
                        time.sleep(1)  # Wait before the media file is created

                if state.value <= TorrentState.DOWNLOADING_METADATA.value \
                        and media_file and webtorrent_url:
                    # DOWNLOADING_METADATA -> DOWNLOADING
                    state = TorrentState.DOWNLOADING
                    bus.post(
                        TorrentDownloadStartEvent(resource=resource,
                                                  media_file=media_file,
                                                  stream_url=webtorrent_url))
                    break

            if not output_dir:
                raise RuntimeError('Could not download torrent')
            if not download_only and (not media_file or not webtorrent_url):
                if not media_file:
                    self.logger.warning(
                        'The torrent does not contain any video files')
                else:
                    self.logger.warning('WebTorrent could not start streaming')

                # Keep downloading but don't start the player
                try:
                    self._webtorrent_process.wait()
                except:
                    pass
                return

            player = None

            if not download_only:
                # Wait until we have enough chunks to start the player
                while True:
                    result = poll.poll(0)
                    if not result:
                        continue

                    if not self._is_process_alive():
                        break

                    try:
                        if os.path.getsize(media_file) > \
                                self._download_size_before_streaming:
                            break
                    except FileNotFoundError:
                        continue

                player = get_plugin('media.' + player_type) if player_type \
                    else self._media_plugin

                media = media_file if player.is_local() else webtorrent_url

                self.logger.info(
                    'Starting playback of {} to {} through {}'.format(
                        media_file, player.__class__.__name__, webtorrent_url))

                subfile = self.get_subtitles(media)
                if subfile:
                    player_args['subtitles'] = subfile

                player.play(media, **player_args)
                self.logger.info('Waiting for player to terminate')

            self._wait_for_player(player)
            self.logger.info('Torrent player terminated')
            bus.post(
                TorrentDownloadCompletedEvent(resource=resource,
                                              output_dir=output_dir,
                                              media_file=media_file))

            try:
                self.quit()
            except:
                pass
            self.logger.info('WebTorrent process terminated')