Example #1
0
class AsyncMusicPlayer(threading.Thread):
    '''Music Player.
    
    MusicPlayer가 동기적이기 때문에 이것을 비동기적으로 명령을 처리
    하기 위해서 Thread로 만듬

    외부와의 데이터 교환:
    - playlist        : 플레이 리스트
    - command_list    : 명령 수행
    '''

    def __init__(self):
        threading.Thread.__init__(self)

        # 현재 플레이 중인 Url
        self.url = ''
        # 현재 플레이 되고 있는 노래
        self.current_song = None

        # webbrowser player 인스턴스
        self.player = MusicPlayer()

        # DB
        self.store = Store()

    def run(self):
        '이 쓰레드에서 수행할 로직'

        while True:
            try:
                # 0.5초를 주기로 명령 수행
                time.sleep(0.5)

                # 광고가 나오는지 확인해서 넘긴다.
                # 보통 youtube 광고는 5초다.
                # TODO: 광고가 나오면 volume을 줄이도록 한다.
                self.player.skip_if_exists_ad()

                if self.url == '':
                    self.play_next_song()
                
                # URL이 변경되었으면 표시한다.
                url = self.player.current_url()
                if( self.url != url ):
                    self.url = url
                    # TODO:
                    #   - 여기에서 곡을 추가하는 로직을 넣으면
                    #   - 내가 듣는 링크를 플레이 리스트로 만들 수 있다.
                    print(self.url)
                    
                # 노래가 중지되면 다음 노래
                if self.player.is_finished() :

                    # played_count 수를 하나 증가 시킨다.
                    if self.current_song:
                        self.current_song.played_count += 1
                        self.store.update(self.current_song)

                    self.play_next_song()
                elif self.player.is_unplable():
                    self.play_next_song()
                self.handle_cmd();
            except queue.Empty:
                pass
            except KeyboardInterrupt:
                break
            except Exception as e:
                # 에러가 발생하면 에러의 종료를 출력
                #print('----')
                #print(type(e))
                #print(e)
                break
                

    def play_next_song(self):
        " 다음 곡 "

        # 플레이 리스트에서 하나 꺼낸다.
        playlist_lock.acquire()
        try:
            song = playlist.pop(0)
            url = song.url
        except:
            url = None
        playlist_lock.release()

        # url이 있으면 다음곡 플레이
        if url:
            self.current_song = song
            self.player.play_url(song.url)

    def stop(self):
        " 일시 정지 "
        self.player.stop()

    def play(self):
        " 다시 플레이"
        self.player.play()

    def handle_cmd(self):
        "명령 처리"
        data = command_list.get(block=False)
        if data:
            cmd, param = data
            if cmd == 'forward':
                self.play_next_song()
            elif cmd == 'stop':
                self.stop()
            elif cmd == 'play':
                self.play()
Example #2
0
class GTK_Main:
    def __init__(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title("Yamp!")
        window.set_default_size(450, 300)
        window.connect("destroy", gtk.main_quit, "WM destroy")
        window.set_position(gtk.WIN_POS_CENTER)

        self.player = MusicPlayer()
        self.player.add_observer(self)

        self.mb = gtk.MenuBar()
        self.filemenu = gtk.Menu()

        self.filem = gtk.MenuItem("File")
        self.filem.set_submenu(self.filemenu)

        self.menuOpen = gtk.MenuItem("Open")
        self.menuOpen.connect("activate", self.open_file_dialog)
        self.menuExit = gtk.MenuItem("Exit")
        self.menuExit.connect("activate", gtk.main_quit)

        self.filemenu.append(self.menuOpen)
        self.filemenu.append(self.menuExit)

        self.mb.append(self.filem)

        vbox = gtk.VBox(False, 2)
        window.add(vbox)
        vbox.pack_start(self.mb, False, False, 0)

        self.imgStop = gtk.Image()
        self.imgPlay = gtk.Image()
        self.imgNext = gtk.Image()
        self.imgPrev = gtk.Image()
        self.imgPause = gtk.Image()

        self.imgStop.set_from_stock(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_BUTTON)
        self.imgPause.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON)
        self.imgPlay.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
        self.imgPrev.set_from_stock(gtk.STOCK_MEDIA_PREVIOUS, gtk.ICON_SIZE_BUTTON)
        self.imgNext.set_from_stock(gtk.STOCK_MEDIA_NEXT, gtk.ICON_SIZE_BUTTON)

        self.lblArtist = gtk.Label()
        self.lblAlbum = gtk.Label()
        self.lblSongTitle = gtk.Label()

        self.lblArtist.set_use_markup(True)
        self.lblAlbum.set_use_markup(True)
        self.lblSongTitle.set_use_markup(True)

        self.buttonPlay = gtk.Button()
        self.buttonNext = gtk.Button()
        self.buttonPrev = gtk.Button()
        self.buttonStop = gtk.Button()

        self.buttonStop.set_relief(gtk.RELIEF_NONE)
        self.buttonPlay.set_relief(gtk.RELIEF_NONE)
        self.buttonPrev.set_relief(gtk.RELIEF_NONE)
        self.buttonNext.set_relief(gtk.RELIEF_NONE)

        self.buttonStop.add(self.imgStop)
        self.buttonPlay.add(self.imgPlay)
        self.buttonPrev.add(self.imgPrev)
        self.buttonNext.add(self.imgNext)

        self.buttonPlay.connect("clicked", self.play_action)
        self.buttonNext.connect("clicked", self.next_action)
        self.buttonPrev.connect("clicked", self.prev_action)
        self.buttonStop.connect("clicked", self.stop_action)

        self.imgCover = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file("./music_cd.png")
        scaled_buf = pixbuf.scale_simple(84, 84, gtk.gdk.INTERP_BILINEAR)
        self.imgCover.set_from_pixbuf(scaled_buf)

        self.sw = gtk.ScrolledWindow()
        self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        store = self.create_model()

        self.treeView = gtk.TreeView(store)
        self.treeView.connect("row-activated", self.on_activated)
        self.treeView.set_rules_hint(True)
        self.sw.add(self.treeView)
        self.create_columns(self.treeView)

        hboxButtons = gtk.HBox(False, 5)
        hboxButtons.pack_start(self.buttonPrev, False, False, 0)
        hboxButtons.pack_start(self.buttonPlay, False, False, 0)
        hboxButtons.pack_start(self.buttonStop, False, False, 0)
        hboxButtons.pack_start(self.buttonNext, False, False, 0)

        vboxInfos = gtk.VBox(False, 0)
        self.lblSongTitle.set_alignment(0, 0.5)
        self.lblArtist.set_alignment(0, 0.5)
        self.lblAlbum.set_alignment(0, 0.5)
        vboxInfos.pack_start(hboxButtons, True, True, 0)
        vboxInfos.pack_start(self.lblSongTitle, True, True, 0)
        vboxInfos.pack_start(self.lblArtist, True, True, 0)
        vboxInfos.pack_start(self.lblAlbum, True, True, 0)

        hbox = gtk.HBox(False, 10)
        hbox.pack_start(self.imgCover, False, False, 0)
        hbox.pack_start(vboxInfos, False, False, 0)

        vbox.pack_start(hbox, False, False, 5)
        vbox.pack_start(self.sw, True, True, 0)
        window.show_all()

    def update(self, message=None, song=None):
        if message == "reset":
            self.buttonPlay.set_image(self.imgPlay)
        elif message == "pause":
            self.buttonPlay.set_image(self.imgPlay)
        elif message == "play":
            if song is not None:
                self.lblArtist.set_markup("<b>" + song.get_artist() + "</b>")
                self.lblAlbum.set_markup("<b>" + song.get_album() + "</b>")
                self.lblSongTitle.set_markup("<b>#{} - {}</b>".format(song.get_track(), song.get_title()))
            self.buttonPlay.set_image(self.imgPause)
        elif message == "update_playlist":
            self.update_model()
        else:
            print("Error : unknow message {}".format(message))

    def update_model(self):
        for song in self.player.get_playlist():
            self.treeView.get_model().append(
                [song.get_track(), song.get_title(), song.get_artist(), song.get_album(), song.get_path()]
            )

    def create_model(self):
        store = gtk.ListStore(str, str, str, str, str)
        return store

    def on_activated(self, widget, row, col):
        model = widget.get_model()
        song = Song(model[row][1], model[row][2], model[row][3], model[row][0], model[row][4])
        if self.player.is_playing():
            self.player.stop()
        self.player.play(song)

    def create_columns(self, treeView):
        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Track #", rendererText, text=0)
        column.set_sort_column_id(0)
        treeView.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Title", rendererText, text=1)
        column.set_sort_column_id(1)
        treeView.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Artist", rendererText, text=2)
        column.set_sort_column_id(2)
        treeView.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Album", rendererText, text=3)
        column.set_sort_column_id(3)
        treeView.append_column(column)

    def play_action(self, w):
        if w == self.buttonPlay:
            if self.player.is_playing():
                self.player.pause()
            else:
                self.player.play()

    def next_action(self, w):
        if w == self.buttonNext:
            self.player.play_next()

    def prev_action(self, w):
        if w == self.buttonPrev:
            self.player.play_prev()

    def stop_action(self, w):
        if w == self.buttonStop:
            self.player.stop()

    def open_file_dialog(self, w):
        chooser = gtk.FileChooserDialog(
            "Open",
            action=gtk.FILE_CHOOSER_ACTION_OPEN,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK),
        )
        chooser.set_select_multiple(True)
        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            filenames = chooser.get_filenames()
            self.player.stop()
            self.update("reset")
            self.player.set_playlist(filenames)

        chooser.destroy()
Example #3
0
class AsyncMusicPlayer(threading.Thread):
    '''Music Player.
    
    MusicPlayer가 동기적이기 때문에 이것을 비동기적으로 명령을 처리
    하기 위해서 Thread로 만듬

    외부와의 데이터 교환:
    - playlist        : 플레이 리스트
    - command_list    : 명령 수행
    '''
    def __init__(self):
        threading.Thread.__init__(self)

        # 현재 플레이 중인 Url
        self.url = ''
        # 현재 플레이 되고 있는 노래
        self.current_song = None

        # webbrowser player 인스턴스
        self.player = MusicPlayer()

        # DB
        self.store = Store()

    def run(self):
        '이 쓰레드에서 수행할 로직'

        while True:
            try:
                # 0.5초를 주기로 명령 수행
                time.sleep(0.5)

                # 광고가 나오는지 확인해서 넘긴다.
                # 보통 youtube 광고는 5초다.
                # TODO: 광고가 나오면 volume을 줄이도록 한다.
                self.player.skip_if_exists_ad()

                if self.url == '':
                    self.play_next_song()

                # URL이 변경되었으면 표시한다.
                url = self.player.current_url()
                if (self.url != url):
                    self.url = url
                    # TODO:
                    #   - 여기에서 곡을 추가하는 로직을 넣으면
                    #   - 내가 듣는 링크를 플레이 리스트로 만들 수 있다.
                    print(self.url)

                # 노래가 중지되면 다음 노래
                if self.player.is_finished():

                    # played_count 수를 하나 증가 시킨다.
                    if self.current_song:
                        self.current_song.played_count += 1
                        self.store.update(self.current_song)

                    self.play_next_song()
                elif self.player.is_unplable():
                    self.play_next_song()
                self.handle_cmd()
            except queue.Empty:
                pass
            except KeyboardInterrupt:
                break
            except Exception as e:
                # 에러가 발생하면 에러의 종료를 출력
                #print('----')
                #print(type(e))
                #print(e)
                break

    def play_next_song(self):
        " 다음 곡 "

        # 플레이 리스트에서 하나 꺼낸다.
        playlist_lock.acquire()
        try:
            song = playlist.pop(0)
            url = song.url
        except:
            url = None
        playlist_lock.release()

        # url이 있으면 다음곡 플레이
        if url:
            self.current_song = song
            self.player.play_url(song.url)

    def stop(self):
        " 일시 정지 "
        self.player.stop()

    def play(self):
        " 다시 플레이"
        self.player.play()

    def handle_cmd(self):
        "명령 처리"
        data = command_list.get(block=False)
        if data:
            cmd, param = data
            if cmd == 'forward':
                self.play_next_song()
            elif cmd == 'stop':
                self.stop()
            elif cmd == 'play':
                self.play()
Example #4
0
class GTK_Main:
    def __init__(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title("Yamp!")
        window.set_default_size(450, 300)
        window.connect("destroy", gtk.main_quit, "WM destroy")
        window.set_position(gtk.WIN_POS_CENTER)

        self.player = MusicPlayer()
        self.player.add_observer(self)

        self.mb = gtk.MenuBar()
        self.filemenu = gtk.Menu()

        self.filem = gtk.MenuItem("File")
        self.filem.set_submenu(self.filemenu)

        self.menuOpen = gtk.MenuItem("Open")
        self.menuOpen.connect("activate", self.open_file_dialog)
        self.menuExit = gtk.MenuItem("Exit")
        self.menuExit.connect("activate", gtk.main_quit)

        self.filemenu.append(self.menuOpen)
        self.filemenu.append(self.menuExit)

        self.mb.append(self.filem)

        vbox = gtk.VBox(False, 2)
        window.add(vbox)
        vbox.pack_start(self.mb, False, False, 0)

        self.imgStop = gtk.Image()
        self.imgPlay = gtk.Image()
        self.imgNext = gtk.Image()
        self.imgPrev = gtk.Image()
        self.imgPause = gtk.Image()

        self.imgStop.set_from_stock(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_BUTTON)
        self.imgPause.set_from_stock(gtk.STOCK_MEDIA_PAUSE,
                                     gtk.ICON_SIZE_BUTTON)
        self.imgPlay.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
        self.imgPrev.set_from_stock(gtk.STOCK_MEDIA_PREVIOUS,
                                    gtk.ICON_SIZE_BUTTON)
        self.imgNext.set_from_stock(gtk.STOCK_MEDIA_NEXT, gtk.ICON_SIZE_BUTTON)

        self.lblArtist = gtk.Label()
        self.lblAlbum = gtk.Label()
        self.lblSongTitle = gtk.Label()

        self.lblArtist.set_use_markup(True)
        self.lblAlbum.set_use_markup(True)
        self.lblSongTitle.set_use_markup(True)

        self.buttonPlay = gtk.Button()
        self.buttonNext = gtk.Button()
        self.buttonPrev = gtk.Button()
        self.buttonStop = gtk.Button()

        self.buttonStop.set_relief(gtk.RELIEF_NONE)
        self.buttonPlay.set_relief(gtk.RELIEF_NONE)
        self.buttonPrev.set_relief(gtk.RELIEF_NONE)
        self.buttonNext.set_relief(gtk.RELIEF_NONE)

        self.buttonStop.add(self.imgStop)
        self.buttonPlay.add(self.imgPlay)
        self.buttonPrev.add(self.imgPrev)
        self.buttonNext.add(self.imgNext)

        self.buttonPlay.connect("clicked", self.play_action)
        self.buttonNext.connect("clicked", self.next_action)
        self.buttonPrev.connect("clicked", self.prev_action)
        self.buttonStop.connect("clicked", self.stop_action)

        self.imgCover = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file("./music_cd.png")
        scaled_buf = pixbuf.scale_simple(84, 84, gtk.gdk.INTERP_BILINEAR)
        self.imgCover.set_from_pixbuf(scaled_buf)

        self.sw = gtk.ScrolledWindow()
        self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        store = self.create_model()

        self.treeView = gtk.TreeView(store)
        self.treeView.connect("row-activated", self.on_activated)
        self.treeView.set_rules_hint(True)
        self.sw.add(self.treeView)
        self.create_columns(self.treeView)

        hboxButtons = gtk.HBox(False, 5)
        hboxButtons.pack_start(self.buttonPrev, False, False, 0)
        hboxButtons.pack_start(self.buttonPlay, False, False, 0)
        hboxButtons.pack_start(self.buttonStop, False, False, 0)
        hboxButtons.pack_start(self.buttonNext, False, False, 0)

        vboxInfos = gtk.VBox(False, 0)
        self.lblSongTitle.set_alignment(0, 0.5)
        self.lblArtist.set_alignment(0, 0.5)
        self.lblAlbum.set_alignment(0, 0.5)
        vboxInfos.pack_start(hboxButtons, True, True, 0)
        vboxInfos.pack_start(self.lblSongTitle, True, True, 0)
        vboxInfos.pack_start(self.lblArtist, True, True, 0)
        vboxInfos.pack_start(self.lblAlbum, True, True, 0)

        hbox = gtk.HBox(False, 10)
        hbox.pack_start(self.imgCover, False, False, 0)
        hbox.pack_start(vboxInfos, False, False, 0)

        vbox.pack_start(hbox, False, False, 5)
        vbox.pack_start(self.sw, True, True, 0)
        window.show_all()

    def update(self, message=None, song=None):
        if message == "reset":
            self.buttonPlay.set_image(self.imgPlay)
        elif message == "pause":
            self.buttonPlay.set_image(self.imgPlay)
        elif message == "play":
            if song is not None:
                self.lblArtist.set_markup("<b>" + song.get_artist() + "</b>")
                self.lblAlbum.set_markup("<b>" + song.get_album() + "</b>")
                self.lblSongTitle.set_markup("<b>#{} - {}</b>".format(
                    song.get_track(), song.get_title()))
            self.buttonPlay.set_image(self.imgPause)
        elif message == "update_playlist":
            self.update_model()
        else:
            print("Error : unknow message {}".format(message))

    def update_model(self):
        for song in self.player.get_playlist():
            self.treeView.get_model().append([
                song.get_track(),
                song.get_title(),
                song.get_artist(),
                song.get_album(),
                song.get_path()
            ])

    def create_model(self):
        store = gtk.ListStore(str, str, str, str, str)
        return store

    def on_activated(self, widget, row, col):
        model = widget.get_model()
        song = Song(model[row][1], model[row][2], model[row][3], model[row][0],
                    model[row][4])
        if self.player.is_playing():
            self.player.stop()
        self.player.play(song)

    def create_columns(self, treeView):
        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Track #", rendererText, text=0)
        column.set_sort_column_id(0)
        treeView.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Title", rendererText, text=1)
        column.set_sort_column_id(1)
        treeView.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Artist", rendererText, text=2)
        column.set_sort_column_id(2)
        treeView.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Album", rendererText, text=3)
        column.set_sort_column_id(3)
        treeView.append_column(column)

    def play_action(self, w):
        if w == self.buttonPlay:
            if self.player.is_playing():
                self.player.pause()
            else:
                self.player.play()

    def next_action(self, w):
        if w == self.buttonNext:
            self.player.play_next()

    def prev_action(self, w):
        if w == self.buttonPrev:
            self.player.play_prev()

    def stop_action(self, w):
        if w == self.buttonStop:
            self.player.stop()

    def open_file_dialog(self, w):
        chooser = gtk.FileChooserDialog(
            "Open",
            action=gtk.FILE_CHOOSER_ACTION_OPEN,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
                     gtk.RESPONSE_OK))
        chooser.set_select_multiple(True)
        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            filenames = chooser.get_filenames()
            self.player.stop()
            self.update("reset")
            self.player.set_playlist(filenames)

        chooser.destroy()