Ejemplo n.º 1
0
class MainController(tk.Frame):
    """
    Controller for our views
    """
    def __init__(self, parent):
        """Creates the main window"""
        tk.Frame.__init__(self, parent)
        self._root_win = tk.Toplevel()
        self._main_window = MainWindow(self._root_win, self)
        self._vlc_instance = vlc.Instance()
        self._player = self._vlc_instance.media_player_new()
        self.list_songs_callback()
        self.queue_titles = []

    def list_songs_callback(self):
        """ Lists song titles in listbox. """
        response = requests.get("http://localhost:5000/songs/all")
        song_list = response.json()
        self.song_title_list = []
        for song in song_list:
            self.song_title_list.append(song['title'])
        self._main_window.add_titles_to_listbox(self.song_title_list)

    def play_callback(self):
        """Play a song specified by the index. """
        index = self._main_window.get_index()
        response = requests.get("http://localhost:5000/songs/all")
        song_list = response.json()
        song = song_list[index]
        media_file = song['pathname'] + song['filename']
        if self._player.get_state() == vlc.State.Playing:
            self._player.stop()
        self.update_play_stats(song['filename'])
        media = self._vlc_instance.media_new_path(media_file)
        self._player.set_media(media)
        self._player.play()
        self._main_window.song_playing['text'] = song['title']
        self._main_window.artist_name['text'] = song['artist']
        self._main_window.runtime_value['text'] = song['runtime']
        self._main_window.album_name['text'] = song['album']
        self._main_window.genre_name['text'] = song['genre']
        self._main_window.state_value['text'] = "Playing"

    def pause_callback(self):
        """ Pause the player """
        if self._player.get_state() == vlc.State.Playing:
            self._player.pause()
            self._main_window.state_value['text'] = "Paused"

    def resume_callback(self):
        """ Resume playing """
        if self._player.get_state() == vlc.State.Paused:
            self._player.pause()
            self._main_window.state_value['text'] = "Playing"

    def stop_callback(self):
        """ Stop the player """
        self._player.stop()
        self._main_window.state_value['text'] = "Stopped"

    def quit_callback(self):
        """ Exit the application. """
        self.master.quit()

    def open_mp3_file(self):
        """ Load the file name selected"""
        abs_path = filedialog.askopenfilename(initialdir='.\\Music\\')
        path = os.getcwd() + "\\Music\\"
        file = os.path.basename(abs_path)
        if file.endswith('.mp3'):
            mp3_file = eyed3.load(os.path.join(path, file))
            runtime = mp3_file.info.time_secs
            mins = int(runtime // 60)
            secs = int(runtime % 60)
            song = Song(str(getattr(mp3_file.tag, 'title')),
                        str(getattr(mp3_file.tag,
                                    'artist')), '{}:{}'.format(mins, secs),
                        '{}'.format(path), '{}'.format(file),
                        str(getattr(mp3_file.tag, 'album')),
                        str(getattr(mp3_file.tag, 'genre')))
            self.add_callback(song)

    def add_callback(self, song):
        """ Add audio file. """
        data = {
            'title': song.title,
            'artist': song.artist,
            'runtime': song.runtime,
            'pathname': song.pathname,
            'filename': song.filename,
            'album': song.album,
            'genre': song.genre
        }

        response = requests.post("http://localhost:5000/songs", json=data)
        if response.status_code == 200:
            self.list_songs_callback()
            msg_str = song.title + " has been added to library"
            messagebox.showinfo(title="Song Added", message=msg_str)
        else:
            msg_str = response.content
            messagebox.showinfo(title="Error", message=msg_str)

    def update_rating(self, event):
        """Updates the rating for the selected song"""
        index = self._main_window.get_index()
        form_data = self._rate_song.get_form_data()
        try:
            form_data['rating'] = int(form_data['rating'])
            get_response = requests.get("http://localhost:5000/songs/all")
            song_list = get_response.json()
            song = song_list[index]
            response = requests.put("http://localhost:5000/songs/rating/" +
                                    song['filename'],
                                    json=form_data)
            if response.status_code == 200:
                message = song['title'] + " has been successfully rated"
                messagebox.showinfo(title="Song Rated", message=message)
                self._close_rate_song_popup()
            else:
                message = response.content
                messagebox.showinfo(title="Error", message=message)
        except ValueError:
            message = "Rating must be a number"
            messagebox.showinfo(title="Error", message=message)

    def update_play_stats(self, filename):
        """Updates the play count and last_played"""
        requests.put("http://localhost:5000/songs/play_count/" + filename)

    def delete_callback(self):
        """ Deletes selected song from the library. """
        index = self._main_window.get_index()
        get_response = requests.get("http://localhost:5000/songs/all")
        song_list = get_response.json()
        song = song_list[index]
        filename = song['filename']
        del_response = requests.delete("http://localhost:5000/songs/" +
                                       filename)

        if del_response.status_code == 200:
            self.list_songs_callback()
            msg_str = song['title'] + " has been deleted from library"
            messagebox.showinfo(title="Song Added", message=msg_str)
            if song['title'] in self.queue_titles:
                self.queue_titles.remove(song['title'])
        else:
            msg_str = del_response.content
            messagebox.showinfo(title="Song Deleted", message=msg_str)

    def rate_song_popup(self):
        """ Show Rating Popup Window """
        self._rate_win = tk.Toplevel()
        self._rate_song = RatingWindow(self._rate_win, self,
                                       self._main_window.get_title())

    def _close_rate_song_popup(self):
        """ Close Rating Popup """
        self._rate_win.destroy()

    def queue_pop_up(self):
        """Loads the Queue Window"""
        self._queue_win = tk.Toplevel()
        self._view_queue = ViewQueueWindow(self._queue_win, self,
                                           self.queue_titles)

    def delete_from_queue(self):
        """Removes a song from queue"""
        index = self._view_queue.get_index()
        self.queue_titles.pop(index)
        self._view_queue.list_songs_in_queue()

    def _close_queue_popup(self):
        """ Close Rating Popup """
        self._queue_win.destroy()

    def add_queue_popup(self):
        """Adds the selected song to the queue"""
        self._add_queue_win = tk.Toplevel()
        self._add_queue = AddQueueWindow(self._add_queue_win, self,
                                         self.song_title_list)

    def add_to_queue_callback(self):
        """Adds the selected song to the queue list box"""
        index = self._add_queue.get_index()
        get_response = requests.get("http://localhost:5000/songs/all")
        song_list = get_response.json()
        song = song_list[index]
        self._view_queue.listbox.insert(tk.END, song['title'])
        self.queue_titles.append(song['title'])

    def _close_add_queue_popup(self):
        """ Close Rating Popup """
        self._add_queue_win.destroy()
Ejemplo n.º 2
0
class MainController(tk.Frame):
    """
    Controller for our views
    """
    def __init__(self, parent):
        """Creates the main window"""
        tk.Frame.__init__(self, parent)

        # creates an instance of YouTubeAPI
        self.youtube_api = YouTubeAPI()

        # creates an instance of the MainWindow class
        self._root_win = tk.Toplevel()
        self._main_window = MainWindow(self._root_win, self)

        # defines a list to add all of the downloaded video titles
        self._video_titles = []

        # call this function to add all the names to the list at startup
        self.list_titles_callback()

    def download_callback(self):
        """Downloads a YouTube video with the specified URL
        Posts the video data to the API"""
        yt = self.download.yt_obj
        try:
            if self.download.format_label['text'] != "mp3":
                path = self.__validate_path()
                res = self.__validate_res()
                format = self.__validate_format()
                fps = self.__validate_fps()
                streams_list = self.__validate_video(yt, format, res, fps)
                video = streams_list[0]
                # Checks if the file already exists in the directory
                for clip in self.youtube_api.get_all_videos():
                    file, extension = clip['filename'].split(".")
                    if yt.title == clip['title'] and yt.author == clip['author'] and \
                            path == clip['pathname'] and extension == format:
                        raise ValueError("File already exists")
                file_location = video.download(path)

                data = {
                    'title': yt.title,
                    'author': yt.author,
                    'resolution': video.resolution,
                    'frame_rate': video.fps,
                    'pathname': path,
                    'filename': os.path.basename(file_location)
                }

                response = self.youtube_api.add_video(data)
                msg = "Your video has been downloaded"
                messagebox.showinfo(title="Downloaded", message=msg)
                self.download_win.destroy()
                self.list_titles_callback()
            else:
                streams_list, path = self.__validate_audio(yt)
                video = streams_list[0]
                for clip in self.youtube_api.get_all_videos():
                    if yt.title == clip['title'] and yt.author == clip['author'] \
                            and path == clip["pathname"]:
                        raise ValueError("File already exists")
                file_location = video.download(path)
                file_name, extension = os.path.basename(file_location).split(
                    ".")
                file = file_name + ".mp3"
                os.rename(file_location, path + file)

                data = {
                    'title': yt.title,
                    'author': yt.author,
                    'resolution': video.resolution,
                    'frame_rate': video.fps,
                    'pathname': path,
                    'filename': file
                }
                response = self.youtube_api.add_video(data)
                msg = "Your video has been downloaded"
                messagebox.showinfo(title="Downloaded", message=msg)
                self.download_win.destroy()
                self.list_titles_callback()
        except ValueError as e:
            messagebox.showinfo(title="Error", message=str(e))

    def __validate_path(self) -> str:
        """Checks if a path is chosen"""
        path = self.download.file_label['text']
        if path == "":
            raise ValueError("Pick a file location.")
        return path

    def __validate_res(self) -> str:
        """Checks if a resolution is chosen"""
        res = self.download.res_label['text']
        if res == "":
            raise ValueError("Pick a resolution")
        return res

    def __validate_format(self) -> str:
        """Checks if a format is chosen"""
        format = self.download.format_label['text']
        if format == "":
            raise ValueError("Pick a file format")
        return format

    def __validate_fps(self) -> str:
        """Checks if fps is chosen"""
        fps = self.download.fps_label['text']
        if fps == "":
            raise ValueError("Pick fps")
        return fps

    def __validate_video(self, yt, format, res, fps) -> list:
        """Validates streams for videos"""
        try:
            streams_list = []
            for stream in yt.streams:
                type, extension = stream.mime_type.split("/")
                if extension == format and stream.resolution == res and stream.fps == fps:
                    streams_list.append(stream)
            if len(streams_list) < 1:
                raise ValueError
            return streams_list
        except Exception:
            msg = "This format is not available. Try picking another format."
            messagebox.showinfo(title="Error", message=msg)

    def __validate_audio(self, yt):
        """Validates streams for audio"""
        format = self.download.format_label['text']
        path = self.download.file_label['text']
        if path == "":
            raise ValueError("Pick a file location.")
        streams_list = []
        for stream in yt.streams:
            type, old_extenstion = stream.mime_type.split("/")
            if type == "audio":
                new_extention = old_extenstion.replace(old_extenstion, "mp3")
                if new_extention == format:
                    streams_list.append(stream)
        return streams_list, path

    def list_titles_callback(self):
        """ Lists video titles in listbox.
        Gets all the videos stored in the database and adds the title"""
        self._video_titles.clear()  # removes all items in the list

        # calls API and returns a list of videos
        video_list = self.youtube_api.get_all_videos()
        for video in video_list:
            self._video_titles.append(video['title'])

        # inserts the titles to the tkinter listbox
        self._main_window.insert_to_listbox(self._video_titles)

    def play_video(self, event):
        """Plays the selected video"""
        index = self._main_window.get_index()
        if self._main_window.get_title() == "":
            msg_str = "You must select a video first."
            messagebox.showinfo(title="Error", message=msg_str)
        else:
            video_list = self.youtube_api.get_all_videos()
            video = video_list[index]
            file_location = video['pathname'] + video['filename']
            os.startfile(file_location)

    def rename_window_popup(self, event):
        """Launches the Rename Window"""
        title = self._main_window.get_title()
        if title == "":
            msg_str = "You must select a video first to rename."
            messagebox.showinfo(title="Error", message=msg_str)
        else:
            self.rename_win = tk.Toplevel()
            self.rename = RenameWindow(self.rename_win, self, title)

    def details_window_popup(self, event):
        """Launches a window with the video details listed"""
        if self._main_window.get_title() == "":
            msg_str = "You must select a video first."
            messagebox.showinfo(title="Error", message=msg_str)
        else:
            index = self._main_window.get_index()
            video_list = self.youtube_api.get_all_videos()
            video = video_list[index]
            self.details_win = tk.Toplevel()
            self.details = DetailsWindow(self.details_win, video)

    def download_win_popup(self):
        """Launches the Download settings window"""
        try:
            yt_obj = YouTube(self._main_window.get_link())
            self.download_win = tk.Toplevel()
            self.download = DownloadWindow(self.download_win, self, yt_obj)
        except Exception:
            msg_str = "Please paste a valid YouTube URL"
            messagebox.showinfo(title="Error", message=msg_str)

    def update_title(self, event):
        """Updates the title of the video - sends request to API"""
        index = self._main_window.get_index()
        form_data = self.rename.get_form_data()
        if form_data['title'] == "":
            message = "Field cannot be left empty"
            messagebox.showinfo(title="Error", message=message)
        else:
            video_list = self.youtube_api.get_all_videos()
            video = video_list[index]

            response = self.youtube_api.update_title(form_data,
                                                     video['pathname'],
                                                     video['filename'])

            if response == 200:
                message = "Video Title has been updated"
                messagebox.showinfo(title="Video Updated", message=message)
                self.rename_win.destroy()
                self.list_titles_callback()
            else:
                message = response
                messagebox.showinfo(title="Error", message=message)

    def delete_callback(self, event):
        """ Deletes selected video from the library. """
        index = self._main_window.get_index(
        )  # returns index of title in listbox
        if self._main_window.get_title(
        ) == "":  # checks if you selected a video before deleting
            msg_str = "You must select a video first."
            messagebox.showinfo(title="Error", message=msg_str)
        else:
            # gets a list of all the videos in the database
            video_list = self.youtube_api.get_all_videos()
            video = video_list[index]  # gets the specific video you chose
            filename = video['filename']

            # sends a delete request to the API
            del_response = self.youtube_api.delete_video(
                video['pathname'], filename)

            if del_response == 200:
                msg_str = video['title'] + " has been deleted from library"
                messagebox.showinfo(title="Video Deleted", message=msg_str)
                self.list_titles_callback()
                os.remove(video['pathname'] + filename)
            else:
                msg_str = del_response
                messagebox.showinfo(title="Error", message=msg_str)