Exemple #1
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))
Exemple #2
0
    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()
Exemple #3
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()
Exemple #4
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)
Exemple #5
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()
Exemple #6
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()
Exemple #7
0
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=", "")
Exemple #8
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()
Exemple #9
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()
Exemple #10
0
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 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()
Exemple #12
0
 def stop(self):
     Logger().write(LogVerbosity.All, "Player stop")
     thread = CustomThread(lambda: self.__player.stop(),
                           "Stopping VLC player")
     thread.start()
Exemple #13
0
class StreamListener(LogObject):

    wait_for_data = 0.1

    mime_mapping = {
        ".mp4": "video/mp4",
        ".avi": "video/x-msvideo",
        ".mkv": "video/mp4",
        ".srt": "json"
    }

    def __init__(self, name, port, arg=None):
        super().__init__(arg, name)

        self.name = name
        self.torrent = arg

        self.port = port
        self.thread = None
        self.chunk_length = Settings.get_int("max_chunk_size")
        self.server = StreamServer(self.name, port, self.handle_request)

        self.sockets_writing_data = []

        self.running = False
        self.bytes_send = 0
        self.id = 0

    def start_listening(self):
        self.thread = CustomThread(self.server.start, "Listener: " + self.name)
        self.running = True
        self.thread.start()

    def handle_request(self, socket):
        Logger().write(LogVerbosity.Info, self.name + " new request")

        # Read headers
        total_message = self.read_headers(socket)
        if total_message is None:
            return

        header = HttpHeader.from_string(total_message)
        if header.path == "/torrent":
            # Handle torrent stream request
            self.handle_torrent_request(socket, header)
        elif header.path.startswith("/file"):
            # Handle file stream request
            self.handle_file_request(socket, header)
        else:
            # Unknown request
            Logger().write(
                LogVerbosity.Info, self.name +
                " streamListener received unknown request: " + header.path)
            socket.close()

    def read_headers(self, socket):
        try:
            total_message = b''
            while not total_message.endswith(b'\r\n\r\n'):
                rec = socket.recv(1024)
                if len(rec) == 0:
                    break
                total_message += rec
                time.sleep(0)
        except (socket.timeout, ConnectionRefusedError, ConnectionAbortedError,
                ConnectionResetError, OSError):
            socket.close()
            Logger().write(LogVerbosity.Info,
                           self.name + " error reading http header")
            return

        if not total_message.endswith(b'\r\n\r\n'):
            socket.close()
            Logger().write(LogVerbosity.Info,
                           self.name + " invalid http header, closing")
            return
        return total_message

    def handle_file_request(self, socket, header):
        file_path = header.path[6:]
        if sys.platform == "linux" or sys.platform == "linux2":
            file_path = "/" + file_path

        Logger().write(LogVerbosity.Debug,
                       self.name + " file request for " + file_path)

        if not os.path.exists(file_path):
            file_path = urllib.parse.unquote_plus(file_path)
            if not os.path.exists(file_path):
                Logger().write(LogVerbosity.Info,
                               self.name + " file not found: " + file_path)
                self.write_header(socket, "404 Not Found")
                socket.close()
                return

        read_file = ReadFile(file_path)
        read_file.open()

        if header.range_end == 0 or header.range_end == -1:
            header.range_end = read_file.size - 1

        if header.range is None:
            Logger().write(LogVerbosity.Debug,
                           self.name + ' request without range')
            self.write_header_with_content(socket, "200 OK", 0,
                                           header.range_end, read_file.size,
                                           file_path)
            self.write_data(socket, header.range_start,
                            header.range_end - header.range_start + 1,
                            read_file.get_bytes)
        else:
            Logger().write(LogVerbosity.Debug,
                           self.name + ' request with range')
            self.write_header_with_content(socket, "206 Partial Content",
                                           header.range_start,
                                           header.range_end, read_file.size,
                                           file_path)
            self.write_data(socket, header.range_start,
                            header.range_end - header.range_start + 1,
                            read_file.get_bytes)
        read_file.close()

    def handle_torrent_request(self, socket, header):
        if not self.torrent or not self.running:
            socket.close()
            Logger().write(
                LogVerbosity.Debug, self.name +
                " stopping connection because there is no more torrent")
            return

        if header.range_end == 0 or header.range_end == -1:
            header.range_end = self.torrent.media_file.length - 1

        if header.range:
            range_start = header.range_start
            if range_start == self.torrent.media_file.length:
                Logger().write(LogVerbosity.Debug,
                               "Request for content length 0, cant process")
                self.write_header(socket,
                                  "416 Requested range not satisfiable")
                socket.close()
                return

        if header.range is None:
            Logger().write(LogVerbosity.Debug,
                           self.name + ' request without range')
            success = self.write_header_with_content(
                socket, "200 OK", 0, header.range_end,
                self.torrent.media_file.length, self.torrent.media_file.path)

            if not success:
                return

            self.write_data(socket, header.range_start,
                            header.range_end - header.range_start + 1,
                            self.torrent.get_data)
        else:
            Logger().write(LogVerbosity.Debug,
                           self.name + ' request with range')
            success = self.write_header_with_content(
                socket, "206 Partial Content", header.range_start,
                header.range_end, self.torrent.media_file.length,
                self.torrent.media_file.path)

            if not success:
                return

            self.write_data(socket, header.range_start,
                            header.range_end - header.range_start + 1,
                            self.torrent.get_data)

    def write_header(self, socket, status):
        response_header = HttpHeader()
        response_header.status_code = status

        Logger().write(
            LogVerbosity.Info,
            self.name + " return header: " + response_header.to_string())

        try:
            socket.send(response_header.to_string().encode())
            return True
        except (ConnectionAbortedError, ConnectionResetError, OSError):
            Logger().write(
                LogVerbosity.Info,
                "Connection closed 2 during sending of response header")
            socket.close()
            return False

    def write_header_with_content(self, socket, status, start, end, length,
                                  path):
        response_header = HttpHeader()
        Logger().write(
            LogVerbosity.Debug,
            self.name + " stream requested: " + str(start) + "-" + str(end))

        response_header.status_code = status
        response_header.content_length = end - start + 1
        response_header.set_range(start, end, length)
        filename, file_extension = os.path.splitext(path.lower())
        if file_extension not in StreamListener.mime_mapping:
            Logger().write(
                LogVerbosity.Info, self.name + " unknown video type: " +
                str(file_extension) + ", defaulting to mp4")
            response_header.mime_type = StreamListener.mime_mapping[".mp4"]
        else:
            response_header.mime_type = StreamListener.mime_mapping[
                file_extension]

        Logger().write(
            LogVerbosity.Info,
            self.name + " return header: " + response_header.to_string())

        try:
            socket.send(response_header.to_string().encode())
            return True
        except (ConnectionAbortedError, ConnectionResetError, OSError):
            Logger().write(
                LogVerbosity.Info,
                "Connection closed 2 during sending of response header")
            socket.close()
            return False

    def write_data(self, socket, requested_byte, length, data_delegate):
        written = 0
        Logger().write(
            LogVerbosity.Info, self.name + " write data: " +
            str(requested_byte) + ", length " + str(length))
        id = self.id
        self.id += 1
        data_writer = SocketWritingData(self, id, socket, requested_byte,
                                        requested_byte + length,
                                        current_time())
        self.sockets_writing_data.append(data_writer)
        if len(self.sockets_writing_data) > 1:
            Logger().write(LogVerbosity.Debug, "Multiple data writers:")
            for writer in self.sockets_writing_data:
                Logger().write(LogVerbosity.Debug, "    " + str(writer))

        while written < length:
            part_length = min(length - written, self.chunk_length)
            if not self.running:
                Logger().write(
                    LogVerbosity.Debug,
                    self.name + ' writer ' + str(data_writer.id) +
                    " canceling retrieving data because we are no longer running 1"
                )
                data_writer.close()
                self.sockets_writing_data.remove(data_writer)
                return

            if data_writer.stop:
                Logger().write(
                    LogVerbosity.Debug,
                    self.name + ' writer ' + str(data_writer.id) +
                    " canceling because we're seeking and expecting a new request"
                )
                data_writer.close()
                self.sockets_writing_data.remove(data_writer)
                return

            if not self.wait_writable(data_writer, socket):
                Logger().write(
                    LogVerbosity.Debug,
                    self.name + ' writer ' + str(data_writer.id) + " closed")
                self.sockets_writing_data.remove(data_writer)
                return

            data = data_delegate(requested_byte + written, part_length)
            if not self.running:
                Logger().write(
                    LogVerbosity.Debug,
                    self.name + ' writer ' + str(data_writer.id) +
                    " canceling retrieved data because we are no longer running 2"
                )
                data_writer.close()
                self.sockets_writing_data.remove(data_writer)
                return

            if data is None:
                time.sleep(self.wait_for_data)
                continue

            Logger().write(
                LogVerbosity.Info,
                self.name + ' writer ' + str(data_writer.id) +
                ' data retrieved: ' + str(requested_byte + written) + " - " +
                str(requested_byte + written + part_length))
            send = 0
            try:
                while send < len(data):
                    this_send = data[send:send + 50000]
                    data_length = len(this_send)
                    socket.sendall(this_send)
                    written += data_length
                    send += data_length
                    self.bytes_send += data_length
                    data_writer.streamed += data_length
                    Logger().write(
                        LogVerbosity.All,
                        self.name + ' writer ' + str(data_writer.id) +
                        " send " + str(data_length) + " bytes")
                    time.sleep(0.005)  # give other threads some time
            except (ConnectionAbortedError, ConnectionResetError,
                    OSError) as e:
                Logger().write(
                    LogVerbosity.Info,
                    self.name + " writer " + str(data_writer.id) +
                    " connection closed during sending of data: " + str(e))
                data_writer.close()
                self.sockets_writing_data.remove(data_writer)
                return

        Logger().write(LogVerbosity.Info,
                       "Completed request: " + str(data_writer))
        data_writer.close()
        self.sockets_writing_data.remove(data_writer)

    def wait_writable(self, writer, socket):
        while True:
            if not self.running:
                return False

            if writer.stop:
                Logger().write(
                    LogVerbosity.Debug, self.name +
                    " canceling because we're seeking and expecting a new request"
                )
                writer.close()
                return False

            # check if socket is still open
            readable, writeable, exceptional = select.select([socket],
                                                             [socket],
                                                             [socket], 0)
            if len(readable) == 1:
                read = []
                try:
                    read = socket.recv(1024)
                except Exception as e:
                    Logger().write(
                        LogVerbosity.Debug,
                        "Request socket closed with exception: " + str(e))

                if len(read) == 0:
                    Logger().write(LogVerbosity.Info,
                                   self.name + " socket no longer open 3")
                    writer.close()
                    return False
                else:
                    Logger().write(
                        LogVerbosity.Info,
                        self.name + " recv received data?? - " +
                        str(read.decode("utf-8'")))

            if len(writeable) == 0:
                # not currently writeable, wait for it to become available again
                time.sleep(0.1)
                continue

            return True

    def stop(self):
        self.running = False
        for writer in self.sockets_writing_data:
            writer.stop = True

        self.torrent = None
        if self.server is not None:
            self.server.close()
        Logger().write(LogVerbosity.Info, self.name + " stopped")
Exemple #14
0
class App(tk.Frame):

    root = None

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, value):
        Logger().write(
            LogVerbosity.Info,
            "Setting UI state from " + str(self._state) + " to " + str(value))
        prev_state = self._state
        self._state = value
        if value == UIState.Home:
            self.status_image_frame.place_forget()
            self.player_frame.place_forget()
            self.background_canvas.place(x=0, y=0)
            self.change_loading_visibility(False)
        elif value == UIState.Playing:
            self.status_image_frame.place_forget()
            self.change_loading_visibility(False)
            self.background_canvas.place_forget()

            if prev_state != UIState.Paused:
                self.player_frame.place(x=0, y=0)

        elif value == UIState.Paused:
            self.status_image_frame.place(x=self.parent.winfo_screenwidth() -
                                          134,
                                          y=50)

    def change_loading_visibility(self, show):
        state = "hidden"
        if show:
            state = "normal"
        self.background_canvas.itemconfig(self.loading_speed_label,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_speed_value,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_buffered_label,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_buffered_value,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_peers_available_label,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_peers_available_value,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_peers_connected_label,
                                          state=state)
        self.background_canvas.itemconfig(self.loading_peers_connected_value,
                                          state=state)
        self.loading_details_visible = show

    @staticmethod
    def initialize():
        App.root = tk.Tk()
        App.root.config(cursor="none")
        gui = App(App.root)
        while True:
            App.root.update()
            time.sleep(0.01)

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self._state = UIState.Home

        self.loading_details_visible = False

        self.background_time = 60 * 15
        self.background_max_requests = 5
        self.background_images = []
        self.base_image_path = os.getcwd() + "/UI/TV/Images/"
        self.background_canvas = None
        self.background_image = None

        self.name_label = None
        self.time_label = None
        self.date_label = None
        self.playing_label = None
        self.playing_value = None

        self.info_background = None

        self.loading_speed_label = None
        self.loading_buffered_label = None
        self.loading_speed_value = None
        self.loading_buffered_value = None
        self.loading_peers_connected_label = None
        self.loading_peers_connected_value = None
        self.loading_peers_available_value = None
        self.loading_peers_available_label = None

        self.loading_gif = None
        self.rects = []
        self.images = []
        self.player_frame = None
        self.status_image_frame = None
        self.pause_image = None
        self.weather_max = None
        self.weather_min = None
        self.weather_temp = None
        self.weather_icon_image = None

        self.init_UI()

        VLCPlayer().player_state.register_callback(self.player_update)
        MediaManager().media_data.register_callback(self.media_update)
        MediaManager().torrent_data.register_callback(self.torrent_update)

        self.image_fetcher_thread = CustomThread(self.get_backgrounds,
                                                 "UI background downloader")
        self.image_fetcher_thread.start()
        self.background_swapper_thread = CustomThread(self.swap_backgrounds,
                                                      "UI background swapper")
        self.background_swapper_thread.start()
        self.time_change_thread = CustomThread(self.change_time,
                                               "UI time changer")
        self.time_change_thread.start()
        self.current_weather_thread = CustomThread(self.get_weather_data,
                                                   "UI current weather")
        self.current_weather_thread.start()

        VLCPlayer().set_window(self.player_frame.winfo_id())

    def init_UI(self):
        self.parent.title("TV UI")
        self.configure(background='black')

        w = self.parent.winfo_screenwidth()
        h = self.parent.winfo_screenheight()

        self.master.geometry("{0}x{1}+0+0".format(w, h))
        self.parent.bind("<Escape>", self.fullscreen_cancel)
        self.fullscreen_toggle()

        self.background_canvas = tk.Canvas(self.parent,
                                           width=w,
                                           height=h,
                                           highlightthickness=0,
                                           background="#000")
        self.background_image = self.set_canvas_image(self.background_canvas,
                                                      "background.jpg", 0, 0,
                                                      w, h)

        self.info_background = self.create_rectangle(self.background_canvas,
                                                     w - 250,
                                                     0,
                                                     w,
                                                     h,
                                                     fill="#FFF",
                                                     alpha=0.7,
                                                     outline="#AAA")
        self.name_label = self.background_canvas.create_text(
            w - 125,
            30,
            anchor="n",
            font=("Purisa", 20),
            text=Settings.get_string("name"),
            fill="#444")

        playing_position = 96
        self.playing_label = self.background_canvas.create_text(
            w - 220,
            playing_position,
            anchor="nw",
            font=("Purisa", 14),
            text="",
            fill="#999")
        self.playing_value = self.background_canvas.create_text(
            w - 220,
            playing_position + 22,
            anchor="nw",
            font=("Purisa", 16),
            text="",
            fill="#444")

        self.time_label = self.background_canvas.create_text(
            w - 125,
            h - 80,
            font=("Purisa", 28),
            text=time.strftime('%H:%M'),
            fill="#444")
        self.date_label = self.background_canvas.create_text(
            w - 125,
            h - 40,
            font=("Purisa", 20),
            text=time.strftime('%a %d %b'),
            fill="#444")

        loading_position = 96
        self.loading_speed_label = self.background_canvas.create_text(
            w - 230,
            loading_position,
            anchor="nw",
            font=("Purisa", 16),
            text="Speed:",
            fill="#444",
            state="hidden")
        self.loading_buffered_label = self.background_canvas.create_text(
            w - 230,
            loading_position + 24,
            anchor="nw",
            font=("Purisa", 16),
            text="Buffered:",
            fill="#444",
            state="hidden")
        self.loading_peers_connected_label = self.background_canvas.create_text(
            w - 230,
            loading_position + 48,
            anchor="nw",
            font=("Purisa", 16),
            text="Connected:",
            fill="#444",
            state="hidden")
        self.loading_peers_available_label = self.background_canvas.create_text(
            w - 230,
            loading_position + 72,
            anchor="nw",
            font=("Purisa", 16),
            text="Available:",
            fill="#444",
            state="hidden")

        self.loading_speed_value = self.background_canvas.create_text(
            w - 20,
            loading_position,
            anchor="ne",
            font=("Purisa", 16),
            text="",
            fill="#444",
            state="hidden")
        self.loading_buffered_value = self.background_canvas.create_text(
            w - 20,
            loading_position + 24,
            anchor="ne",
            font=("Purisa", 16),
            text="",
            fill="#444",
            state="hidden")
        self.loading_peers_connected_value = self.background_canvas.create_text(
            w - 20,
            loading_position + 48,
            anchor="ne",
            font=("Purisa", 16),
            text="",
            fill="#444",
            state="hidden")
        self.loading_peers_available_value = self.background_canvas.create_text(
            w - 20,
            loading_position + 72,
            anchor="ne",
            font=("Purisa", 16),
            text="",
            fill="#444",
            state="hidden")

        self.player_frame = tk.Frame(self.parent,
                                     width=w,
                                     height=h,
                                     highlightthickness=0,
                                     background="black")
        self.status_image_frame = tk.Canvas(self.parent,
                                            width=84,
                                            height=84,
                                            highlightthickness=0,
                                            background="#DDD")
        self.status_image_frame.pause_image = ImageTk.PhotoImage(
            Image.open(self.base_image_path + "paused.png"))
        self.pause_image = self.status_image_frame.create_image(
            10, 10, anchor='nw', image=self.status_image_frame.pause_image)

        self.weather_icon_image = self.background_canvas.create_image(
            w - 125, h - 230, image=None)
        self.weather_temp = self.background_canvas.create_text(w - 125,
                                                               h - 150,
                                                               font=("Purisa",
                                                                     20),
                                                               text="",
                                                               fill="#444")

        self.background_canvas.create_line(w - 240,
                                           70,
                                           w - 10,
                                           70,
                                           fill="#888")
        self.background_canvas.create_line(w - 240,
                                           h - 120,
                                           w - 10,
                                           h - 120,
                                           fill="#888")

        self.state = UIState.Home

    def set_canvas_image(self, canvas, name, x, y, w, h):
        image = Image.open(self.base_image_path + name)
        resized = image.resize((w, h), Image.ANTIALIAS)
        background_image = ImageTk.PhotoImage(resized)
        self.images.append(background_image)
        return canvas.create_image(x, y, anchor='nw', image=background_image)

    def change_time(self):
        while True:
            self.background_canvas.itemconfigure(self.time_label,
                                                 text=time.strftime('%H:%M'))
            self.background_canvas.itemconfigure(
                self.date_label, text=time.strftime('%a %d %b'))

            time.sleep(0.2)

    def get_backgrounds(self):
        while True:
            amount = self.background_max_requests - len(self.background_images)
            if amount == 0:
                time.sleep(30)
                continue

            result = RequestFactory.make_request(
                "https://api.unsplash.com/photos/random/" + "?count=" +
                str(amount) + "&orientation=landscape" +
                "&collections=827743,3178572,225,573009" +
                "&client_id=825216e69ea20d24e5b3ddeeab316f6569dcecc4965e16a0725aee3eeb143872"
            )
            if result is None:
                time.sleep(30)
                continue

            json_data = json.loads(result.decode('utf-8'))

            urls = [
                x['urls']['raw'] + "&w=" +
                str(self.parent.winfo_screenwidth()) + "&h=" +
                str(self.parent.winfo_screenheight()) + "&fit=scale"
                for x in json_data
            ]

            for url in urls:
                image_byt = urlopen(url).read()
                image = Image.open(BytesIO(image_byt))
                self.background_images.append(image)

            time.sleep(30)

    def create_rectangle(self, canvas, x1, y1, x2, y2, **kwargs):
        if 'alpha' in kwargs:
            alpha = int(kwargs.pop('alpha') * 255)
            fill = kwargs.pop('fill')
            fill = App.root.winfo_rgb(fill) + (alpha, )
            state = 'normal'
            if 'state' in kwargs:
                state = kwargs.pop('state')
            image = Image.new('RGBA', (x2 - x1, y2 - y1), fill)
            self.rects.append(ImageTk.PhotoImage(image))
            return canvas.create_image(x1,
                                       y1,
                                       image=self.rects[-1],
                                       anchor='nw',
                                       state=state)
        return canvas.create_rectangle(x1, y1, x2, y2, **kwargs)

    def swap_backgrounds(self):
        while True:
            if len(self.background_images) == 0:
                time.sleep(30)
                continue

            self.swap_background()
            time.sleep(self.background_time)

    def swap_background(self):
        img = self.background_images[0]
        self.background_images.remove(img)
        self.background_canvas.background_image = ImageTk.PhotoImage(img)
        self.background_canvas.itemconfig(
            self.background_image,
            image=self.background_canvas.background_image)

    def set_now_playing(self, title):
        play_label = "Now playing:"
        if title is None:
            play_label = ""
        self.background_canvas.itemconfigure(self.playing_label,
                                             text=play_label)
        self.background_canvas.itemconfigure(self.playing_value,
                                             text=title or "")

    def update_loading_state(self, title, speed, buffered, connected_peers,
                             available_peers):
        if not self.loading_details_visible:
            self.background_canvas.itemconfig(self.loading_speed_label,
                                              state="normal")
            self.background_canvas.itemconfig(self.loading_buffered_label,
                                              state="normal")
            self.background_canvas.itemconfig(self.loading_speed_value,
                                              state="normal")
            self.background_canvas.itemconfig(self.loading_buffered_value,
                                              state="normal")
            self.background_canvas.itemconfig(
                self.loading_peers_connected_label, state="normal")
            self.background_canvas.itemconfig(
                self.loading_peers_available_label, state="normal")
            self.background_canvas.itemconfig(
                self.loading_peers_connected_value, state="normal")
            self.background_canvas.itemconfig(
                self.loading_peers_available_value, state="normal")
            self.loading_details_visible = True

        self.background_canvas.itemconfig(self.loading_speed_value,
                                          text=write_size(speed) + "ps")
        self.background_canvas.itemconfig(self.loading_buffered_value,
                                          text=write_size(buffered))
        self.background_canvas.itemconfig(self.loading_peers_available_value,
                                          text=str(available_peers))
        self.background_canvas.itemconfig(self.loading_peers_connected_value,
                                          text=str(connected_peers))

    def media_update(self, old_data, new_data):
        if new_data.title is not None and self.state == UIState.Home:
            self.state = UIState.Loading
        if new_data.title is None and self.state != UIState.Home:
            self.state = UIState.Home

        if MediaManager().media_data.type == "Radio":
            self.set_now_playing(new_data.title)
        else:
            self.set_now_playing(None)

    def torrent_update(self, old_data, new_data):
        if self.state == UIState.Loading:
            self.update_loading_state(new_data.title, new_data.download_speed,
                                      new_data.total_streamed,
                                      new_data.connected, new_data.potential)

    def player_update(self, old_state, new_state):
        if new_state.state != old_state.state:
            if new_state.state == PlayerState.Playing:
                if MediaManager().media_data.type != "Radio":
                    self.state = UIState.Playing
                else:
                    self.state = UIState.Home

            if new_state.state == PlayerState.Paused:
                if MediaManager().media_data.type != "Radio":
                    self.state = UIState.Paused

    def fullscreen_toggle(self, event="none"):
        self.parent.focus_set()
        self.parent.attributes("-fullscreen", True)
        self.parent.wm_attributes("-topmost", 1)

    def fullscreen_cancel(self, event="none"):
        self.parent.attributes("-fullscreen", False)
        self.parent.wm_attributes("-topmost", 0)
        self.center_window()

    def center_window(self):
        sw = self.parent.winfo_screenwidth()
        sh = self.parent.winfo_screenheight()

        w = sw * 0.7
        h = sh * 0.7

        x = (sw - w) / 2
        y = (sh - h) / 2

        self.parent.geometry("%dx%d+%d+%d" % (w, h, x, y))

    def get_weather_data(self):
        while True:
            api_key = SecureSettings.get_string("open_weather_map_key")
            url = "http://api.openweathermap.org/data/2.5/group?id=2750947&units=metric&appid=" + api_key
            result = RequestFactory.make_request(url)
            if not result:
                Logger().write(LogVerbosity.Info, "Failed to get weather data")
                return

            data = json.loads(result.decode('utf8'))
            current_temp = data['list'][0]['main']['temp']
            icon = data['list'][0]['weather'][0]['icon'].replace('n', 'd')

            self.background_canvas.itemconfigure(
                self.weather_temp, text=str(round(current_temp, 1)) + "°C")

            image = Image.open(self.base_image_path + "Weather/" + icon +
                               ".png")
            resized = image.resize((140, 140), Image.ANTIALIAS)
            self.background_canvas.weather_icon = ImageTk.PhotoImage(resized)
            self.background_canvas.itemconfigure(
                self.weather_icon_image,
                image=self.background_canvas.weather_icon)

            time.sleep(60 * 30)
Exemple #15
0
class Socket:
    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 start(self):
        self.socket.bind(('0.0.0.0', self.port))

        self.running = True
        self.message_thread.start()

    def send_response(self, msg, ip, port):
        self.to_send_messages.append(NodeMessage(ip, port, msg))

    def send_query(self, msg, ip, port, on_response, on_timeout):
        self.to_send_messages.append(
            QueryMessage(NodeMessage(ip, port, msg), 0, on_response,
                         on_timeout))

    def message_thread_action(self):
        Logger().write(LogVerbosity.Debug, "Starting DHT socket")
        while self.running:
            self.receive()
            self.send()
            self.check()
            time.sleep(0.005)

    def receive(self):
        try:
            while True:
                data, sender = self.socket.recvfrom(2048)
                msg_object = BaseDHTMessage.from_bytes(data)
                if msg_object is None:
                    return

                if isinstance(msg_object, ErrorDHTMessage):
                    Logger().write(
                        LogVerbosity.Debug,
                        "DHT error message: " + str(msg_object.errorcode) +
                        " " + str(msg_object.errormsg))
                    continue
                else:
                    self.node_seen_handler(sender[0], sender[1], msg_object.id)

                msg = NodeMessage(sender[0], sender[1], msg_object)
                self.received_messages.append(msg)
                Logger().write(LogVerbosity.All, "Received DHT message")
        except OSError as e:
            return

    def send(self):
        for pending in list(self.to_send_messages):
            try:
                if not isinstance(pending, QueryMessage):
                    data = pending.message.to_bytes()
                    self.socket.sendto(data, (pending.ip, pending.port))
                    self.to_send_messages.remove(pending)
                    Logger().write(LogVerbosity.All, "Sent DHT response")
                else:
                    data = pending.message.message.to_bytes()
                    self.socket.sendto(
                        data, (pending.message.ip, pending.message.port))
                    pending.send_at = current_time()
                    self.awaiting_messages.append(pending)
                    self.to_send_messages.remove(pending)
                    Logger().write(LogVerbosity.All, "Sent DHT query")
            except OSError as e:
                Logger().write(LogVerbosity.All, "Failed to send: " + str(e))

    def check(self):
        for pending in list(self.awaiting_messages):
            if current_time() - pending.send_at > 10000:
                Logger().write(LogVerbosity.All, "DHT message timeout")
                self.node_timeout_handler(pending.message.ip,
                                          pending.message.port)
                pending.on_timeout()
                self.awaiting_messages.remove(pending)

        for received in list(self.received_messages):
            if isinstance(received.message, QueryDHTMessage):
                self.query_handler(received.ip, received.port,
                                   received.message)
                self.received_messages.remove(received)
                continue

            elif isinstance(received.message, ResponseDHTMessage):
                pending = [
                    x for x in self.awaiting_messages
                    if x.message.message.transaction_id ==
                    received.message.transaction_id
                ]
                if len(pending) == 0:
                    Logger().write(LogVerbosity.All,
                                   "DHT response for no request (timed out?)")
                    self.received_messages.remove(received)
                    continue

                Logger().write(LogVerbosity.All, "DHT message response")
                pending[0].on_response(received.message)  # answer to request
                self.received_messages.remove(received)
                self.awaiting_messages.remove(pending[0])
Exemple #16
0
class Observable(LogObject):
    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 register_callback(self, cb):
        self.__callbacks.append(cb)
        cb(self, self)

    def remove_callback(self, cb):
        self.__callbacks.remove(cb)

    def start_update(self):
        self.__start_state = {
            k: v
            for k, v in self.__dict__.items() if not k.startswith("_")
        }

    def stop_update(self):
        for k, v in self.__start_state.items():
            if self.__dict__[k] != v:
                self.__changed = True
                self.__wait_event.set()
                break
        if not self.__running:
            self.__update_thread.start()

    def changed(self):
        self.__changed = True
        self.__wait_event.set()
        if not self.__running:
            self.__update_thread.start()

    def reset(self):
        self.start_update()
        for k, v in self.__start_state.items():
            if isinstance(v, int) or isinstance(v, float):
                self.__dict__[k] = 0
            else:
                self.__dict__[k] = None
        self.stop_update()

    def __check_update(self):
        self.__running = True
        while self.__running:
            self.__wait_event.wait(self.__update_interval)
            self.__wait_event.clear()
            if current_time() - self.__last_update < (self.__update_interval *
                                                      1000):
                continue

            if self.__changed:
                self.__changed = False
                self.__last_update = current_time()
                dic = {
                    k: v
                    for k, v in self.__dict__.items() if not k.startswith("_")
                }
                last_update = namedtuple("Observable",
                                         dic.keys())(*dic.values())
                for cb in self.__callbacks:
                    try:
                        cb(self.__last_update_state or self, self)
                    except Exception as e:
                        Logger().write_error(e,
                                             "Exception in observer callback")
                self.__last_update_state = last_update
Exemple #17
0
class Peer(TorrentManager):
    @property
    def bitfield(self):
        # Only create a new bitfield when we actually have metadata for it
        if self.__bitfield is None and not self.torrent.is_preparing:
            self.__bitfield = Bitfield(self,
                                       self.torrent.data_manager.total_pieces)
        return self.__bitfield

    @property
    def state(self):
        return self._state

    @state.setter
    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()

    def __init__(self, id, torrent, uri, source):
        super().__init__(torrent, "Peer " + str(id))
        self.id = id
        self.torrent = torrent
        self.uri = uri
        self._state = PeerState.Initial
        self.source = source

        self.connection_manager = None
        self.download_manager = None
        self.metadata_manager = None
        self.extension_manager = None

        self.__bitfield = None
        self.communication_state = PeerCommunicationState(self)
        self.counter = None
        self.peer_speed = PeerSpeed.Low

        self.allowed_fast_pieces = []

        self.round_trips = 0
        self.round_trip_total = 0
        self.round_trip_average = 0
        self.max_blocks_log = 0
        self.speed_log = 0

        self.peer_start_task = None
        self.peer_state_task = None
        self.peer_stop_task = None

        self.stop_reason = "Torrent stopping"
        self.protocol_logger = ProtocolLogger(self)

    def adjust_round_trip_time(self, time):
        self.round_trips += 1
        self.round_trip_total += time
        self.round_trip_average = self.round_trip_total / self.round_trips

    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')

    def update(self):
        self.metadata_manager.update()
        self.download_manager.update()

    def check_peer_state(self):
        zero_speed_checks = 0
        while self.state == PeerState.Started:
            if current_time() - self.connection_manager.connected_on < 20000:
                time.sleep(1)
                continue

            if not self.torrent.peer_manager.should_stop_peers():
                time.sleep(1)
                continue

            if self.counter.total == 0:
                Logger().write(LogVerbosity.Info,
                               str(self.id) + " stopping not downloading peer")
                self.stop_async(
                    "Not downloading"
                )  # Stop since we haven't downloaded anything since connecting
                return

            if self.counter.value == 0:
                zero_speed_checks += 1
                if zero_speed_checks >= 10:
                    Logger().write(
                        LogVerbosity.Info,
                        str(self.id) +
                        " stopping currently not downloading peer")
                    self.stop_async(
                        "Not recently downloading"
                    )  # Stop since we haven't downloaded anything in the last 10 seconds
                    return
            else:
                zero_speed_checks = 0

            time.sleep(1)

    @staticmethod
    def add_connected_peer_stat(source):
        if source == PeerSource.DHT:
            Stats().add('peers_source_dht_connected', 1)
        elif source == PeerSource.HttpTracker:
            Stats().add('peers_source_http_tracker_connected', 1)
        elif source == PeerSource.UdpTracker:
            Stats().add('peers_source_udp_tracker_connected', 1)
        elif source == PeerSource.PeerExchange:
            Stats().add('peers_source_exchange_connected', 1)

    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 stop(self):
        if self.state == PeerState.Stopped:
            return

        self.state = PeerState.Stopping
        Logger().write(LogVerbosity.All, str(self.id) + ' Peer stopping')
        if self.peer_state_task is not None:
            self.peer_state_task.join()

        if self.state == PeerState.Stopped:
            return

        self.connection_manager.disconnect()
        self.download_manager.stop()
        self.extension_manager.stop()
        self.metadata_manager.stop()

        self.state = PeerState.Stopped
        self.peer_start_task.join()

        self.protocol_logger = None
        super().stop()
        self.finish()
        Logger().write(LogVerbosity.Debug,
                       str(self.id) + ' Peer stopped: ' + self.stop_reason)
Exemple #18
0
 def stop_torrent(self):
     if self.torrent:
         thread = CustomThread(self.torrent.stop, "Torrent stopper")
         thread.start()
         self.torrent = None
Exemple #19
0
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)
class PeerConnectionManager(LogObject):

    @property
    def ready_for_sending(self):
        return len(self.to_send_bytes) > 0 and current_time() - self.last_send > 10

    @property
    def ready_for_reading(self):
        return len(self.buffer) >= self._next_message_length

    def __init__(self, peer, uri):
        super().__init__(peer, "connection")

        self.peer = peer
        self.uri = uri
        self.to_send_bytes = bytearray()
        self.last_send = 0
        self.connected_on = 0
        self._last_communication = 0
        self._peer_timeout = Settings.get_int("peer_timeout")
        self._connection_timeout = Settings.get_int("connection_timeout") / 1000

        self.connection = TcpClient(uri.hostname, uri.port, self._connection_timeout)
        self.buffer = bytearray()

        self.buffer_in_size = 0
        self.buffer_out_size = 0

        self._next_message_length = 1
        self._buffer_position = 0
        self._receive_state = ReceiveState.ReceiveLength
        self._receive_buffer_size = 32768

        self.in_thread = None
        self.reading_handshake = True

    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 socket_reader(self):
        while self.peer.state == PeerState.Started:
            if len(self.buffer) > 1000000:
                time.sleep(0.01)
                continue

            data = self.connection.receive_available(self._receive_buffer_size)
            if data is None or len(data) == 0:
                self.peer.stop_async("Reading error")
                break

            self._last_communication = current_time()
            self.buffer += data
            self.buffer_in_size = len(self.buffer)
            time.sleep(0.001)

    def handle_read(self):
        received_messages = []
        messages_size = 0

        while True:
            buffer_size = len(self.buffer)
            if buffer_size - self._buffer_position < self._next_message_length:
                # cant read another complete message
                break

            # form messages from the buffer:
            if self._receive_state == ReceiveState.ReceiveLength:
                if self.reading_handshake:
                    offset, id_length = read_byte_as_int(self.buffer, 0)
                    msg_length = id_length + 49  # Handshake sends the length of the id, the rest of the handshake takes 49 bytes
                    if msg_length > len(self.buffer):
                        break
                    self.reading_handshake = False
                else:
                    offset, msg_length = read_integer(self.buffer, self._buffer_position)
                    self._buffer_position += 4

                self._next_message_length = msg_length
                self._receive_state = ReceiveState.ReceiveMessage

                if self._next_message_length < 0 or self._next_message_length > 17000:
                    Logger().write(LogVerbosity.Info, "Invalid next message length: " + str(self._next_message_length))
                    self.peer.stop_async("Invalid next msg length")
                    break
            else:
                total_data = self._buffer_position + self._next_message_length
                message = bytes(self.buffer[self._buffer_position: total_data])
                self._buffer_position = total_data
                self._next_message_length = 4
                self._receive_state = ReceiveState.ReceiveLength
                messages_size += len(message)
                received_messages.append(message)

        self.buffer = self.buffer[self._buffer_position:]
        self._buffer_position = 0
        self.buffer_in_size = len(self.buffer)
        return messages_size, received_messages

    def handle_write(self):
        success = self.connection.send(self.to_send_bytes)
        self.to_send_bytes.clear()
        self.buffer_out_size = 0
        self.last_send = current_time()
        self._last_communication = current_time()

        if not success:
            self.peer.stop_async("Write error")

    def send(self, data):
        self.to_send_bytes.extend(data)
        self.buffer_out_size = len(self.to_send_bytes)

    def disconnect(self):
        if self.connected_on != 0:
            Logger().write(LogVerbosity.Debug, str(self.peer.id) + ' disconnected')

        self.connection.disconnect()
        self.to_send_bytes.clear()

        if self.in_thread is not None:
            self.in_thread.join()
        self.buffer.clear()
        self.peer = None
 def request_master_cb(topic, callback, timeout, *args):
     data = to_JSON(args)
     request = SlaveClientController._send_request(topic, data)
     thread = CustomThread(SlaveClientController.wait_for_request_response, "Request callback " + topic, [request, timeout, callback])
     thread.start()
Exemple #22
0
class TradfriManager(metaclass=Singleton):

    api_factory = None
    api = None
    gateway = None
    enabled = False
    initialized = False
    last_init = 0

    def __init__(self):
        self.tradfri_state = TradfriState()
        self.observing_end = 0
        self.observing = False
        self.observe_thread = None

    def init(self):
        if self.initialized:
            Logger().write(LogVerbosity.Info, "already init")
            return

        if sys.platform != "linux" and sys.platform != "linux2":
            Logger().write(LogVerbosity.Info, "Lighting: Not initializing, no coap client available on windows")
            self.initialized = True
            self.tradfri_state.update_group(DeviceGroup(1, "Test group", True, 128, 6))
            self.tradfri_state.update_group(DeviceGroup(2, "Test group 2", False, 18, 6))
            return

        if current_time() - self.last_init < 5000:
            Logger().write(LogVerbosity.Info, "Tried initialization less than 5s ago")
            return

        Logger().write(LogVerbosity.All, "Start LightManager init")
        self.enabled = True
        if not self.initialized:
            ip = Settings.get_string("tradfri_hub_ip")
            identity = Database().get_stat_string("LightingId")
            key = Database().get_stat_string("LightingKey")

            if identity is None or key is None:
                Logger().write(LogVerbosity.Info, "Lighting: No identity/key found, going to generate new")
                # We don't have all information to connect, reset and start from scratch
                Database().remove_stat("LightingId")
                Database().remove_stat("LightingKey")
                key = None

                identity = uuid.uuid4().hex
                Database().update_stat("LightingId", identity)  # Generate and save a new id
                self.api_factory = APIFactory(host=ip, psk_id=identity)
            else:
                self.api_factory = APIFactory(host=ip, psk_id=identity, psk=key)

            self.api = self.api_factory.request
            self.gateway = Gateway()

            if key is None:
                try:
                    security_code = SecureSettings.get_string("tradfri_hub_code")  # the code at the bottom of the hub
                    key = self.api_factory.generate_psk(security_code)
                    Database().update_stat("LightingKey", key)  # Save the new key
                    Logger().write(LogVerbosity.Info, "Lighting: New key retrieved")
                except Exception as e:
                    Logger().write_error(e, "Unhandled exception")
                    return
            else:
                Logger().write(LogVerbosity.Info, "Lighting: Previously saved key found")

            try:
                self.initialized = True
                groups = self.get_device_groups()
                for group in groups:
                    self.tradfri_state.update_group(group)
            except Exception as e:
                Logger().write(LogVerbosity.Info, "Failed to init tradfri, clearing previous key to try generate new")
                self.initialized = False
                Database().remove_stat("LightingId")
                Database().remove_stat("LightingKey")
                Logger().write_error(e, "Failed to get groups from hub")

    def start_observing(self):
        Logger().write(LogVerbosity.Debug, "Start observing light data")
        self.observing = True
        if self.observing_end > current_time():
            Logger().write(LogVerbosity.All, "Still observing, not starting again")
            return  # still observing, the check observing thread will renew

        if not self.check_state():
            return

        self.observing_end = current_time() + 30000
        groups_commands = self.api(self.gateway.get_groups())
        result = self.api(groups_commands)
        for group in result:
            self.observe_group(group)

    def observe_group(self, group):
        Logger().write(LogVerbosity.All, "Starting observe for group " + group.name)
        self.observe_thread = CustomThread(lambda: self.api(group.observe(
            self.tradfri_state.update_group,
            lambda x: self.check_observe(group), duration=30)), "Light group observer", [])
        self.observe_thread.start()

    def check_observe(self, group):
        if self.observing:
            # Restart observing since it timed out
            Logger().write(LogVerbosity.Debug, "Restarting observing for group " + str(group.name))
            self.observe_group(group)

    def stop_observing(self):
        Logger().write(LogVerbosity.Debug, "Stop observing light data")
        self.observing = False

    def get_devices(self):
        if not self.check_state():
            return []

        Logger().write(LogVerbosity.All, "Get devices")
        devices_commands = self.api(self.gateway.get_devices())
        devices = self.api(devices_commands)
        return [d for d in [self.parse_device(x) for x in devices] if d is not None]

    def set_state(self, device_id, state):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set device state")
        device = self.api(self.gateway.get_device(device_id))
        if device.has_light_control:
            self.api(device.light_control.set_state(state))
        else:
            self.api(device.socket_control.set_state(state))

    def set_light_warmth(self, device_id, warmth):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set light warmth")
        device = self.api(self.gateway.get_device(device_id))
        self.api(device.light_control.set_color_temp(warmth))

    def set_light_dimmer(self, device_id, amount):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set light dimmer")
        device = self.api(self.gateway.get_device(device_id))
        self.api(device.light_control.set_dimmer(amount))

    def set_device_name(self, device_id, name):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set device name")
        device = self.api(self.gateway.get_device(device_id))
        self.api(device.set_name(name))

    def get_device_groups(self):
        if not self.check_state():
            return []

        Logger().write(LogVerbosity.All, "Get device groups")
        groups_commands = self.api(self.gateway.get_groups())
        result = self.api(groups_commands)
        Logger().write(LogVerbosity.All, "Get device groups: " + str([x.raw for x in result]))
        return [DeviceGroup(group.id, group.name, group.state, group.dimmer, len(group.member_ids)) for group in result]

    def get_devices_in_group(self, group):
        if not self.check_state():
            return []

        Logger().write(LogVerbosity.All, "Get lights in group")
        group = self.api(self.gateway.get_group(group))
        members = group.member_ids
        result = [self.api(self.gateway.get_device(x)) for x in members]
        return [d for d in [self.parse_device(x) for x in result] if d is not None]

    def set_group_name(self, group, name):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set group name")
        group = self.api(self.gateway.get_group(group))
        self.api(group.set_name(name))

    def set_group_state(self, group, state):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set group state")
        group = self.api(self.gateway.get_group(group))
        self.api(group.set_state(state))

    def set_group_dimmer(self, group, dimmer):
        if not self.check_state():
            return

        Logger().write(LogVerbosity.All, "Set group dimmer")
        group = self.api(self.gateway.get_group(group))
        self.api(group.set_dimmer(dimmer))

    def check_state(self):
        if not self.enabled:
            return False  # not available

        if not self.initialized:
            self.init()
            if not self.initialized:
                return False  # init failed
        return True

    @staticmethod
    def parse_device(data):
        if data.has_light_control:
            lights = []
            for light in data.light_control.lights:
                lights.append(LightDevice(
                    light.state,
                    light.dimmer,
                    light.color_temp,
                    light.hex_color))

            return LightControl(data.id,
                                data.name,
                                data.application_type,
                                data.last_seen.timestamp(),
                                data.reachable,
                                data.light_control.can_set_dimmer,
                                data.light_control.can_set_temp,
                                data.light_control.can_set_color,
                                lights)

        elif data.has_socket_control:
            sockets = []
            for socket in data.socket_control.sockets:
                sockets.append(SocketDevice(socket.state))

            return SocketControl(data.id, data.name, data.application_type, data.last_seen.timestamp(), data.reachable, sockets)
Exemple #23
0
 def throw_event(event_type, args):
     thread = CustomThread(EventManager.execute_handlers,
                           "EventHandler " + str(event_type),
                           args=[event_type, args])
     thread.start()
Exemple #24
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)
 def request_cb(self, topic, callback, timeout, room, *args):
     request_message = self._send_request(topic, args, room)
     thread = CustomThread(self.wait_for_request_response, "Request callback " + topic, [request_message, timeout, callback])
     thread.start()
Exemple #26
0
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)
Exemple #27
0
class RuleManager(metaclass=Singleton):
    conditions = {
        1: IsBetweenTimeCondition,
        2: IsPassingTimeCondition,
        3: IsHomeCondition,
        4: OnLeavingHomeCondition,
        5: OnComingHomeCondition
    }
    actions = {
        1: ToggleTradfriGroupAction,
        2: SetTemperatureAction,
        3: ToggleTvAction,
        4: PlayRadioAction
    }

    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 start(self):
        if Settings.get_bool("slave"):
            return

        self.running = True
        self.check_thread.start()

    def stop(self):
        self.running = False
        self.check_thread.join()

    def set_enabled(self, enabled):
        self.enabled = enabled
        Database().update_stat("rules_enabled", enabled)

    def check_rules(self):
        while self.running:
            Logger().write(LogVerbosity.All, "Checking rules")
            for rule in self.current_rules:
                if rule.check():
                    Logger().write(
                        LogVerbosity.Info, "Executing rule " + rule.name +
                        ": " + rule.description)
                    if self.enabled:
                        try:
                            rule.execute()
                        except Exception as e:
                            Logger().write_error(e, "Rule error")
                    Database().update_rule(rule)

            time.sleep(10)

    def update_rule(self, rule_id, active, name, actions, conditions):
        if rule_id == -1:
            rule = Rule(-1, name, current_time(), True, 0)
            self.current_rules.append(rule)
        else:
            rule = [x for x in self.current_rules if x.id == rule_id][0]
        rule.name = name
        rule.active = active
        rule.actions = []
        for action in actions:
            rule.add_action(-1, action[0],
                            [x for x in action[1:] if x is not None])

        rule.conditions = []
        for condition in conditions:
            rule.add_condition(-1, condition[0],
                               [x for x in condition[1:] if x is not None])

        rule.last_execution = 0
        Database().save_rule(rule)

    def remove_rule(self, rule_id):
        self.current_rules = [x for x in self.current_rules if x.id != rule_id]
        Database().remove_rule(rule_id)

    def get_rule(self, rule_id):
        return [x for x in self.current_rules if x.id == rule_id][0]

    def get_rules(self):
        return self.enabled, self.current_rules

    def get_actions_and_conditions(self):
        actions = [
            ActionModel(id, action.name, action.description,
                        action.parameter_descriptions)
            for id, action in self.actions.items()
        ]
        conditions = [
            ActionModel(id, condition.name, condition.description,
                        condition.parameter_descriptions)
            for id, condition in self.conditions.items()
        ]
        return actions, conditions

    def load_rules(self):
        db_rules = Database().get_rules()
        self.current_rules = self.parse_rules(db_rules)

    def parse_rules(self, rules):
        result = []
        for r in rules:
            rule = Rule(r.id, r.name, r.created, r.active, r.last_execution)
            for link in r.links:
                if link.rule_link_type == "Condition":
                    rule.add_condition(link.id, link.link_type,
                                       link.parameters)
                else:
                    rule.add_action(link.id, link.link_type, link.parameters)
            result.append(rule)
        return result

    @staticmethod
    def update_check_time(hour, minute):
        result = datetime.now()
        if result.hour > hour or (result.hour == hour
                                  and result.minute >= minute):
            result += timedelta(days=1)
        result = result.replace(hour=hour,
                                minute=minute,
                                second=0,
                                microsecond=0)
        return result