예제 #1
0
파일: VLCPlayer.py 프로젝트: JKorf/MediaPi
    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)
예제 #2
0
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))
예제 #3
0
 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)
예제 #4
0
    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)
예제 #5
0
    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
예제 #6
0
파일: State.py 프로젝트: JKorf/MediaPi
 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()
예제 #7
0
    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()
예제 #8
0
파일: TVManager.py 프로젝트: JKorf/MediaPi
    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()
예제 #9
0
 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()
예제 #10
0
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)
예제 #11
0
    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()
예제 #12
0
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()
예제 #13
0
    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()
예제 #14
0
    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')
예제 #15
0
파일: State.py 프로젝트: JKorf/MediaPi
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=", "")
예제 #16
0
파일: Socket.py 프로젝트: JKorf/MediaPi
    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 = []
예제 #17
0
    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")
예제 #18
0
    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),
        ]
예제 #19
0
    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()
예제 #20
0
파일: Stats.py 프로젝트: JKorf/MediaPi
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)
예제 #21
0
파일: VLCPlayer.py 프로젝트: JKorf/MediaPi
    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
예제 #22
0
    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()
예제 #23
0
    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()
예제 #24
0
    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()
예제 #25
0
파일: Engine.py 프로젝트: JKorf/MediaPi
 def start(self):
     self.running = True
     self.thread = CustomThread(self.runner, self.name)
     self.thread.start()
예제 #26
0
파일: Engine.py 프로젝트: JKorf/MediaPi
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)
예제 #27
0
 def stop_torrent(self):
     if self.torrent:
         thread = CustomThread(self.torrent.stop, "Torrent stopper")
         thread.start()
         self.torrent = None
예제 #28
0
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)
예제 #29
0
파일: VLCPlayer.py 프로젝트: JKorf/MediaPi
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)
예제 #30
0
파일: VLCPlayer.py 프로젝트: JKorf/MediaPi
 def stop(self):
     Logger().write(LogVerbosity.All, "Player stop")
     thread = CustomThread(lambda: self.__player.stop(),
                           "Stopping VLC player")
     thread.start()