コード例 #1
0
ファイル: FrontEnd.py プロジェクト: AndyGVSU/CIS343_CLI-Audio
 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)
コード例 #2
0
    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')
コード例 #3
0
 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
コード例 #4
0
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()
コード例 #5
0
ファイル: FrontEnd.py プロジェクト: charathmathew/cli-audio
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()
コード例 #6
0
ファイル: FrontEnd.py プロジェクト: charathmathew/cli-audio
 def __init__(self, player):
     self.library = Library()
     self.player = player
     curses.wrapper(self.menu)
コード例 #7
0
ファイル: FrontEnd.py プロジェクト: AndyGVSU/CIS343_CLI-Audio
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,"                                 ")