def __init__(self, **kwargs): self.client = AsyncioClient(**kwargs) self.subtitle_downloads = {} asyncio.async(self.client_event_handler())
class VideoPlayer: def __init__(self, **kwargs): self.client = AsyncioClient(**kwargs) self.subtitle_downloads = {} asyncio.async(self.client_event_handler()) @property def audio(self): try: return self.client.audio except ValueError: return 0 def sub_language(self): for track in self.client.subtitles(): if track.get("selected", 0): return track.get("lang", "unk") return "unk" def audio_language(self): for track in self.client.audio_tracks(): if track.get("selected", 0): return track.get("lang", "unk") return "unk" @property def sub(self): try: return self.client.sub except ValueError: return 0 @property def length(self): try: return self.client.length except ValueError: return 0 @property def path(self): return self.client.path @property def paused(self): return self.client.pause @paused.setter def paused(self, v): self.client.pause = v @property def percent_pos(self): try: return self.client.percent_pos except ValueError: return 0.0 @property def volume(self): try: return self.client.volume except ValueError: return None @volume.setter def volume(self, amount): try: self.client.volume = float(amount) except ValueError: pass @property def has_chapters(self): try: return bool(self.client.chapters) except ValueError: return False @property def length(self): try: return self.client.length except ValueError: return 0.0 @property def time_pos(self): try: return self.client.time_pos except ValueError: return 0.0 def get_progress(self): time_pos, length = self.time_pos, self.length if length <= 0.0: return "" progress = str(timedelta(seconds=time_pos)).split(".")[0] length = str(timedelta(seconds=length)).split(".")[0] return "{} / {}".format(progress, length) def play(self, media_file, append=False): self.client.loadfile(media_file, add_mode=LoadFile.Append if append else LoadFile.Replace) def stop(self): self.client.stop() def seek_backward(self, seek_size): try: if self.has_chapters: self.client.chapter -= 1 else: self.client.seek(-seek_size) except ValueError: pass def seek_forward(self, seek_size): try: if self.has_chapters: self.client.chapter += 1 else: self.client.seek(seek_size) except ValueError: pass def load_srt_subtitle(self, path, language): self.client.sub_add(path, title=language, lang=language) @asyncio.coroutine def set_subtitle(self, sid): if isinstance(sid, str) and sid.startswith("download_"): offset = len("download_") lang = sid[offset:] yield from events.broadcast("download-subtitle", path=self.client.path, language=lang) return log.info("Setting subtitle to {}", sid) self.client.sub = sid def set_audio(self, aid): log.info("Setting subtitle to {}", aid) self.client.audio = aid def add_available_srt_subtitles(self): path = pathlib.Path(self.client.path) glob = "{}*.srt".format(path.stem) glob = re.sub(r"\[", "[[]", glob) glob = re.sub(r"(?<!\[)\]", "[]]", glob) for subtitle in path.parent.glob(glob): subtitle = pathlib.Path(subtitle) language = get_language(subtitle) if language is not None: log.debug("Adding {} as {}", subtitle, language) self.load_srt_subtitle(str(subtitle), language) else: log.debug("Couldn't figure out a language for {}", subtitle) @asyncio.coroutine def client_event_handler(self): while True: event = yield from self.client.event_queue.get() log.debug("mpv event received {}", event_name(event)) if event == libmpv.MPV_EVENT_FILE_LOADED: self.subtitle_downloads.clear() self.add_available_srt_subtitles() media = get_movie_or_tv_show(self.client.path) now_playing = media.title log.info("Now playing {}", now_playing) yield from asyncio.gather( events.info(now_playing), broadcast_player_property("now_playing", now_playing) ) elif event == libmpv.MPV_EVENT_TRACKS_CHANGED: yield from self.update_track_info() elif event == libmpv.MPV_EVENT_PLAYBACK_RESTART: yield from self.broadcast_volume() @asyncio.coroutine def update_track_info(self): yield from asyncio.gather( self.broadcast_available_subtitles(), self.broadcast_available_audio(), self.broadcast_subtitle(), broadcast_player_property("selected_audio", str(self.audio)), events.broadcast("list-subtitles", path=self.client.path), ) if ( self.sub != 0 and self.audio_language() != "unk" and self.audio_language() == self.sub_language() and not int(Config.get("player", "subtitles for matching audio")) ): log.info("Disabling subtitle as it's the same as the language") self.client.sub = 0 @asyncio.coroutine def broadcast_now_playing(self): if self.client.path is None: now_playing = None else: media = get_movie_or_tv_show(self.client.path) now_playing = media.title yield from broadcast_player_property("now_playing", now_playing) @asyncio.coroutine def broadcast_volume(self): volume = self.volume yield from broadcast_player_property("volume", volume) @asyncio.coroutine def broadcast_subtitle(self): yield from broadcast_player_property("selected_subtitle", str(self.sub)) @asyncio.coroutine def broadcast_available_audio(self): audio_streams = [ dict(value=str(track["id"]), display=isocodes.nicename(track.get("lang", "unk"))) for track in self.client.audio_tracks() ] if len(audio_streams) <= 1: audio_streams = None else: audio_streams = sorted(audio_streams, key=itemgetter("display")) yield from broadcast_player_property("available_audio", audio_streams) @asyncio.coroutine def broadcast_available_subtitles(self): subtitles = [ dict(value=str(track["id"]), display=isocodes.nicename(track.get("lang", "unk"))) for track in self.client.subtitles() ] if self.subtitle_downloads: subtitles.extend( [ dict(value="download_{}".format(slang), display=nicename) for (slang, nicename) in self.subtitle_downloads.items() ] ) if not subtitles: subtitles = None else: subtitles = sorted(subtitles, key=itemgetter("display")) yield from broadcast_player_property("available_subtitles", subtitles) @asyncio.coroutine def broadcast_all_properties(self): yield from asyncio.gather( self.broadcast_now_playing(), self.broadcast_available_subtitles(), self.broadcast_available_audio(), self.broadcast_subtitle(), broadcast_player_property("selected_audio", str(self.audio)), self.broadcast_volume(), )