def __init__(self, player): """Player to communicate with from this class""" self.player = player """Page length for the library to display per page.""" self.pageLength = 12 """Library to pull songs from.""" self.library = Library(self.pageLength) """Wrapper for the curses menu.""" curses.wrapper(self.menu)
def __init__(self, player): """ Initializes the player and the library and creates the curse gui allowing the menu function to take over. If the screen size of the terminal is too small for some reason, A exception for screen size will be thrown and the program will stop. param player: The player for this FrontEnd. throws: CLI_Audio_Screen_Size_Exception if the screen size is too small """ if len(sys.argv) != 2: print("./cli-audio <song name>") exit() try: self.player = player self.player.play(sys.argv[1]) self.library = Library() curses.wrapper(self.menu) except Exception: raise CLI_Exception.CLI_Audio_Screen_Size_Exception ('Screen Size to Small')
def __init__(self, player): self.player = player os.chdir("./media") self.library = Library() try: self.player.play(sys.argv[1]) except Exception: raise Exception.Audio_File_Exception try: curses.wrapper(self.menu) except Exception: raise Exception.Screen_Size_Exception
class FrontEnd: """ The FrontEnd Class handles the cli gui for the user to interact with. It presents an interface that shows the current song being played while also presenting options for the user to take if they wish. The gui runs through a curse wrapper until the user quits the program Author: Ira Woodring, David Baas Version: 1.0 - 11 Attributes: player: The audio player for the cli library: The playlist queue for the cli stdscr: The gui object for the cli """ def __init__(self, player): """ Initializes the player and the library and creates the curse gui allowing the menu function to take over. If the screen size of the terminal is too small for some reason, A exception for screen size will be thrown and the program will stop. param player: The player for this FrontEnd. throws: CLI_Audio_Screen_Size_Exception if the screen size is too small """ if len(sys.argv) != 2: print("./cli-audio <song name>") exit() try: self.player = player self.player.play(sys.argv[1]) self.library = Library() curses.wrapper(self.menu) except Exception: raise CLI_Exception.CLI_Audio_Screen_Size_Exception ('Screen Size to Small') def menu(self, args): """ The menu function is the driver for the FrontEnd gui. It creates a cli interface for the user to interact with and runs the event loop to track user inputs. The commands are: p: play/pause c: change the song q: queue songs: this can take a file or a folder as an input n: play the next song l: list the songs in the queue ESC: quit program. """ self.stdscr = curses.initscr() self.stdscr.border() self.stdscr.addstr(0, 0, "cli-audio", curses.A_REVERSE) self.stdscr.addstr(5, 10, "c - Change current song") self.stdscr.addstr(6, 10, "p - Play/Pause") self.stdscr.addstr(7, 10, "q - Queue Songs") self.stdscr.addstr(8, 10, "n - Next Song") self.stdscr.addstr(9, 10, "l - List Queue") self.stdscr.addstr(10, 10, "ESC - Quit") self.updateSong() self.stdscr.refresh() while True: c = self.stdscr.getch() if c == 27: self.quit() elif c == ord('p'): self.player.pause() elif c == ord('c'): self.changeSong() self.updateSong() self.stdscr.touchwin() self.stdscr.refresh() elif c == ord('q'): self.queueSong() elif c == ord('n'): self.nextSong() self.updateSong() self.stdscr.touchwin() self.stdscr.refresh() elif c == ord('l'): self.listQueue() def updateSong(self): """ Updates the title listed as the song playing This takes place even if the song is invalid and not playing. """ self.stdscr.addstr(15, 10, " ") self.stdscr.addstr(15, 10, "Now playing: " + self.player.getCurrentSong()) def changeSong(self): """ Changes the song currently playing to a song of the users choice. This is achieved in two ways. First is by typing the path of a song file (relative or absolute) or by typing in the name of a folder containing songs. If the latter method is used then a prompt is displayed to ask which song from the list of files the user wants played. This method catches an exception related to the audio file if something goes wrong. """ changeWindow = curses.newwin(5, 40, 5, 50) changeWindow.border() changeWindow.addstr(0, 0, "What is the file path?", curses.A_REVERSE) self.stdscr.refresh() curses.echo() path = changeWindow.getstr(1, 1, 30) curses.noecho() del changeWindow self.stdscr.touchwin() self.stdscr.refresh() self.player.stop() #self.player.play(path.decode(encoding = "utf-8")) try: changeList = self.library.changeTrack( path.decode(encoding="utf-8")) changeListLen = len(changeList) if changeListLen == 1: self.player.play(path.decode(encoding="utf-8")) else: listWin = curses.newwin(changeListLen + 1, 100, 5, 50) #list the song options for i in range(changeListLen): listWin.addstr(i, 0, changeList[i]) listWin.addstr(changeListLen, 0, "Select Song, j = DOWN, k = UP ") i = 0 ch = None while ch != ord('\n'): listWin.addstr(i, 0, changeList[i], curses.A_REVERSE) self.stdscr.refresh() ch = listWin.getch() if ch == ord('j') and i + 1 < changeListLen: listWin.addstr(i, 0, changeList[i]) i = i + 1 elif ch == ord('k') and i - 1 >= 0: listWin.addstr(i, 0, changeList[i]) i = i - 1 #play the selected song self.player.play(changeList[i]) except CLI_Exception.CLI_Audio_File_Exception: self.printError('The file or folder does not exist') def nextSong(self): """ Cycles the player to the next song queued in the library. This method handles a file exception when the library list is empty. """ try: next = self.library.get_next_track() self.player.stop() self.player.play(next) except CLI_Exception.CLI_Audio_File_Exception: self.printError('The queue is empty') def queueSong(self): """ This method allows the user to queue up a series of songs for later play. This is achieved in two ways. First by specify the path of an audio file or specifying the name of a directory both means of adding to the queue will add to the queue. If the directory method is used then all the contents of the directory will be added to the queue. This method handles file exceptions for when an invalid file or folder name is given by the user. """ queueWindow = curses.newwin(5, 40, 5, 50) queueWindow.border() queueWindow.addstr(0, 0, "What is the file path?", curses.A_REVERSE) self.stdscr.refresh() curses.echo() path = queueWindow.getstr(1, 1, 30) curses.noecho() del queueWindow self.stdscr.touchwin() self.stdscr.refresh() try: self.library.add_tracks(path.decode(encoding="utf-8")) except CLI_Exception.CLI_Audio_File_Exception: self.printError('Error queueing file or folder') def listQueue(self): """ Prints a list of queue songs to the user. This is done by asking for the whole queue of songs in the libray and printing them to the screen. If the queue is empty a message indicating such will be displayed. """ queue = self.library.list_tracks() if len(queue) > 0: listWin = curses.newwin(len(queue), 40, 5, 50) for i in range(len(queue)): listWin.addstr(i, 0, queue[i]) self.stdscr.refresh() curses.echo() listWin.getch() curses.noecho() del listWin self.stdscr.touchwin() self.stdscr.refresh() else: self.printError('Nothing to list') def printError(self, message): """ If an error occurs weather an exception or otherwise, an error message is printed to the user explaining the error. The only error that cant be handled such as a screen exception the program just won't run. param: message: The error message being displayed. returns: nothing """ errorWindow = curses.newwin(5, 40, 5, 50) errorWindow.border() errorWindow.addstr(2, 2, message) self.stdscr.refresh() curses.echo() errorWindow.getch() curses.noecho() del errorWindow self.stdscr.touchwin() self.stdscr.refresh() def quit(self): """ Exits the cli program and also stops the player. """ self.player.stop() exit()
class FrontEnd: def __init__(self, player): self.library = Library() self.player = player curses.wrapper(self.menu) """Displays the main menu""" def menu(self, args): self.stdscr = curses.initscr() self.stdscr.border() self.stdscr.addstr(0,0, "CLI Audio Player",curses.A_REVERSE) self.stdscr.addstr(5,10, "c - Change current song") self.stdscr.addstr(6,10, "p - Play/Pause") self.stdscr.addstr(7,10, "l - Library") self.stdscr.addstr(8,10, "n - Next song in queue") self.stdscr.addstr(10,10, "ESC - Quit") height,width = self.stdscr.getmaxyx() if(height < 20 or width < 60): raise CLI_Audio_Exception.CLI_Audio_Screen_Size_Exception self.updateSong() self.stdscr.refresh() while True: c = self.stdscr.getch() if c == 27: self.quit() elif c == ord('l'): self.displayLibrary() self.stdscr.touchwin() self.stdscr.refresh() elif c == ord('p'): self.player.pause() elif c == ord('c'): self.changeSong() self.updateSong() self.stdscr.clear() curses.wrapper(self.menu) self.stdscr.touchwin() self.stdscr.refresh() elif c == ord('n'): next = self.library.getNextSong() if next != None: self.player.stop() self.player.play(next.decode(encoding="utf-8")) self.updateSong() self.stdscr.clear() self.stdscr.touchwin() self.stdscr.refresh() curses.wrapper(self.menu) else: self.player.resetCurrentSong() curses.wrapper(self.menu) """Updates the song in the Now Playing field""" def updateSong(self): self.stdscr.addstr(15,10, " ") self.stdscr.addstr(15,10, "Now playing: " + self.player.getCurrentSong()) """Changes the song to be played""" def changeSong(self): changeWindow = curses.newwin(5, 40, 5, 35) changeWindow.border() changeWindow.addstr(0,0, "Enter name of the song(including .wav)", curses.A_REVERSE) self.stdscr.refresh() curses.echo() songName = changeWindow.getstr(1,1, 30) if self.library.searchSong(songName) is True: playSong = songName else: raise CLI_Audio_Exception.CLI_Audio_File_Exception curses.noecho() del changeWindow self.stdscr.touchwin() self.stdscr.refresh() self.player.stop() self.player.play(playSong.decode(encoding="utf-8")) """Displays library (wav files)""" def displayLibrary(self): changeWindow = curses.newwin(24, 80, 0, 0) changeWindow.border() changeWindow.addstr(0,0, "Audio Library", curses.A_REVERSE) changeWindow.addstr(1,5, "Songs:") changeWindow.addstr(1,60, "b - Back") changeWindow.addstr(2,60, "a - add to queue") i = 0 x = 3 songs = self.library.songsList() for song in songs: i += 1 x += 1 changeWindow.addstr(x, 5, str(i)+". "+song) while True: c = changeWindow.getch() if c == ord('b'): curses.wrapper(self.menu) elif c == ord('a'): self.addQueue() self.stdscr.refresh() c = changeWindow.getch() path = changeWindow.getstr(20,5, 30) curses.noecho() del changeWindow self.stdscr.touchwin() self.stdscr.refresh() """Adds the chosen song to a queue""" def addQueue(self): queueBox = curses.newwin(5, 40, 5, 35) queueBox.border() queueBox.addstr(0,0, "Enter name of the song(including .wav)", curses.A_REVERSE) self.stdscr.refresh() curses.echo() songName = queueBox.getstr(1,1, 30) if self.library.searchSong(songName) is True: self.library.addToQueue(songName) curses.noecho() del queueBox self.stdscr.touchwin() self.stdscr.refresh() curses.wrapper(self.menu) def quit(self): self.player.stop() exit()
def __init__(self, player): self.library = Library() self.player = player curses.wrapper(self.menu)
class FrontEnd: """ Constructor of the class. Takes in self and the player. """ def __init__(self, player): """Player to communicate with from this class""" self.player = player """Page length for the library to display per page.""" self.pageLength = 12 """Library to pull songs from.""" self.library = Library(self.pageLength) """Wrapper for the curses menu.""" curses.wrapper(self.menu) """ Initializes the menu for the GUI. Additionally, provides functionality for the commands that the user can apply. """ def menu(self, args): self.stdscr = curses.initscr() """Max window size. If screen is less than this, then CLI_Audio_Screen_Size_Exception is thrown.""" screenSize = self.stdscr.getmaxyx() minY = 20 minX = 102 message = "" if (screenSize[0] < minY or screenSize[1] < minX): if (screenSize[0] < minY): message = message + "\nScreen size of " + str(screenSize[0]) + " isn't tall enough; must be at least " + str(minY) if (screenSize[1] < minX): message = message + "\nScreen size of " + str(screenSize[1]) + " isn't wide enough; must be at least " + str(minX) raise CLI_Audio_Screen_Size_Exception(message) """Initialize the curses window""" self.stdscr.border() self.stdscr.addstr(0,0, "cli-audio",curses.A_REVERSE) self.stdscr.addstr(5,10, "c - Change Current Song") self.stdscr.addstr(6,10, "p - Play/Pause") self.stdscr.addstr(7,10, "l - Library") self.stdscr.addstr(8,10, "[ - Next Library Page") self.stdscr.addstr(9,10, "] - Previous Library Page") self.stdscr.addstr(10,10, "ESC - Quit") self.updateSong() self.stdscr.refresh() self.libraryPad = curses.newwin(14,50,5,50) self.libraryPad.mvwin(5,50) self.libraryPad.border() self.libraryPad.refresh() wait = 0 while True: #Wait for user input. c = self.stdscr.getch() #escape = quit if c == 27: self.quit() elif c == ord('p'): self.player.pause() if self.player.getCurrentSong() == self.player.getStartSong(): self.drawError("No song selected!") #change song elif c == ord('c'): self.changeSong() #change library elif c == ord('l'): self.changeLibrary() #go back one page in library elif c == ord('['): if self.library.getPage() > 0: self.library.addPage(-1) self.refreshLibraryPad() elif self.library.isEmpty(): self.drawError("No library loaded!") #go forward a page in the library elif c == ord(']'): if self.library.getPage() < self.library.getTotalPages(): self.library.addPage(1) self.refreshLibraryPad() elif self.library.isEmpty(): self.drawError("No library loaded!") """ Update song function. Called when new song is loaded in. Displays song information. """ def updateSong(self): self.stdscr.addstr(16,10, " ") self.stdscr.addstr(15,10, "Now playing: ") self.stdscr.addstr(16,10, self.player.getCurrentSong()) """ Changes the current song playing. Creates a window where the user can select a song from the loaded library. """ def changeSong(self): if self.library.isEmpty(): self.drawError("No library loaded!") return self.resetError() changeWindow = curses.newwin(3, 30, 1, 50) changeWindow.border() changeWindow.addstr(0,0, "Select a song number:", curses.A_REVERSE) self.stdscr.refresh() curses.echo() songNumber = changeWindow.getstr(1,1, 30) curses.noecho() del changeWindow self.stdscr.touchwin() self.stdscr.refresh() if not self.player.getPaused(): self.player.stop() self.refreshLibraryPad() #Attempt to change the song with the given song number. try: songNumber = int(songNumber.decode(encoding="utf-8")) except ValueError: self.drawError("Song number invalid!") return #Send the update to the player. try: self.player.play(self.library.getFile(songNumber)) except KeyError: self.drawError("Song number out of library range!") return except CLI_Audio_File_Exception: self.drawError("Song file invalid!") return self.updateSong() """ Quits the player. Sends the quit command to the player as well. """ def quit(self): self.player.stop() exit() """ Changes the library. Opens a window for the user to input a directory path. """ def changeLibrary(self): self.resetError() changeWindow = curses.newwin(5, 40, 5, 50) changeWindow.border() changeWindow.addstr(0,0, "What is the file path?", curses.A_REVERSE) self.stdscr.refresh() curses.echo() path = changeWindow.getstr(1,1, 30) curses.noecho() del changeWindow self.stdscr.touchwin() self.stdscr.refresh() try: self.library.loadFiles(path) except CLI_Audio_File_Exception: self.drawError("Path does not exist!") self.refreshLibraryPad() """ Changes the page of the library. Used for both [ and ] input. Gets the next <pagelength> number of songs to display. """ def refreshLibraryPad(self): self.stdscr.addstr(19,50,"<PAGE " + str(self.library.getPage() + 1) + " OF " + str(self.library.getTotalPages() + 1) + ">") self.libraryPad.erase() self.libraryPad.border() if self.library.isEmpty(): self.libraryPad.addstr(1, 1, "No files found!") else: for y in range(0,self.pageLength): key = y + (self.pageLength * self.library.getPage()) if key < len(self.library): media = self.library.getFile(key) if len(media) >= 45: media = media[0:45] self.libraryPad.addstr(1 + y, 1, str(key) + ": " + media) self.libraryPad.refresh() """ Displays an error message in the curses window. """ def drawError(self, message): self.stdscr.addstr(3,5," ") self.stdscr.addstr(3,5,message) """ Resets the error window. """ def resetError(self): self.stdscr.addstr(3,5," ")