Esempio n. 1
0
class AudioGUIServerApplication:
    WINDOW_NAME = "Audio Server Application"

    AUDIO_FOLDER_NAME = "audio"
    SUPPORTED_FORMATS = [".wav", ".mp3"]

    PROGRESS_BAR_SIZE = 200
    LOOP_FREQUENCY = 22

    def __init__(self):

        self._window = Tk()

        self._window.title(self.WINDOW_NAME)
        self._window.protocol("WM_DELETE_WINDOW", self._close_application)
        self._window.resizable(1, 1)

        self._audio_server = ServerNetworkProcess()
        self._audio_server.start()

        self._audio_file_list = []
        self._selected_audio_file = ""

        self._audio_playing = False
        self._audio_data = []
        self._prev_audio_index = 0
        self._current_audio_index = constants.AUDIO_BYTE_FRAME_SIZE

        self._build_window_space()

        self._window.after(20, self._update_loop)
        self._window.mainloop()

        return

    def __del__(self):
        return

    def _close_application(self):
        self._audio_server.stop()
        self._window.quit()
        return

    def _build_window_space(self):

        # On the left most side there should be a list of the songs
        self._audio_file_list = self._get_audio_file_list()

        self._file_list_box = Listbox(self._window)
        self._file_list_box.grid(row=0, column=0, sticky=tkinter.W, rowspan=3)
        self._file_list_box.grid_configure(sticky="nsew")

        for audio_file_name in self._audio_file_list:
            self._file_list_box.insert(tkinter.END, audio_file_name)

        # Then in the middle want to then have the current song playing listed
        self._song_playing_text = tkinter.StringVar()
        self._song_playing_text.set("Nothing")
        self._song_playing_label = Label(self._window,
                                         textvariable=self._song_playing_text)
        self._song_playing_label.grid(row=0, column=1, rowspan=2)
        self._song_playing_label.grid_configure(sticky="nsew")

        # Want to have below it a progress bar of where in the song it is
        self._song_progress_bar = ttk.Progressbar(
            self._window, orient="horizontal", length=self.PROGRESS_BAR_SIZE)
        self._song_progress_bar.grid(row=2, column=1)
        self._song_progress_bar.grid_configure(sticky="nsew")

        # Set so the window properly adjust on resize
        self._window.grid_columnconfigure(0, weight=1)
        self._window.grid_columnconfigure(1, weight=1)
        self._window.grid_rowconfigure(0, weight=1)
        self._window.grid_rowconfigure(1, weight=1)

        return

    def _get_audio_file_list(self):
        audio_files = []
        for file in os.listdir(self.AUDIO_FOLDER_NAME):
            for file_extension in self.SUPPORTED_FORMATS:
                if file.endswith(file_extension):
                    audio_files.append(file)

        return audio_files

    def _update_loop(self):
        loop_start_time = datetime.datetime.now()

        selected_file = self._file_list_box.get(tkinter.ANCHOR)
        if self._selected_audio_file != selected_file:
            self._song_playing_text.set(selected_file)
            self._selected_audio_file = selected_file
            self._start_playing_audio_file()

        if self._audio_playing:
            self._update_audio_playback()

        loop_end_time = datetime.datetime.now()
        loop_run_time = (loop_end_time - loop_start_time).total_seconds()
        loop_run_time_ms = int(loop_run_time * 1000)

        if loop_run_time_ms >= self.LOOP_FREQUENCY:
            self._window.after(1, self._update_loop)
        else:
            next_loop_time = self.LOOP_FREQUENCY - loop_run_time_ms
            self._window.after(next_loop_time, self._update_loop)
        return

    def _start_playing_audio_file(self):
        actual_audio_file = os.path.join(self.AUDIO_FOLDER_NAME,
                                         self._selected_audio_file)
        file_data = pydub.AudioSegment.from_file(actual_audio_file)
        self._audio_data = file_data.raw_data

        self._audio_playing = True
        self._prev_audio_index = 0
        self._current_audio_index = constants.AUDIO_BYTE_FRAME_SIZE
        return

    def _update_audio_playback(self):
        audio_time = datetime.datetime.now()
        audio_segment = self._audio_data[self._prev_audio_index:self.
                                         _current_audio_index]
        audio_message = {
            constants.AUDIO_PAYLOAD_STR: list(audio_segment),
            constants.TIMESTAMP_STR: str(audio_time)
        }

        self._audio_server.add_audio_packet(audio_message, wait=False)

        self._prev_audio_index = self._current_audio_index
        self._current_audio_index += constants.AUDIO_BYTE_FRAME_SIZE

        if self._current_audio_index > len(self._audio_data):
            self._audio_playing = False
        else:
            self._update_progress_bar()

        return

    def _update_progress_bar(self):
        song_progress = self._current_audio_index / len(self._audio_data)
        progress_percent = song_progress * 100
        self._song_progress_bar["value"] = progress_percent
        return