def observe_player(self): while True: state = self.get_state().value if state in [5, 6, 7]: state = 0 new_state = PlayerState(state) if new_state == PlayerState.Nothing and self.player_state.state != PlayerState.Nothing: self.stop_player_thread = CustomThread(self.stop, "Stopping player") self.stop_player_thread.start() self.player_state.start_update() self.player_state.state = new_state self.player_state.playing_for = self.get_position() self.player_state.length = self.get_length() self.player_state.audio_tracks = self.get_audio_tracks() self.player_state.audio_track = self.get_audio_track() self.player_state.sub_delay = self.get_subtitle_delay() self.player_state.sub_track = self.get_selected_sub() self.player_state.sub_tracks = self.get_subtitle_tracks() self.player_state.volume = self.get_volume() self.player_state.stop_update() time.sleep(0.5)
class TorrentPeerProcessor(TorrentManager): def __init__(self, torrent): TorrentManager.__init__(self, torrent, "Peer processor") self.running = False self.process_thread = CustomThread(self.process, "Peer processor") def start(self): self.running = True self.process_thread.start() def stop(self): self.running = False self.process_thread.join() super().stop() def process(self): while self.running: start_time = current_time() peers_to_process = self.torrent.peer_manager.connected_peers Timing().start_timing("peer_processing") for peer in peers_to_process: peer.metadata_manager.update() peer.download_manager.update_timeout() Timing().stop_timing("peer_processing") spend_time = current_time() - start_time time.sleep(0.1 - (spend_time / 1000))
def __init__(self): self.running = False self.current_rules = [] self.check_thread = CustomThread(self.check_rules, "Rule checker") self.load_rules() enabled = Database().get_stat("rules_enabled") self.enabled = bool(enabled)
def player_state_change(self, old_state, new_state): if old_state.state != new_state.state: Logger().write( LogVerbosity.Info, "Player state changed from " + str(old_state.state) + " to " + str(new_state.state)) if new_state.state == PlayerState.Playing: self.play_position = new_state.playing_for self.play_length = new_state.length if old_state.state != PlayerState.Paused and old_state.state != new_state.state and new_state.state == PlayerState.Playing: self.update_subtitles(new_state) self.next_epi_thread = CustomThread( lambda: self.next_episode_manager.check_next_episode( self.media_data, self.torrent), "Check next episode", []) self.next_epi_thread.start() if old_state.state != new_state.state and new_state.state == PlayerState.Nothing: self.history_id = 0 self.media_data.reset() self.stop_torrent() if self.play_length != 0 and self.play_position / self.play_length > 0.9: self.next_episode_manager.notify_next_episode( self.play_next_episode) else: self.next_episode_manager.reset() self.play_position = 0 self.play_length = 0 self.update_tracking(new_state)
def __init__(self): self.media_data = MediaData() self.torrent_data = TorrentData() self.torrent = None self.subtitle_provider = SubtitleProvider() self.next_episode_manager = NextEpisodeManager() self.play_position = 0 self.play_length = 0 self.history_id = 0 self.last_tracking_update = 0 self.dht_enabled = Settings.get_bool("dht") if self.dht_enabled: self.dht = DHTEngine() self.dht.start() EventManager.register_event(EventType.AbortingTorrent, self.aborting_torrent) EventManager.register_event(EventType.TorrentMediaSelectionRequired, self.media_selection_required) EventManager.register_event(EventType.TorrentMediaFileSet, lambda x: self._start_playing_torrent()) EventManager.register_event(EventType.TorrentStopped, lambda: self.on_torrent_stopped()) VLCPlayer().player_state.register_callback(self.player_state_change) self.torrent_observer = CustomThread(self.observe_torrent, "Torrent observer") self.torrent_observer.start() self.next_epi_thread = None
def __init__(self): self.state_data = StateData() self.monitoring = sys.platform == "linux" or sys.platform == "linux2" self.state_data.name = Settings.get_string("name") self.watch_thread = CustomThread(self.update_state, "State observer") self.watch_thread.start() self.memory_thread = CustomThread(self.check_memory, "Memory observer") self.memory_thread.start()
def stop_async(self, reason): if self.state != PeerState.Started and self.state != PeerState.Starting: return self.stop_reason = reason self.state = PeerState.Stopping self.peer_stop_task = CustomThread(self.stop, "Peer stopper " + str(self.id), []) self.peer_stop_task.start()
def start(self): if not self.pi: return self.cec_process = subprocess.Popen(['cec-client'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) t = CustomThread(self.__read_cec, "Cec reader", []) t.start()
def search_subtitles(self, name, size, length, first_64k, last_64k): Logger().write( LogVerbosity.Info, "Going to search subs: name: " + name + ", size: " + str(size) + ", length: " + str(length)) self.sub_files = [] for source in self.subtitle_sources: thread = CustomThread( self.search_subtitles_thread, "Search subtitles", [source, size, length, name, first_64k, last_64k]) thread.start()
class PresenceManager(metaclass=Singleton): def __init__(self): self.check_thread = CustomThread(self.check_presence, "Presence checker") self.running = False self.check_interval = 5 self.device_gone_interval = 240 self.on_coming_home = None self.on_leaving_home = None self.anyone_home = True self.pi = sys.platform == "linux" or sys.platform == "linux2" self.device_states = [ DeviceState("Mobiel Jan", "192.168.2.51", self.device_gone_interval), DeviceState("Mobiel Melissa", "192.168.2.50", self.device_gone_interval), ] def start(self): self.running = True self.check_thread.start() def stop(self): self.running = False self.check_thread.join() def check_presence(self): if not self.pi: return while self.running: for device in self.device_states: result = subprocess.call('sudo arping -q -c1 -W 1 ' + device.ip + ' > /dev/null', shell=True) device.set_device_state(result == 0) if self.anyone_home and len( [x for x in self.device_states if x.home_state]) == 0: # left self.anyone_home = False Logger().write(LogVerbosity.Info, "Everybody left home") if self.on_leaving_home is not None: self.on_leaving_home() elif not self.anyone_home and len( [x for x in self.device_states if x.home_state]) > 0: # returned self.anyone_home = True Logger().write(LogVerbosity.Info, "Someone came home") if self.on_coming_home is not None: self.on_coming_home() time.sleep(self.check_interval)
def state(self, value): if self._state != value: old = self._state self._state = value if self.torrent.peer_manager is not None: self.torrent.peer_manager.update_peer(self, old, value) if value == PeerState.Started: self.peer_state_task = CustomThread( self.check_peer_state, "Check peer state " + str(self.id)) self.peer_state_task.start()
class TorrentNetworkManager(TorrentManager): def __init__(self, torrent): super().__init__(torrent, "network") self.running = True self.torrent = torrent self.speed_log = 0 self.average_download_counter = AverageCounter(self, 3) self.thread = None self._event_id_stopped = EventManager.register_event(EventType.TorrentStopped, self.unregister) def unregister(self): EventManager.deregister_event(self._event_id_stopped) def start(self): Logger().write(LogVerbosity.Info, "Starting network manager") self.thread = CustomThread(self.execute, "Network IO") self.thread.start() def execute(self): while self.running: Timing().start_timing("IO") # Select in/outputs input_peers = self.torrent.peer_manager.get_peers_for_reading() received_messages = [] for peer in input_peers: messages_size, messages = peer.connection_manager.handle_read() if messages_size > 0: self.average_download_counter.add_value(messages_size) time = current_time() received_messages += [(peer, x, time) for x in messages] if len(received_messages) != 0: self.torrent.message_processor.process_messages(received_messages) for peer in self.torrent.peer_manager.connected_peers: peer.download_manager.update_requests() output_peers = self.torrent.peer_manager.get_peers_for_writing() for peer in output_peers: peer.connection_manager.handle_write() Timing().stop_timing("IO") sleep(0.005) def stop(self): self.running = False self.thread.join() super().stop()
def request_peers(self, torrent): if not self.initialized: for uri in torrent.announce_uris: if len([x for x in self.trackers if x.host == uri]) == 0: tracker = TrackerFactory.create_tracker(uri) if tracker is not None: self.trackers.append(tracker) Logger().write(LogVerbosity.Debug, "Initialized " + str(len(self.trackers)) + " trackers") self.initialized = True for tracker in self.trackers: thread = CustomThread(self.tracker_announce, "Tracker announce", [tracker, torrent]) thread.start()
def start(self): Logger().write(LogVerbosity.All, str(self.id) + ' Starting peer') self.state = PeerState.Starting self.connection_manager = PeerConnectionManager(self, self.uri) self.download_manager = PeerDownloadManager(self) self.metadata_manager = PeerMetaDataManager(self) self.extension_manager = PeerExtensionManager(self) self.counter = AverageCounter(self, 3) self.peer_start_task = CustomThread(self.connection_manager.start, "Start peer " + str(self.id)) self.peer_start_task.start() Logger().write(LogVerbosity.Debug, str(self.id) + ' Peer started')
class StateManager(metaclass=Singleton): def __init__(self): self.state_data = StateData() self.monitoring = sys.platform == "linux" or sys.platform == "linux2" self.state_data.name = Settings.get_string("name") self.watch_thread = CustomThread(self.update_state, "State observer") self.watch_thread.start() self.memory_thread = CustomThread(self.check_memory, "Memory observer") self.memory_thread.start() def update_state(self): boot_time = psutil.boot_time() while True: self.state_data.start_update() self.state_data.memory = psutil.virtual_memory().percent self.state_data.cpu = psutil.cpu_percent() self.state_data.threads = ThreadManager().thread_count self.state_data.temperature = self.get_temperature() disk_info = psutil.disk_usage("/" if self.monitoring else "C:/") self.state_data.disk_total = disk_info.total self.state_data.disk_used = disk_info.used self.state_data.disk_free = disk_info.free self.state_data.disk_percentage = disk_info.percent self.state_data.boot_time = boot_time self.state_data.stop_update() time.sleep(1) def check_memory(self): if not self.monitoring: return while True: if self.state_data.memory > 90: Logger().write( LogVerbosity.Info, "Memory high ( " + str(self.state_data.memory) + "% )") time.sleep(10) def get_temperature(self): if not self.monitoring: return "-" proc = subprocess.Popen(["vcgencmd", "measure_temp"], stdout=PIPE, universal_newlines=True) out, err = proc.communicate() return out.replace("temp=", "")
def __init__(self, port, on_node_seen, on_node_timeout, on_query): self.port = port self.socket = socket(AF_INET, SOCK_DGRAM) self.socket.settimeout(0.1) self.message_thread = CustomThread(self.message_thread_action, "DHT message", []) self.running = False self.node_seen_handler = on_node_seen self.node_timeout_handler = on_node_timeout self.query_handler = on_query self.last_send = 0 self.received_messages = [] self.to_send_messages = [] self.awaiting_messages = []
def __init__(self, name, update_interval): super().__init__(None, name) self.__name = name self.__update_interval = update_interval self.__callbacks = [] self.__changed = True self.__last_update = 0 self.__start_state = None self.__last_update_state = None self.__wait_event = Event() self.__running = False self.__update_thread = CustomThread(self.__check_update, name + " observer")
def __init__(self): self.check_thread = CustomThread(self.check_presence, "Presence checker") self.running = False self.check_interval = 5 self.device_gone_interval = 240 self.on_coming_home = None self.on_leaving_home = None self.anyone_home = True self.pi = sys.platform == "linux" or sys.platform == "linux2" self.device_states = [ DeviceState("Mobiel Jan", "192.168.2.51", self.device_gone_interval), DeviceState("Mobiel Melissa", "192.168.2.50", self.device_gone_interval), ]
def start(self): Logger().write( LogVerbosity.Debug, self.name + " starting listener on port " + str(self.port)) self.soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.running = True try: self.soc.bind(("", self.port)) Logger().write( LogVerbosity.Info, "StreamServer " + self.name + " listening on port " + str(self.port)) except (socket.error, OSError) as e: Logger().write( LogVerbosity.Info, "Couldn't start StreamServer " + self.name + ": " + str(e)) return self.soc.listen(10) try: while True: Logger().write( LogVerbosity.Debug, "StreamServer " + self.name + " listening for incoming connection") conn, addr = self.soc.accept() if not self.running: break ip, port = str(addr[0]), str(addr[1]) Logger().write(LogVerbosity.Debug, 'New connection from ' + ip + ':' + port) thread = CustomThread(self.client_thread, "Stream request", [conn]) thread.start() except Exception as e: Logger().write_error(e, "Stream server") Logger().write(LogVerbosity.Debug, "StreamServer " + self.name + " closing") self.soc.close()
class Stats(metaclass=Singleton): def __init__(self): self.cache = StatList() self.changed = False self.work_thread = CustomThread(self.save_stats, "Stat saver", []) def start(self): stats = Database().get_stats() for key, value, last_change in stats: self.cache.update(key, value) self.work_thread.start() def _update_stat(self, name, value): self.cache.update(name, value) self.changed = True def save_stats(self): while True: if self.changed: self.changed = False copy = self.cache.statistics.copy() Logger().write(LogVerbosity.Debug, "Saving stats") for key, val in copy.items(): Database().update_stat(key, val) time.sleep(15) def add(self, name, value): stat = self.cache.get(name) if stat == 0: self._update_stat(name, value) else: self._update_stat(name, stat + value) def total(self, name): return self.cache.get(name) def set(self, name, value): self._update_stat(name, value)
def __init__(self): self.__vlc_instance = None self.player_state = PlayerData() self.instantiate_vlc() self.media = None self.__player = self.__vlc_instance.media_player_new() self.__list_player = self.__vlc_instance.media_list_player_new() self.__list_player.set_media_player(self.__player) self.__event_manager = self.__player.event_manager() self.set_volume(75) EventManager.register_event(EventType.SetSubtitleFiles, self.set_subtitle_files) EventManager.register_event(EventType.StopPlayer, self.stop) self.player_observer = CustomThread(self.observe_player, "Player observer") self.player_observer.start() self.stop_player_thread = None
def start(self): APIController.slaves = SlaveCollection() log_verbosity = Settings.get_int("log_level") if log_verbosity > 0: flask_logger = logging.getLogger('werkzeug') flask_logger.setLevel(logging.INFO) if Settings.get_bool("slave"): thread = CustomThread(self.internal_start_slave, "API controller", []) thread.start() else: thread = CustomThread(self.internal_start_master, "API controller", []) thread.start()
def start(self): self.connected_on = 0 Logger().write(LogVerbosity.All, str(self.peer.id) + ' connecting to ' + str(self.uri.netloc)) Stats().add('peers_connect_try', 1) if not self.connection.connect(): Stats().add('peers_connect_failed', 1) if self.peer is not None: Logger().write(LogVerbosity.All, str(self.peer.id) + ' could not connect to ' + str(self.uri.netloc)) self.peer.stop_async("Can't connect") return if self.peer.state is not PeerState.Starting: return self.connected_on = current_time() self.peer.add_connected_peer_stat(self.peer.source) Stats().add('peers_connect_success', 1) Logger().write(LogVerbosity.Debug, str(self.peer.id) + ' connected to ' + str(self.uri.netloc)) self.peer.state = PeerState.Started self.in_thread = CustomThread(self.socket_reader, "Peer " + str(self.peer.id) + " input") self.in_thread.start()
def on_command(topic, command, args): Logger().write(LogVerbosity.Debug, "Master command " + topic + ": " + command) method = None if topic == "media": from MediaPlayer.MediaManager import MediaManager method = getattr(MediaManager(), command) if topic == "updater": from Updater import Updater method = getattr(Updater(), command) if topic == "system": if command == "restart_device": os.system('sudo reboot') if command == "restart_application": python = sys.executable os.execl(python, python, *sys.argv) if command == "close_application": sys.exit() if method is not None: cb_thread = CustomThread(method, "Master command", args) cb_thread.start()
def start(self): self.running = True self.thread = CustomThread(self.runner, self.name) self.thread.start()
class Engine(LogObject): def __init__(self, name, tick_time=1000, parent=None): super().__init__(parent, "Engine:" + name) self.name = name self.tick_time = tick_time self.last_tick = 0 self.running = False self.thread = None self.work_items = [] self.current_item = None self.start_time = 0 self.timing = dict() self.own_time = TimingObject(self.name) # Log props self.current_item_log = "" def runner(self): while self.running: sleep(0.01) if not self.running: break self.last_tick = current_time() self.tick() def start(self): self.running = True self.thread = CustomThread(self.runner, self.name) self.thread.start() def add_work_item(self, name, interval, work_item, initial_invoke=True): self.work_items.append(EngineWorkItem(self, name, interval, work_item, initial_invoke)) def stop(self): self.running = False self.thread.join() def tick(self): tick_time = current_time() cur_list = list(self.work_items) for i in range(len(cur_list)): work_item = cur_list[i] if work_item.last_run_time + work_item.interval < tick_time: Timing().start_timing("Engine item " + work_item.name) self.current_item = work_item self.current_item_log = work_item.name self.start_time = current_time() if not self.running: return result = work_item.action() self.current_item = None self.current_item_log = "" test_time = current_time() work_item.last_run_time = test_time work_item.last_run_duration = test_time - self.start_time if work_item.interval == -1: self.work_items.remove(work_item) elif not result: self.work_items.remove(work_item) if work_item.name not in self.timing: self.timing[work_item.name] = TimingObject(work_item.name) self.timing[work_item.name].add_time(current_time() - self.start_time) Timing().stop_timing("Engine item " + work_item.name) sleep(0) self.own_time.add_time(current_time() - tick_time)
def stop_torrent(self): if self.torrent: thread = CustomThread(self.torrent.stop, "Torrent stopper") thread.start() self.torrent = None
class MediaManager(metaclass=Singleton): def __init__(self): self.media_data = MediaData() self.torrent_data = TorrentData() self.torrent = None self.subtitle_provider = SubtitleProvider() self.next_episode_manager = NextEpisodeManager() self.play_position = 0 self.play_length = 0 self.history_id = 0 self.last_tracking_update = 0 self.dht_enabled = Settings.get_bool("dht") if self.dht_enabled: self.dht = DHTEngine() self.dht.start() EventManager.register_event(EventType.AbortingTorrent, self.aborting_torrent) EventManager.register_event(EventType.TorrentMediaSelectionRequired, self.media_selection_required) EventManager.register_event(EventType.TorrentMediaFileSet, lambda x: self._start_playing_torrent()) EventManager.register_event(EventType.TorrentStopped, lambda: self.on_torrent_stopped()) VLCPlayer().player_state.register_callback(self.player_state_change) self.torrent_observer = CustomThread(self.observe_torrent, "Torrent observer") self.torrent_observer.start() self.next_epi_thread = None def start_file(self, url, time): actual_url = url if Settings.get_bool("slave"): actual_url = "http://" + Settings.get_string( "master_ip") + ":50015/file/" + urllib.parse.quote(url) self.stop_play() VLCPlayer().play(actual_url, time) if Settings.get_bool("slave"): self.history_id, = SlaveClientController.request_master( "add_watched_file", 5, url, current_time()) else: self.history_id = Database().add_watched_file(url, current_time()) self.media_data.start_update() self.media_data.type = "File" self.media_data.title = os.path.basename(url) self.media_data.url = url self.media_data.image = None self.media_data.stop_update() TVManager().switch_input_to_pi() def start_radio(self, name, url): self.stop_play() VLCPlayer().play(url, 0) self.media_data.start_update() self.media_data.type = "Radio" self.media_data.title = name self.media_data.image = None self.media_data.stop_update() TVManager().switch_input_to_pi() def start_episode(self, id, season, episode, title, url, image, position): self.stop_play() self._start_torrent(url, None) self.media_data.start_update() self.media_data.type = "Show" self.media_data.title = title self.media_data.image = image self.media_data.season = season self.media_data.id = id self.media_data.episode = episode self.media_data.start_from = position self.media_data.stop_update() def start_torrent(self, title, url, media_file=None): self.stop_play() self._start_torrent(url, media_file) self.media_data.start_update() self.media_data.type = "Torrent" self.media_data.title = title self.media_data.image = None self.media_data.stop_update() def start_movie(self, id, title, url, image, position): self.stop_play() self._start_torrent(url, None) self.media_data.start_update() self.media_data.type = "Movie" self.media_data.title = title self.media_data.image = image self.media_data.id = id self.media_data.start_from = position self.media_data.stop_update() def start_youtube(self, title, url, position): self.stop_play() VLCPlayer().play(url, position) if Settings.get_bool("slave"): self.history_id, = SlaveClientController.request_master( "add_watched_youtube", 5, title, url, current_time()) else: self.history_id = Database().add_watched_youtube( title, url, current_time()) self.media_data.start_update() self.media_data.type = "YouTube" self.media_data.url = url self.media_data.title = title self.media_data.stop_update() TVManager().switch_input_to_pi() def start_url(self, title, url): self.stop_play() VLCPlayer().play(url, 0) if Settings.get_bool("slave"): self.history_id, = SlaveClientController.request_master( "add_watched_url", 5, url, current_time()) else: self.history_id = Database().add_watched_url(url, current_time()) self.media_data.start_update() self.media_data.type = "Url" self.media_data.title = title self.media_data.stop_update() TVManager().switch_input_to_pi() def pause_resume(self): VLCPlayer().pause_resume() def seek(self, position): VLCPlayer().set_time(position) def change_subtitle(self, track): VLCPlayer().set_subtitle_track(track) def change_audio(self, track): VLCPlayer().set_audio_track(track) def change_volume(self, change_volume): VLCPlayer().set_volume(change_volume) def change_subtitle_delay(self, delay): VLCPlayer().set_subtitle_delay(delay) def stop_play(self): stop_torrent = False if VLCPlayer().player_state.state == PlayerState.Nothing: stop_torrent = True VLCPlayer().stop() if stop_torrent: self.stop_torrent() while self.torrent is not None: time.sleep(0.2) self.media_data.reset() def aborting_torrent(self, reason): APIController().ui_message("Aborting torrent", reason) self.stop_play() @staticmethod def on_torrent_stopped(): time.sleep(2) gc.collect() time.sleep(1) obj = objgraph.by_type('MediaPlayer.Torrents.Torrent.Torrent.Torrent') if len(obj) != 0: Logger().write(LogVerbosity.Important, "Torrent not disposed!") else: Logger().write(LogVerbosity.Info, "Torrent disposed") def play_next_episode(self, continue_next): if continue_next: if self.next_episode_manager.next_type == "File": self.start_file(self.next_episode_manager.next_path, 0) elif self.next_episode_manager.next_type == "Show": self.start_episode(self.next_episode_manager.next_id, self.next_episode_manager.next_season, self.next_episode_manager.next_episode, self.next_episode_manager.next_title, self.next_episode_manager.next_path, self.next_episode_manager.next_img, 0) else: self.start_torrent(self.next_episode_manager.next_title, self.next_episode_manager.next_path, self.next_episode_manager.next_media_file) Logger().write( LogVerbosity.Info, "Playing next: " + self.next_episode_manager.next_title) self.next_episode_manager.reset() def media_selection_required(self, files): if Settings.get_bool("slave"): data, = SlaveClientController.request_master( "get_history_for_url", 5, self.torrent.uri) if data: history = [ History(x['id'], x['imdb_id'], x['type'], x['title'], x['image'], x['watched_at'], x['season'], x['episode'], x['url'], x['media_file'], x['played_for'], x['length']) for x in json.loads(data) ] else: history = [] else: history = Database().get_history_for_url(self.torrent.uri) for file in files: seen = [x for x in history if x.media_file == file.path] file.seen = len(seen) > 0 if file.seen: seen = seen[-1] file.played_for = seen.played_for file.play_length = seen.length APIController().ui_request("SelectMediaFile", self.set_media_file, 60 * 30, files) def set_media_file(self, file, position): if not file: self.stop_play() else: self.media_data.start_from = position self.torrent.set_media_file(file) def _start_playing_torrent(self): if Settings.get_bool("slave"): self.history_id, = SlaveClientController.request_master( "add_watched_torrent", 5, self.media_data.type, self.media_data.title, self.media_data.id, self.torrent.uri, self.torrent.media_file.path, self.media_data.image, self.media_data.season, self.media_data.episode, current_time()) else: self.history_id = Database().add_watched_torrent( self.media_data.type, self.media_data.title, self.media_data.id, self.torrent.uri, self.torrent.media_file.path, self.media_data.image, self.media_data.season, self.media_data.episode, current_time()) VLCPlayer().play("http://localhost:50009/torrent", self.media_data.start_from) def _start_torrent(self, url, media_file): if self.torrent is not None: Logger().write(LogVerbosity.Important, "Can't start new torrent, still torrent active") return success, torrent = Torrent.create_torrent(1, url) if success: self.torrent = torrent if media_file is not None: self.torrent.set_selected_media_file(media_file) torrent.start() self.last_torrent_start = current_time() TVManager().switch_input_to_pi() else: Logger().write(LogVerbosity.Important, "Invalid torrent") EventManager.throw_event(EventType.Error, ["torrent_error", "Invalid torrent"]) self.stop_torrent() def player_state_change(self, old_state, new_state): if old_state.state != new_state.state: Logger().write( LogVerbosity.Info, "Player state changed from " + str(old_state.state) + " to " + str(new_state.state)) if new_state.state == PlayerState.Playing: self.play_position = new_state.playing_for self.play_length = new_state.length if old_state.state != PlayerState.Paused and old_state.state != new_state.state and new_state.state == PlayerState.Playing: self.update_subtitles(new_state) self.next_epi_thread = CustomThread( lambda: self.next_episode_manager.check_next_episode( self.media_data, self.torrent), "Check next episode", []) self.next_epi_thread.start() if old_state.state != new_state.state and new_state.state == PlayerState.Nothing: self.history_id = 0 self.media_data.reset() self.stop_torrent() if self.play_length != 0 and self.play_position / self.play_length > 0.9: self.next_episode_manager.notify_next_episode( self.play_next_episode) else: self.next_episode_manager.reset() self.play_position = 0 self.play_length = 0 self.update_tracking(new_state) def update_subtitles(self, new_state): media_type = self.media_data.type if media_type == "File": if Settings.get_bool("slave"): SlaveClientController.request_master_cb( "get_file_info", self.process_file_info_for_subtitles, 5, self.media_data.url) else: size, first_64k, last_64k = get_file_info(self.media_data.url) EventManager.throw_event(EventType.SearchSubtitles, [ self.media_data.title, size, VLCPlayer().get_length(), first_64k, last_64k ]) elif media_type == "Show" or media_type == "Movie" or media_type == "Torrent": EventManager.throw_event(EventType.SearchSubtitles, [ os.path.basename(self.torrent.media_file.name), self.torrent.media_file.length, VLCPlayer().get_length(), self.torrent.media_file.first_64k, self.torrent.media_file.last_64k ]) def process_file_info_for_subtitles(self, size, first_64k, last_64k): Logger().write(LogVerbosity.Debug, "Received file info from master, requesting subs") EventManager.throw_event(EventType.SearchSubtitles, [ self.media_data.title, size, VLCPlayer().get_length(), first_64k.encode('utf8'), last_64k.encode('utf8') ]) def update_tracking(self, state): if self.media_data.type == "Radio": return if self.history_id == 0 or state.state != PlayerState.Playing or current_time( ) - self.last_tracking_update < 5000: return if state.playing_for > state.length - ( state.length * 0.04) or state.length - state.playing_for < 10000: if Settings.get_bool("slave"): SlaveClientController.notify_master("update_watching_item", self.history_id, state.length, state.length, current_time()) else: Database().update_watching_item(self.history_id, state.length, state.length, current_time()) else: if Settings.get_bool("slave"): SlaveClientController.notify_master("update_watching_item", self.history_id, state.playing_for, state.length, current_time()) else: Database().update_watching_item(self.history_id, state.playing_for, state.length, current_time()) self.last_tracking_update = current_time() def stop_torrent(self): if self.torrent: thread = CustomThread(self.torrent.stop, "Torrent stopper") thread.start() self.torrent = None def observe_torrent(self): while True: if self.torrent is None or self.torrent.state == TorrentState.Stopping: self.torrent_data.reset() time.sleep(0.5) continue self.torrent_data.start_update() self.torrent_data.title = self.torrent.name self.torrent_data.size = self.torrent.total_size if self.torrent.media_file is not None: self.torrent_data.media_file = self.torrent.media_file.name self.torrent_data.size = self.torrent.media_file.length self.torrent_data.downloaded = self.torrent.network_manager.average_download_counter.total self.torrent_data.left = self.torrent.left self.torrent_data.overhead = self.torrent.overhead self.torrent_data.download_speed = self.torrent.network_manager.average_download_counter.value self.torrent_data.buffer_position = self.torrent.stream_buffer_position self.torrent_data.buffer_total = self.torrent.bytes_total_in_buffer self.torrent_data.stream_position = self.torrent.stream_position self.torrent_data.buffer_size = self.torrent.bytes_ready_in_buffer self.torrent_data.total_streamed = self.torrent.bytes_streamed self.torrent_data.state = self.torrent.state self.torrent_data.potential = len( self.torrent.peer_manager.potential_peers) self.torrent_data.connecting = len( self.torrent.peer_manager.connecting_peers) self.torrent_data.connected = len( self.torrent.peer_manager.connected_peers) self.torrent_data.disconnected = len( self.torrent.peer_manager.disconnected_peers) self.torrent_data.cant_connect = len( self.torrent.peer_manager.cant_connect_peers) self.torrent_data.stop_update() time.sleep(0.5)
class VLCPlayer(metaclass=Singleton): def __init__(self): self.__vlc_instance = None self.player_state = PlayerData() self.instantiate_vlc() self.media = None self.__player = self.__vlc_instance.media_player_new() self.__list_player = self.__vlc_instance.media_list_player_new() self.__list_player.set_media_player(self.__player) self.__event_manager = self.__player.event_manager() self.set_volume(75) EventManager.register_event(EventType.SetSubtitleFiles, self.set_subtitle_files) EventManager.register_event(EventType.StopPlayer, self.stop) self.player_observer = CustomThread(self.observe_player, "Player observer") self.player_observer.start() self.stop_player_thread = None def instantiate_vlc(self): parameters = self.get_instance_parameters() Logger().write(LogVerbosity.Debug, "VLC parameters: " + str(parameters)) self.__vlc_instance = vlc.Instance("cvlc", *parameters) Logger().write(LogVerbosity.Info, "VLC version " + libvlc_get_version().decode('utf8')) def play(self, url, time=0): parameters = self.get_play_parameters(url, time) Logger().write(LogVerbosity.Info, "VLC Play | Url: " + url) Logger().write(LogVerbosity.Info, "VLC Play | Time: " + str(time)) Logger().write(LogVerbosity.Info, "VLC Play | Parameters: " + str(parameters)) self.player_state.start_update() self.player_state.path = url self.player_state.stop_update() self.media = Media(url, *parameters) if 'youtube' in url: media_list = MediaList() media_list.add_media(self.media) self.__list_player.set_media_list(media_list) self.__list_player.play() else: self.__player.set_media(self.media) self.__player.play() @staticmethod def get_instance_parameters(): params = [ "--verbose=" + str(Settings.get_int("vlc_log_level")), "--network-caching=" + str(Settings.get_int("network_caching")), "--ipv4-timeout=500", "--image-duration=-1" ] if sys.platform == "linux" or sys.platform == "linux2": log_path = Settings.get_string( "base_folder") + "/Logs/" + datetime.datetime.now().strftime( '%Y-%m-%d %H-%M-%S') params.append( "--logfile=" + log_path + '/vlc_' + datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S') + ".txt") params.append("--file-logging") params.append("--file-caching=5000") return params def get_play_parameters(self, url, time): params = [] if time != 0: params.append("start-time=" + str(time // 1000)) return params def set_window(self, handle): if sys.platform == "linux" or sys.platform == "linux2": self.__player.set_xwindow(handle) else: self.__player.set_hwnd(handle) def pause_resume(self): Logger().write(LogVerbosity.All, "Player pause resume") self.__player.pause() def stop(self): Logger().write(LogVerbosity.All, "Player stop") thread = CustomThread(lambda: self.__player.stop(), "Stopping VLC player") thread.start() def set_volume(self, vol): Logger().write(LogVerbosity.Debug, "Player set volume " + str(vol)) self.__player.audio_set_volume(vol) self.player_state.start_update() self.player_state.volume = vol self.player_state.stop_update() def get_volume(self): return self.__player.audio_get_volume() def get_position(self): return self.__player.get_time() def get_length(self): return int(self.__player.get_length()) def set_time(self, pos): Logger().write(LogVerbosity.Debug, "Player set time " + str(pos)) self.__player.set_time(pos) self.player_state.start_update() self.player_state.playing_for = pos self.player_state.stop_update() def set_position(self, pos): Logger().write(LogVerbosity.Debug, "Player set position " + str(pos)) self.__player.set_position(pos) def set_subtitle_delay(self, delay): Logger().write(LogVerbosity.Debug, "Player set subtitle delay " + str(delay)) self.__player.video_set_spu_delay(delay) self.player_state.start_update() self.player_state.sub_delay = delay self.player_state.stop_update() def get_state(self): return self.__player.get_state() def get_audio_track(self): return self.__player.audio_get_track() def set_audio_track(self, track_id): Logger().write(LogVerbosity.Debug, "Player set audio track " + str(track_id)) self.__player.audio_set_track(track_id) self.player_state.start_update() self.player_state.audio_track = track_id self.player_state.stop_update() def get_audio_tracks(self): tracks = self.__player.audio_get_track_description() result = [] for trackid, trackname in tracks: result.append((trackid, trackname.decode('utf8'))) return result def set_subtitle_files(self, files): Logger().write(LogVerbosity.Debug, "Adding " + str(len(files)) + " subtitle files") pi = sys.platform == "linux" or sys.platform == "linux2" for file in reversed(files): if not pi and file[1] != ":": file = "C:" + file file = file.replace("/", os.sep).replace("\\", os.sep) # NOTE this must be called after Play() self.__player.video_set_subtitle_file(file) def set_subtitle_track(self, id): Logger().write(LogVerbosity.Debug, "Player set subtitle track " + str(id)) self.__player.video_set_spu(id) self.player_state.start_update() self.player_state.sub_track = id self.player_state.stop_update() def get_subtitle_count(self): return self.__player.video_get_spu_count() def get_subtitle_tracks(self): tracks = self.__player.video_get_spu_description() result = [] for trackid, trackname in tracks: result.append((trackid, trackname.decode('utf-8'))) return result def get_subtitle_delay(self): return self.__player.video_get_spu_delay() def get_selected_sub(self): return self.__player.video_get_spu() def try_play_subitem(self): media = self.__player.get_media() if media is None: self.stop() return subs = media.subitems() if subs is None: self.stop() return if len(subs) == 1: subs[0].add_options("demux=avformat") self.__player.set_media(subs[0]) self.__player.play() def observe_player(self): while True: state = self.get_state().value if state in [5, 6, 7]: state = 0 new_state = PlayerState(state) if new_state == PlayerState.Nothing and self.player_state.state != PlayerState.Nothing: self.stop_player_thread = CustomThread(self.stop, "Stopping player") self.stop_player_thread.start() self.player_state.start_update() self.player_state.state = new_state self.player_state.playing_for = self.get_position() self.player_state.length = self.get_length() self.player_state.audio_tracks = self.get_audio_tracks() self.player_state.audio_track = self.get_audio_track() self.player_state.sub_delay = self.get_subtitle_delay() self.player_state.sub_track = self.get_selected_sub() self.player_state.sub_tracks = self.get_subtitle_tracks() self.player_state.volume = self.get_volume() self.player_state.stop_update() time.sleep(0.5)
def stop(self): Logger().write(LogVerbosity.All, "Player stop") thread = CustomThread(lambda: self.__player.stop(), "Stopping VLC player") thread.start()