Пример #1
0
class Playlist:
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Playlist'}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.config = {}
        rpt = self.userconf.config['Playlist']['repeat']
        self.config['repeat'] = bool(int(rpt))
        shf = self.userconf.config['Playlist']['shuffle']
        self.config['shuffle'] = bool(int(shf))
        shm = self.userconf.config['Playlist']['shuffle_mode']
        self.config['shuffle_mode'] = shm

        self.lastfm = LastFm()
        self.playlists_mgmnt = Playlists()

        self.playlist_content = {}
        self.playlist_identifier = 0
        self.playlist_current = None
        self.current_playlist_id = 0
        self.user_playlists = {}
        self.last_user_playlist = None

        self.similar_artists = []
        self.is_in_similar_thread = False

        # Create the Playlist view
        def launch_playlist(wdg):
            self.widgets = wdg[1]

            self.playlist_label = self.widgets.get_object('label_playlist')
            self.playlist_repeat = self.widgets.get_object('tool-repeat')
            self.playlist_shuffle = self.widgets.get_object('tool-shuffle')
            self.playlist_clean = self.widgets.get_object('tool-clean')
            self.playlist_combo = self.widgets.get_object('combo-playlist')
            self.playlist_save = self.widgets.get_object('tool-saveplaylist')
            self.playlist_lyrics = self.widgets.get_object('tool-lyrics')

            self.playlist_tree = self.widgets.get_object('treeview_playlist')
            self.playlist_tree.set_headers_visible(False)
            self.playlist_tree.props.reorderable = True
            self.playlist_tree.connect('key_press_event', self.key_pressed)
            self.playlist_tree.connect('row_activated', self.row_activated)

            self.liststore = ListStore(str, str, str, str, int)
            self.playlist_tree.set_model(self.liststore)

            renderer_pix = CellRendererPixbuf()
            column_pixbuf = TreeViewColumn('1', renderer_pix, icon_name=0)
            column_pixbuf.set_fixed_width(18)
            self.playlist_tree.append_column(column_pixbuf)

            renderer_text = CellRendererText()
            column_text = TreeViewColumn('2', renderer_text, markup=1)
            column_text.props.expand = True
            column_text.props.max_width = 192
            self.playlist_tree.append_column(column_text)

            column_text = TreeViewColumn('3', renderer_text, markup=2)
            column_text.set_fixed_width(40)
            self.playlist_tree.append_column(column_text)

            self.repeat_btn = self.widgets.get_object('tool-repeat')
            if self.config['repeat']:
                self.repeat_btn.set_active(True)
            self.repeat_btn.connect('clicked', self.toggle, 'repeat')

            self.shuffle_btn = self.widgets.get_object('tool-shuffle')
            if self.config['shuffle']:
                self.shuffle_btn.set_active(True)
            self.shuffle_btn.connect('clicked', self.toggle, 'shuffle')

            def clean_wdg(widget):
                # Clean playlist
                self.clean()

                # Show popover
                if self.current_playlist_id > 3:
                    self.clean_btn.set_sensitive(True)
                    self.clean_pop.show_all()

            self.clean_btn = self.widgets.get_object('tool-clean')
            self.clean_btn.connect('clicked', clean_wdg)
            self.clean_pop = Popover.new(self.clean_btn)
            self.clean_pop.set_size_request(100, 30)

            gtkpla = join(self.functions.datadir, 'glade', 'plist-del-pop.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-playlist')
            lbl = win.get_object('label')
            lbl.set_text(_('Do you also want to remove the playlist?'))
            btn = win.get_object('del-btn')
            btn.set_label(_('Delete'))
            btn.connect('clicked', self.delete_playlist)
            self.clean_pop.add(hbox)

            # Populate combobox
            self.combolist = ListStore(int, str)

            self.combobox = self.widgets.get_object('combobox')
            self.combobox.set_model(self.combolist)
            self.combobox.set_popup_fixed_width(False)
            self.combobox.props.expand = False

            renderer_text = CellRendererText()
            renderer_text.props.ellipsize = EllipsizeMode.END
            self.combobox.pack_start(renderer_text, True)
            self.combobox.set_entry_text_column(1)
            self.combobox.add_attribute(renderer_text, 'text', 1)

            self.combolist.append([0, _('Current')])
            self.combolist.append([1, _('Top 50 songs')])
            self.combolist.append([2, _('Top 10 albums')])

            playlists = self.playlists_mgmnt.get_playlists()

            if len(playlists) > 0:
                self.combolist.append([3, ''])
                item_id = 3

                playlists.sort(key=lambda it: it[1])
                for item in playlists:
                    item_id += 1
                    self.combolist.append([item_id, item])
                    self.user_playlists[item_id] = item
                    self.last_user_playlist = item_id

            def combo_sep(model, iter):
                if model[iter][0] == 3:
                    return True
            self.combobox.set_row_separator_func(combo_sep)

            def on_combo_changed(widget):
                path = widget.get_active()
                item_id = self.combolist[path][0]

                # First, clean the playlist
                self.clean(None)

                # Second, populate the playlist
                if item_id > 0:
                    self.populate(item_id)

                # Then, update playlist identifier
                self.current_playlist_id = item_id

                # Show delete/remove button if the playlist is from the user
                if item_id > 3:
                    self.clean_btn.set_sensitive(True)

            self.combobox.set_active(0)
            self.combobox.connect('changed', on_combo_changed)
            
            self.tool_save = self.widgets.get_object('tool-saveplaylist')
            self.tool_save.connect('clicked', self.save_playlist)
            self.save_pop = Popover.new(self.tool_save)
            self.save_pop.set_size_request(100, 30)

            gtkpla = join(self.functions.datadir, 'glade', 'plist-add-pop.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-playlist')
            self.save_pop.add(hbox)

            self.save_entry = win.get_object('save-entry')
            self.save_entry.connect('key_press_event', self.save_playlist_key)
            self.save_btn = win.get_object('save-btn')
            self.save_btn.connect('clicked', self.save_playlist_button)
            self.save_btn.set_label(_('Save'))

            self.clean_btn.set_sensitive(False)
            self.tool_save.set_sensitive(False)

        # Acquire the songs tree
        def acquire_tree(st):
            self.songs_tree = st

        self.extensions.connect('OnBluemindoStarted', launch_playlist)
        self.extensions.connect('OnSongsTreeCreated', acquire_tree)
        self.extensions.connect('OnSongQueued', self.on_new_song_queued)
        self.extensions.connect('OnAlbumQueued', self.on_new_album_queued)
        self.extensions.connect('AskPreviousSong', self.ask_previous_song)
        self.extensions.connect('AskNextSong', self.ask_next_song)
        self.extensions.connect('HasStartedSong', self.song_started)


    def toggle(self, widget, action):
        if action == 'repeat' and self.config['repeat']:
            self.config['repeat'] = False
            self.repeat_btn.set_active(False)
            self.userconf.update_key('Playlist', 'repeat', str(int(False)))
        elif action == 'repeat' and not self.config['repeat']:
            self.config['repeat'] = True
            self.repeat_btn.set_active(True)
            self.userconf.update_key('Playlist', 'repeat', str(int(True)))
        elif action == 'shuffle' and self.config['shuffle']:
            self.config['shuffle'] = False
            self.shuffle_btn.set_active(False)
            self.userconf.update_key('Playlist', 'shuffle', str(int(False)))
        elif action == 'shuffle' and not self.config['shuffle']:
            self.config['shuffle'] = True
            self.shuffle_btn.set_active(True)
            self.userconf.update_key('Playlist', 'shuffle', str(int(True)))

    def row_activated(self, widget, path, column):
        item_iter = self.liststore.get_iter(path)

        # Get the founded element.
        item_identifier = self.liststore.get_value(item_iter, 4)
        current_item = self.playlist_content[item_identifier]

        # The element is a song.
        if self.playlist_content[item_identifier].kind == 'song':
            self.playlist_current = [item_iter, item_identifier, None]
            self.extensions.load_event('OnPlayNewSong', current_item)
        # The element is an album.
        else:
            self.extensions.load_event('OnAbortPlayback')
            sng = self.playlist_content[item_identifier].tracks[0]
            self.playlist_current = [item_iter, item_identifier, 0]
            self.extensions.load_event('OnPlayNewSong', sng)

    def key_pressed(self, widget, eventkey):
        if eventkey.get_keyval()[1] == KEY_Delete:
            # Delete an item from the playlist
            selection = self.playlist_tree.get_selection()
            selected = selection.get_selected_rows()
            liststore = selected[0]
            listpath = selected[1]

            if len(listpath) > 0:
                selpath = listpath[0]
                playlist_identifier = liststore[selpath][4]

                # Are we removing the currently playing item?
                if self.playlist_current is not None:
                    item_iter, item_path, item_in_album = self.playlist_current
                    if selpath == TreePath.new_from_string(str(item_path)):
                        self.playlist_current = None

                # Removal
                del self.playlist_content[playlist_identifier]
                del liststore[selpath]

    def clean(self, data=None):
        self.playlist_content = {}
        self.playlist_identifier = 0
        self.playlist_current = None
        self.liststore.clear()

        # Update GUI
        self.clean_btn.set_sensitive(False)
        self.tool_save.set_sensitive(False)

    def populate(self, playlist_id):
        if playlist_id in (1, 2):
            # Automatic playlists based on listening stats
            if playlist_id == 1:
                tb = 'stats_songs'
                lm = 50
            elif playlist_id == 2:
                tb = 'stats_albums'
                lm = 10

            result = []
            txt = ('select * from %s order by tracks desc limit %u' % (tb, lm))

            sql = SQLite()
            cur = sql.execute(txt)
            for sg in cur:
                result.append(sg)
            sql.close()

            for item in result:
                if playlist_id == 1:
                    sng = Song(filename=item[0])
                    if hasattr(sng, 'title'):
                        self.on_new_song_queued(sng)
                elif playlist_id == 2:
                    album_name = item[0]
                    for it in self.songs_tree:
                        if album_name in self.songs_tree[it]:
                            self.on_new_album_queued(Album(it, album_name,
                                                           self.songs_tree))
                            break
        elif playlist_id > 3:
            # User-created playlists
            user_plist = self.user_playlists[playlist_id]
            plist = self.playlists_mgmnt.load_playlist(user_plist)

            for item in plist:
                sng = Song(filename=item)
                if hasattr(sng, 'title'):
                    self.on_new_song_queued(sng)

    def delete_playlist(self, widget):
        if self.current_playlist_id > 3:
            user_plist = self.user_playlists[self.current_playlist_id]
            self.playlists_mgmnt.delete_playlist(user_plist)

            # Delete the playlist from the list
            del self.user_playlists[self.current_playlist_id]

            cblid = 0
            for item in self.combolist:
                if item[0] == self.current_playlist_id:
                    del self.combolist[cblid]
                    break
                cblid += 1

            # Move back to "Current" playlist
            self.combobox.set_active(0)

    def save_playlist_key(self, widget, eventkey):
        if eventkey.get_keyval()[1] == KEY_Return:
            self.save_playlist_button(None)

    def save_playlist_button(self, widget):
        user_entry = self.save_entry.get_text()
        user_entry = user_entry.replace('\\', '-')
        user_entry = user_entry.replace('/', '-')
        user_entry = user_entry.replace('*', '-')
        user_entry = user_entry.replace('|', '-')

        if len(user_entry) > 0:
            rtn_value = self.playlists_mgmnt.create_new_playlist(user_entry)

            if rtn_value:
                self.save_pop.hide()

                # Add playlist to GUI
                if self.last_user_playlist is None:
                    self.combolist.append([3, ''])
                    self.last_user_playlist = 3

                self.last_user_playlist += 1
                self.combolist.append([self.last_user_playlist, user_entry])
                self.user_playlists[self.last_user_playlist] = user_entry

                # Write the playlist
                self.write_playlist(user_entry)

                # Select the new playlist
                self.combobox.set_active(self.last_user_playlist)

    def save_playlist(self, widget):
        if self.current_playlist_id < 3:
            # Create a new playlist
            self.save_entry.set_text('')
            self.save_pop.show_all()
        elif self.current_playlist_id > 3:
            # Update an existing playlist
            user_plist = self.user_playlists[self.current_playlist_id]
            self.write_playlist(user_plist)

    def write_playlist(self, user_plist):
        plist_content = []
        for item in self.liststore:
            item_id = item[4]
            plist_content.append(self.playlist_content[item_id])

        self.playlists_mgmnt.write_playlist(user_plist, plist_content)

    def on_new_song_queued(self, song_info):
        title = song_info.title
        artist = song_info.artist
        album = song_info.album
        filename = song_info.filename
        length = self.functions.human_length(song_info.length)

        self.liststore.append(('audio-x-generic-symbolic', '<b>' +
                               self.functions.view_encode(title, 99) +
                               '</b>\n' + self.functions.view_encode(artist),
                               '<span foreground="grey">' +
                               length + '</span>',
                               filename, self.playlist_identifier))

        self.playlist_content[self.playlist_identifier] = song_info
        self.playlist_identifier += 1

        # Update GUI
        self.clean_btn.set_sensitive(True)
        self.tool_save.set_sensitive(True)

    def on_new_album_queued(self, album_info):
        artist = album_info.artist
        album = album_info.name
        songs_count = str(len(album_info.tracks)) + ' ♫'

        self.liststore.append(('media-optical-symbolic', '<b>' +
                               self.functions.view_encode(album, 99) +
                               '</b>\n' + self.functions.view_encode(artist),
                               '<span foreground="grey">' +
                               songs_count + '</span>', '[album]',
                               self.playlist_identifier))

        self.playlist_content[self.playlist_identifier] = album_info
        self.playlist_identifier += 1

        # Update GUI
        self.clean_btn.set_sensitive(True)
        self.tool_save.set_sensitive(True)

    def ask_next_song(self, current_song):
        self.ask_for_a_song(True, current_song)

    def ask_previous_song(self, current_song):
        self.ask_for_a_song(False, current_song)

    def ask_for_a_song(self, next=True, current_song=None):
        def walk_in_playlist(item_iter, next=True):
            base_item_iter = item_iter
            if item_iter is None:
                # Find first song.
                item_iter = self.liststore.get_iter_first()
            elif next:
                # Find next song.
                path = self.liststore.get_path(self.playlist_current[0])
                path_int = int(path.to_string())
                max_id = len(self.playlist_content) - 1

                if (path_int + 1 <= max_id): # There is a song to launch!
                    item_iter = self.liststore.get_iter(path_int + 1)
                else: # There is no song to launch!
                    if not self.config['repeat']:
                        self.extensions.load_event('OnAbortPlayback')
                        return
                    else:
                        item_iter = self.liststore.get_iter_first()
            elif not next:
                # Find previous song.
                path = self.liststore.get_path(self.playlist_current[0])
                path_int = int(path.to_string())
                max_id = len(self.playlist_content) - 1

                if (path_int -1 >= 0): # There is a song to launch.
                    item_iter = self.liststore.get_iter(path_int - 1)
                else: # There is no song to launch!
                    if not self.config['repeat']:
                        self.extensions.load_event('OnAbortPlayback')
                        return
                    else:
                        item_iter = self.liststore.get_iter_from_string(str(max_id))

            # Get the founded element.
            item_identifier = self.liststore.get_value(item_iter, 4)
            current_item = self.playlist_content[item_identifier]

            def launch_founded_item(item_identifier, item_iter, current_item):
                # The element is a song.
                if self.playlist_content[item_identifier].kind == 'song':
                    self.playlist_current = [item_iter, item_identifier, None]
                    self.extensions.load_event('OnPlayNewSong', current_item)
                # The element is an album.
                else:
                    self.extensions.load_event('OnAbortPlayback')
                    sng = self.playlist_content[item_identifier].tracks[0]
                    sng.rg_mode_guess = 'album'
                    self.playlist_current = [item_iter, item_identifier, 0]
                    self.extensions.load_event('OnPlayNewSong', sng)

            # Are we currently listening from an album?
            if base_item_iter is not None:
                kind = self.playlist_content[self.playlist_current[1]].kind

                if kind == 'album':
                    base_item_identifier = self.liststore.get_value(base_item_iter, 4)
                    tracks = self.playlist_content[self.playlist_current[1]].tracks
                    max_sng = len(tracks) - 1

                    if next:
                        if self.playlist_current[2] < max_sng:
                            item_in_album = self.playlist_current[2] + 1
                        else:
                            return launch_founded_item(item_identifier, item_iter, current_item)
                    elif not next:
                        if self.playlist_current[2] - 1 > -1:
                            item_in_album = self.playlist_current[2] - 1
                        else:
                            return launch_founded_item(item_identifier, item_iter, current_item)

                    sng = self.playlist_content[base_item_identifier].tracks[item_in_album]
                    sng.rg_mode_guess = 'album'
                    self.playlist_current = [base_item_iter, base_item_identifier, item_in_album]
                    self.extensions.load_event('OnPlayNewSong', sng)
                    return

            launch_founded_item(item_identifier, item_iter, current_item)

        if len(self.playlist_content) == 0:
            # Playlist is empty.
            if not self.config['shuffle']:
                # Shuffle disabled: abort playback.
                self.extensions.load_event('OnAbortPlayback')
            else:
                # Shuffle enabled.
                if self.config['shuffle_mode'] == 'random':
                    # Random mode: seek for shuffle song.
                    self.extensions.load_event('AskShuffleSong')
                elif self.config['shuffle_mode'] == 'similar':
                    # Similar mode: seek for a similar song.
                    if len(self.similar_artists) == 0:
                        # No similar song founded: seek for any one.
                        self.extensions.load_event('AskShuffleSong')
                        return

                    # Choose one song in the list of similar artists
                    index = randrange(len(self.similar_artists))
                    artist = self.similar_artists[index]

                    mdb = MusicDatabase(None)
                    songs_list = mdb.load_from_artist(artist)
                    if len(songs_list) > 1:
                        index = randrange(len(songs_list))
                        song = songs_list[index]

                        sng = Song(filename=song[8])
                        print ('[SIMILAR] Playing a song from ' + sng.artist)
                        self.extensions.load_event('OnPlayNewSong', sng)
                    else:
                        self.extensions.load_event('AskShuffleSong')
        else:
            # Playlist is not empty, walk in it!
            if self.playlist_current is None:
                # Currently no current item in playlist, choose the first one!
                walk_in_playlist(None)
            else:
                # The current playling song is in the playlist!
                if next:
                    walk_in_playlist(self.playlist_current[0])
                else:
                    walk_in_playlist(self.playlist_current[0], False)


    def song_started(self, song):
        # First, try to download a few similar artists names
        if self.config['shuffle_mode'] == 'similar':
            def download_similars():
                threads_enter()
                art = self.lastfm.get_similar_artists(song.artist)

                self.similar_artists = []
                mdb = MusicDatabase(None)

                for artist in art:
                    if mdb.artist_exists(artist):
                        self.similar_artists.append(artist)

                self.is_in_similar_thread = False
                threads_leave()

            if not self.is_in_similar_thread:
                self.is_in_similar_thread = True
                thread = Thread(group=None, target=download_similars,
                                name='similars', args=())
                thread.start()

        # Second, update statistics for this song
        song.increment_statistics()
        alb = Album(song.artist, song.album, self.songs_tree)
        alb.increment_statistics()

        # Then, highlight currently playing song/album if it's in playlist
        if self.playlist_current is not None:
            # Currently playing item is in the playlist
            item_iter, item_path, item_in_album = self.playlist_current

            # Remove marker of all items
            for item in self.liststore:
                current_label = item[1]
                if current_label[:2] == '◎ ':
                    item[1] = current_label[2:]

            # Add marker on one item
            current_label = self.liststore[item_iter][1]
            if current_label[:2] != '◎ ':
                self.liststore[item_iter][1] = '◎ ' + current_label
Пример #2
0
class Explorer:
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Explorer'}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.songs_tree = {}
        self.albums = {}

        # Create the Albums view
        def launch_explorer(wdg):
            self.widgets = wdg

            self.aview = AlbumsView(self.widgets, self.extensions)
            self.search = Search(self.widgets, self.aview)
            self.filter = Filter(self.widgets, self.aview)

            # Populate the view
            self.populate()

            # Connect to signals
            def repopulate(wdg):
                self.extensions.load_event('OnAbortPlayback')
                self.populate(True)

            self.widgets[0][3].connect('clicked', repopulate)

        self.extensions.connect('OnBluemindoStarted', launch_explorer)
        self.extensions.connect('AskShuffleSong', self.shuffle_song_asked)

    def populate(self, force_scan=False):
        threads_enter()

        # Do we have a working directory or not?
        if self.userconf.config['Explorer']['folder'] == '':
            fcdialog = FileChooserDialog(
                title=_('Open your music directory'),
                action=FileChooserAction.SELECT_FOLDER,
                buttons=(_('Select'), ResponseType.OK))

            fcdialog.set_transient_for(self.widgets[0][11])
            response = fcdialog.run()
            if response == ResponseType.OK:
                foldername = fcdialog.get_filename()
                self.userconf.update_key('Explorer', 'folder', foldername)
                force_scan = True
            else:
                print("Bluemindo can't work without opening a music " +
                      "directory. Exiting…")
                exit(0)

            fcdialog.destroy()

        # Call database
        musicdb = MusicDatabase(self.userconf.config['Explorer']['folder'])

        # Do we scan for new files?
        if (bool(int(self.userconf.config['Explorer']['scan_at_startup']))
                or force_scan):

            def do_scan():
                # Freeze user interface
                gldfile = join(self.functions.datadir, 'glade', 'loading.ui')
                win = gtk_builder()
                win.set_translation_domain('bluemindo')
                win.add_from_file(gldfile)
                box_content = win.get_object('box1')

                # Create an interface to help the user waiting for the job
                bluemindo = join(self.functions.datadir, 'image',
                                 'bluemindo.png')
                img = win.get_object('image')
                cover_px = Pixbuf.new_from_file(bluemindo)
                idle_add(img.set_from_pixbuf, cover_px)

                idle_add(
                    win.get_object('label').set_markup,
                    '<span size="x-large"><b>' +
                    _('Reloading music database.') + '</b></span>')

                idle_add(self.widgets[0][2].set_sensitive, False)
                idle_add(self.widgets[0][3].set_sensitive, False)
                idle_add(self.widgets[0][5].set_sensitive, False)
                idle_add(self.widgets[0][6].set_sensitive, False)
                idle_add(self.widgets[0][7].set_sensitive, False)
                idle_add(self.widgets[0][8].set_sensitive, False)

                idle_add(self.widgets[1].get_object('box1').add, box_content)

                lbl = win.get_object('label_info')
                idle_add(lbl.set_text,
                         _('Starting… Prepares to search for new files.'))

                # Update GUI
                box_content.show_all()
                self.widgets[1].get_object('box2').hide()

                # Do the scanning
                pb = win.get_object('progressbar')
                musicdb.scan(lbl, pb)

                # Show original GUI
                idle_add(self.widgets[0][2].set_sensitive, True)
                idle_add(self.widgets[0][3].set_sensitive, True)
                idle_add(box_content.hide)
                idle_add(self.widgets[1].get_object('box2').show_all)
                idle_add(self.create_view)

            thread = Thread(group=None,
                            target=do_scan,
                            name='scanning',
                            args=())
            thread.start()
        else:
            self.create_view()

        threads_leave()

    def create_view(self):
        # Call database
        musicdb = MusicDatabase(self.userconf.config['Explorer']['folder'])
        self.database = musicdb.load()

        self.albums_tree = []
        album_names = []
        album_iter = {}

        # Activate player buttons
        self.widgets[0][5].set_sensitive(True)
        self.widgets[0][6].set_sensitive(True)
        self.widgets[0][7].set_sensitive(True)
        self.widgets[0][8].set_sensitive(True)

        # Create the tree artists→albums→songs
        def unique(seq, keepstr=True):
            """This function ensures there are only unique values."""
            t = type(seq)
            if t in (str, str):
                t = (list, ''.join)[bool(keepstr)]
            seen = []
            return t(c for c in seq if not (c in seen or seen.append(c)))

        # Create the songs tree
        songs_tree = {}
        artists = []
        albums = []
        albums_dl = []

        for result in self.database:
            artists.append(result[1])
            albums.append((result[1], result[2]))

        artists = unique(artists)
        albums = unique(albums)

        for a in artists:
            songs_tree[a] = {}

        for a in albums:
            songs_tree[a[0]][a[1]] = []

        # Add songs
        for result in self.database:
            songs_tree[result[1]][result[2]].append(result)

        # Sort songs
        for artist in songs_tree.values():
            for album in artist.values():
                album.sort(key=lambda student: student[3])

        self.songs_tree = songs_tree

        i = 0
        for art in self.songs_tree:
            for alb in self.songs_tree[art]:
                album_names.append(alb)
                self.albums_tree.append({'album': alb, 'artist': art})
                i = i + 1

        # Sort everything
        self.albums_tree.sort(key=lambda item: item['album'].lower())
        self.albums_tree.sort(key=lambda item: item['artist'].lower())

        # Send the music tree to all extensions
        self.extensions.load_event('OnSongsTreeCreated', self.songs_tree)

        # Launch explorer GUI
        self.search.generate_autocompletion(artists, albums, self.songs_tree)
        self.aview.populate_albums(self.albums_tree, self.albums,
                                   self.songs_tree, self.search)
        self.filter.launch(self.albums_tree, self.songs_tree, self.aview)

    def shuffle_song_asked(self):
        if len(self.database) > 1:
            index = randrange(len(self.database))
            song_inf = self.database[index]

            song = Song(filename=song_inf[8])
            self.extensions.load_event('OnPlayNewSong', song)
Пример #3
0
class Functions(object):
    ref = None
    ref2 = None

    def __new__(cls, *args, **kws):
        # Singleton
        if cls.ref is None:
            cls.ref = object.__new__(cls)
        return cls.ref

    def __init__(self):
        if Functions.ref2 is None:
            Functions.ref2 = 42

            self.userconf = ConfigLoader()

            # Just set the data and the locale dir
            if isdir('../data') and isfile('../locale/bluemindo.pot'):
                self.datadir = '../data'
                self.localedir = '../locale'
            else:
                self.datadir = '/usr/share/bluemindo'
                self.localedir = '/usr/share/locale'

    def get_hash(self, str1, str2):
        """Just return the hash for given strings"""
        md5 = md5_new()
        md5.update(str1.encode('utf-8'))
        md5.update(str2.encode('utf-8'))

        return str(md5.hexdigest())

    def view_encode(self, string, limit=25):
        if (len(string)) > limit:
            string = string[:limit] + '…'

        string = markup_escape_text(string)
        return string

    def unescape(string):
        """Unescape an escaped string with markup_escape_text."""
        _str = xml_unescape(string, {'&apos;': "'", '&quot;': '"'})

        return _str

    def human_length(self, length):
        """Return the length in a human-readable way"""
        lg0 = int(length / 60)
        lg1 = int(length % 60)

        if lg0 >= 0 and lg0 < 10:
            lg0 = '0' + str(lg0)

        if lg1 >= 0 and lg1 < 10:
            lg1 = '0' + str(lg1)

        lg = str(lg0) + ':' + str(lg1)
        return lg

    def clear_html(self, text, only_bold=False):
        """Return the text without html"""
        if text.startswith('<b>') and text.endswith('</b>'):
            text = text[3:-4]

        if not only_bold:
            if text.startswith('<span size="small">'):
                text = text[19:-7]

        return text

    def open_bluemindo(self, window):
        """Handle the Bluemindo's window open and change width,
        height and position on the screen."""
        width = int(self.userconf.config['Window']['width'])
        height = int(self.userconf.config['Window']['height'])
        window.resize(width, height)

        x = int(self.userconf.config['Window']['x'])
        y = int(self.userconf.config['Window']['y'])
        window.move(x, y)

    def close_bluemindo(self, window, quit=True):
        """This function is called when the Bluemindo's main window is
        closed."""
        # Backup window width, height and position
        if window is not None and window.get_properties('visible')[0]:
            width = window.get_size()[0]
            height = window.get_size()[1]
            x = window.get_position()[0]
            y = window.get_position()[1]

            self.userconf.update_key('Window', 'width', str(width))
            self.userconf.update_key('Window', 'height', str(height))
            self.userconf.update_key('Window', 'x', str(x))
            self.userconf.update_key('Window', 'y', str(y))

        # Delete the socket file and quit GTK
        if quit:
            SOCKET_NAME = '/tmp/bluemindo'
            if exists(SOCKET_NAME):
                remove(SOCKET_NAME)

            pid_filename = join(self.datadir, 'pid')
            if isfile(pid_filename):
                remove(pid_filename)

            current_playing = join(self.datadir, 'current-playing')
            if isfile(current_playing):
                remove(current_playing)

            print('The dolphin has plunge!')
            idle_add(gtk_main_quit)
        # Hide window
        else:
            if window.get_properties('visible')[0]:
                window.hide()