Пример #1
0
	def _window_response(self, window, response):
		if response == gtk.RESPONSE_CLOSE:
			self.last_tab = self.prefsnotebook.get_current_page()
			#XXX: These two are probably never triggered
			if self.config.show_lyrics and self.config.lyrics_location != consts.LYRICS_LOCATION_HOME:
				if not os.path.isdir(misc.file_from_utf8(self.config.musicdir[self.config.profile_num])):
					ui.show_msg(self.window, _("To save lyrics to the music file's directory, you must specify a valid music directory."), _("Music Dir Verification"), 'musicdirVerificationError', gtk.BUTTONS_CLOSE)
					# Set music_dir entry focused:
					self.prefsnotebook.set_current_page(0)
					self.direntry.grab_focus()
					return
			if self.config.show_covers and self.config.art_location != consts.ART_LOCATION_HOMECOVERS:
				if not os.path.isdir(misc.file_from_utf8(self.config.musicdir[self.config.profile_num])):
					ui.show_msg(self.window, _("To save artwork to the music file's directory, you must specify a valid music directory."), _("Music Dir Verification"), 'musicdirVerificationError', gtk.BUTTONS_CLOSE)
					# Set music_dir entry focused:
					self.prefsnotebook.set_current_page(0)
					self.direntry.grab_focus()
					return
			if not self.using_mpd_env_vars:
				if self.prev_host != self.config.host[self.config.profile_num] or self.prev_port != self.config.port[self.config.profile_num] or self.prev_password != self.config.password[self.config.profile_num]:
					# Try to connect if mpd connection info has been updated:
					ui.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
					self.reconnect()
			self.settings_save()
			self.populate_profiles_for_menu()
			ui.change_cursor(None)
		window.destroy()
Пример #2
0
	def _window_response(self, window, response):
		if response == gtk.RESPONSE_CLOSE:
			self.last_tab = self.prefsnotebook.get_current_page()
			#XXX: These two are probably never triggered
			if self.config.show_lyrics and self.config.lyrics_location != consts.LYRICS_LOCATION_HOME:
				if not os.path.isdir(misc.file_from_utf8(self.config.musicdir[self.config.profile_num])):
					ui.show_msg(self.window, _("To save lyrics to the music file's directory, you must specify a valid music directory."), _("Music Dir Verification"), 'musicdirVerificationError', gtk.BUTTONS_CLOSE)
					# Set music_dir entry focused:
					self.prefsnotebook.set_current_page(0)
					self.direntry.grab_focus()
					return
			if self.config.show_covers and self.config.art_location != consts.ART_LOCATION_HOMECOVERS:
				if not os.path.isdir(misc.file_from_utf8(self.config.musicdir[self.config.profile_num])):
					ui.show_msg(self.window, _("To save artwork to the music file's directory, you must specify a valid music directory."), _("Music Dir Verification"), 'musicdirVerificationError', gtk.BUTTONS_CLOSE)
					# Set music_dir entry focused:
					self.prefsnotebook.set_current_page(0)
					self.direntry.grab_focus()
					return
			if not self.using_mpd_env_vars:
				if self.prev_host != self.config.host[self.config.profile_num] or self.prev_port != self.config.port[self.config.profile_num] or self.prev_password != self.config.password[self.config.profile_num]:
					# Try to connect if mpd connection info has been updated:
					ui.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
					self.reconnect()
			self.settings_save()
			self.populate_profiles_for_menu()
			ui.change_cursor(None)
		window.destroy()
Пример #3
0
    def download_progress(self, dest_filename_curr, i):
        # This populates Main.imagelist for the remote image window
        if os.path.exists(dest_filename_curr):
            pix = gtk.gdk.pixbuf_new_from_file(dest_filename_curr)
            pix = pix.scale_simple(148, 148, gtk.gdk.INTERP_HYPER)
            pix = self.artwork_apply_composite_case(pix, 148, 148)
            pix = img.pixbuf_add_border(pix)
            if self.stop_art_update:
                del pix
                return False # don't continue to next image
            self.imagelist_append([i+1, pix])
            del pix
            self.remotefilelist_append(dest_filename_curr)
            if i == 0:
                self.allow_art_search()

        ui.change_cursor(None) # XXX indented twice more?

        return True # continue to next image
Пример #4
0
    def download_progress(self, dest_filename_curr, i):
        # This populates Main.imagelist for the remote image window
        if os.path.exists(dest_filename_curr):
            pix = gtk.gdk.pixbuf_new_from_file(dest_filename_curr)
            pix = pix.scale_simple(148, 148, gtk.gdk.INTERP_HYPER)
            pix = self.artwork_apply_composite_case(pix, 148, 148)
            pix = img.pixbuf_add_border(pix)
            if self.stop_art_update:
                del pix
                return False # don't continue to next image
            self.imagelist_append([i+1, pix])
            del pix
            self.remotefilelist_append(dest_filename_curr)
            if i == 0:
                self.allow_art_search()

        ui.change_cursor(None) # XXX indented twice more?

        return True # continue to next image
Пример #5
0
	def artwork_download_img_to_file(self, artist, album, dest_filename, all_images=False):
		# Returns False if no images found
		if not artist and not album:
			self.downloading_image = False
			return False
		self.downloading_image = True
		# Amazon currently doesn't support utf8 and suggests latin1 encoding instead:
		artist = urllib.quote(artist.encode('latin1', 'replace'))
		album = urllib.quote(album.encode('latin1', 'replace'))

		# Try searching urls from most specific (artist, title) to least specific (artist only)
		urls = [AMAZON_URI % (AMAZON_KEY, artist) + "&Title=" + album,
			AMAZON_URI % (AMAZON_KEY, artist) + "&Keywords=" + album,
			AMAZON_URI % (AMAZON_KEY, artist)]

		for url in urls:
			request = urllib2.Request(url)
			opener = urllib2.build_opener()
			try:
				body = opener.open(request).read()
				xml = ElementTree.fromstring(body)
				largeimgs = xml.getiterator(AMAZON_NS + "LargeImage")
			except:
				largeimgs = None

			if largeimgs:
				break
			elif url == urls[-1]:
				self.downloading_image = False
				return False

		imgs = misc.iunique(url.text for img in largeimgs for url in img.getiterator(AMAZON_NS + "URL"))
		imglist = list(imgs)

		if not all_images:
			urllib.urlretrieve(imglist[0], dest_filename)
			self.downloading_image = False
			return True
		else:
			try:
				imgfound = False
				for i in range(len(imglist)):
					dest_filename_curr = dest_filename.replace("<imagenum>", str(i+1))
					urllib.urlretrieve(imglist[i], dest_filename_curr)
					# This populates Main.imagelist for the remote image window
					if os.path.exists(dest_filename_curr):
						pix = gtk.gdk.pixbuf_new_from_file(dest_filename_curr)
						pix = pix.scale_simple(148, 148, gtk.gdk.INTERP_HYPER)
						pix = self.artwork_apply_composite_case(pix, 148, 148)
						pix = img.pixbuf_add_border(pix)
						if self.stop_art_update:
							del pix
							self.downloading_image = False
							return imgfound
						self.imagelist_append([i+1, pix])
						del pix
						imgfound = True
						self.remotefilelist_append(dest_filename_curr)
						if i == 0:
							self.allow_art_search()
					ui.change_cursor(None)
			except:
				pass
			self.downloading_image = False
			return imgfound
Пример #6
0
    def current_update(self, prevstatus_playlist, new_playlist_length):
        if self.connected():

            if self.sonata_loaded():
                playlistposition = self.current.get_visible_rect()[1]

            self.current.freeze_child_notify()

            if not self.current_update_skip:

                if not self.filterbox_visible:
                    self.current.set_model(None)

                if prevstatus_playlist:
                    changed_songs = mpdh.call(self.client, "plchanges", prevstatus_playlist)
                else:
                    changed_songs = mpdh.call(self.client, "plchanges", 0)
                    self.current_songs = []

                newlen = int(new_playlist_length)
                currlen = len(self.currentdata)

                for track in changed_songs:
                    pos = int(mpdh.get(track, "pos"))

                    items = []
                    for part in self.columnformat:
                        items += [self.parse_formatting(part, track, True)]

                    if pos < currlen:
                        # Update attributes for item:
                        i = self.currentdata.get_iter((pos,))
                        trackid = int(mpdh.get(track, "id"))
                        if trackid != self.currentdata.get_value(i, 0):
                            self.currentdata.set_value(i, 0, trackid)
                        for index in range(len(items)):
                            if items[index] != self.currentdata.get_value(i, index + 1):
                                self.currentdata.set_value(i, index + 1, items[index])
                        self.current_songs[pos] = track
                    else:
                        # Add new item:
                        self.currentdata.append([int(mpdh.get(track, "id"))] + items)
                        self.current_songs.append(track)

                if newlen == 0:
                    self.currentdata.clear()
                    self.current_songs = []
                else:
                    # Remove excess songs:
                    for i in range(currlen - newlen):
                        it = self.currentdata.get_iter((currlen - 1 - i,))
                        self.currentdata.remove(it)
                    self.current_songs = self.current_songs[:newlen]

                if not self.filterbox_visible:
                    self.current.set_model(self.currentdata)

            self.current_update_skip = False

            # Update statusbar time:
            self.total_time = 0
            for track in self.current_songs:
                try:
                    self.total_time = self.total_time + int(mpdh.get(track, "time"))
                except:
                    pass

            if "pos" in self.songinfo():
                currsong = int(mpdh.get(self.songinfo(), "pos"))
                self.boldrow(currsong)
                self.prev_boldrow = currsong

            if self.filterbox_visible:
                # Refresh filtered results:
                self.prevtodo = (
                    "RETAIN_POS_AND_SEL"
                )  # Hacky, but this ensures we retain the self.current position/selection
                self.plpos = playlistposition
                self.searchfilter_feed_loop(self.filterpattern)
            elif self.sonata_loaded():
                self.playlist_retain_view(self.current, playlistposition)
                self.current.thaw_child_notify()

            self.header_update_column_indicators()
            self.update_statusbar()
            ui.change_cursor(None)
Пример #7
0
 def on_link_leave(self, _widget, _event):
     ui.change_cursor(None)
Пример #8
0
 def on_link_enter(self, widget, _event):
     if widget.get_children()[0].get_use_markup():
         ui.change_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
Пример #9
0
    def current_update(self, prevstatus_playlist, new_playlist_length):
        if self.connected():

            if self.sonata_loaded():
                playlistposition = self.current.get_visible_rect()[1]

            self.current.freeze_child_notify()

            if not self.current_update_skip:

                if not self.filterbox_visible:
                    self.current.set_model(None)

                if prevstatus_playlist:
                    changed_songs = mpdh.call(self.client, 'plchanges',
                                              prevstatus_playlist)
                else:
                    changed_songs = mpdh.call(self.client, 'plchanges', 0)
                    self.current_songs = []

                newlen = int(new_playlist_length)
                currlen = len(self.currentdata)

                for track in changed_songs:
                    pos = int(mpdh.get(track, 'pos'))

                    items = []
                    for part in self.columnformat:
                        items += [self.parse_formatting(part, track, True)]

                    if pos < currlen:
                        # Update attributes for item:
                        i = self.currentdata.get_iter((pos, ))
                        trackid = int(mpdh.get(track, 'id'))
                        if trackid != self.currentdata.get_value(i, 0):
                            self.currentdata.set_value(i, 0, trackid)
                        for index in range(len(items)):
                            if items[index] != self.currentdata.get_value(
                                    i, index + 1):
                                self.currentdata.set_value(
                                    i, index + 1, items[index])
                        self.current_songs[pos] = track
                    else:
                        # Add new item:
                        self.currentdata.append([int(mpdh.get(track, 'id'))] +
                                                items)
                        self.current_songs.append(track)

                if newlen == 0:
                    self.currentdata.clear()
                    self.current_songs = []
                else:
                    # Remove excess songs:
                    for i in range(currlen - newlen):
                        it = self.currentdata.get_iter((currlen - 1 - i, ))
                        self.currentdata.remove(it)
                    self.current_songs = self.current_songs[:newlen]

                if not self.filterbox_visible:
                    self.current.set_model(self.currentdata)

            self.current_update_skip = False

            # Update statusbar time:
            self.total_time = 0
            for track in self.current_songs:
                try:
                    self.total_time = self.total_time + int(
                        mpdh.get(track, 'time'))
                except:
                    pass

            if 'pos' in self.songinfo():
                currsong = int(mpdh.get(self.songinfo(), 'pos'))
                self.boldrow(currsong)
                self.prev_boldrow = currsong

            if self.filterbox_visible:
                # Refresh filtered results:
                self.prevtodo = "RETAIN_POS_AND_SEL"  # Hacky, but this ensures we retain the self.current position/selection
                self.plpos = playlistposition
                self.searchfilter_feed_loop(self.filterpattern)
            elif self.sonata_loaded():
                self.playlist_retain_view(self.current, playlistposition)
                self.current.thaw_child_notify()

            self.header_update_column_indicators()
            self.update_statusbar()
            ui.change_cursor(None)
Пример #10
0
    def artwork_download_img_to_file(self,
                                     artist,
                                     album,
                                     dest_filename,
                                     all_images=False):
        # Returns False if no images found
        if not artist and not album:
            self.downloading_image = False
            return False
        self.downloading_image = True
        # Amazon currently doesn't support utf8 and suggests latin1 encoding instead:
        artist = urllib.quote(artist.encode('latin1', 'replace'))
        album = urllib.quote(album.encode('latin1', 'replace'))

        # Try searching urls from most specific (artist, title) to least specific (artist only)
        urls = [
            AMAZON_URI % (AMAZON_KEY, artist) + "&Title=" + album,
            AMAZON_URI % (AMAZON_KEY, artist) + "&Keywords=" + album,
            AMAZON_URI % (AMAZON_KEY, artist)
        ]

        for url in urls:
            request = urllib2.Request(url)
            opener = urllib2.build_opener()
            try:
                body = opener.open(request).read()
                xml = ElementTree.fromstring(body)
                largeimgs = xml.getiterator(AMAZON_NS + "LargeImage")
            except:
                largeimgs = None

            if largeimgs:
                break
            elif url == urls[-1]:
                self.downloading_image = False
                return False

        imgs = misc.iunique(url.text for img in largeimgs
                            for url in img.getiterator(AMAZON_NS + "URL"))
        # Prevent duplicate images in remote art window:
        imglist = list(set(list(imgs)))

        if not all_images:
            urllib.urlretrieve(imglist[0], dest_filename)
            self.downloading_image = False
            return True
        else:
            try:
                imgfound = False
                for i, image in enumerate(imglist):
                    dest_filename_curr = dest_filename.replace(
                        "<imagenum>", str(i + 1))
                    urllib.urlretrieve(image, dest_filename_curr)
                    # This populates Main.imagelist for the remote image window
                    if os.path.exists(dest_filename_curr):
                        pix = gtk.gdk.pixbuf_new_from_file(dest_filename_curr)
                        pix = pix.scale_simple(148, 148, gtk.gdk.INTERP_HYPER)
                        pix = self.artwork_apply_composite_case(pix, 148, 148)
                        pix = img.pixbuf_add_border(pix)
                        if self.stop_art_update:
                            del pix
                            self.downloading_image = False
                            return imgfound
                        self.imagelist_append([i + 1, pix])
                        del pix
                        imgfound = True
                        self.remotefilelist_append(dest_filename_curr)
                        if i == 0:
                            self.allow_art_search()
                    ui.change_cursor(None)
            except:
                pass
            self.downloading_image = False
            return imgfound
Пример #11
0
 def on_link_leave(self, _widget, _event):
     ui.change_cursor(None)
Пример #12
0
 def on_link_enter(self, widget, _event):
     if widget.get_children()[0].get_use_markup():
         ui.change_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
Пример #13
0
    def on_tags_edit(self, files, temp_mpdpaths, music_dir):
        """Display the editing dialog"""
        # Try loading module
        global tagpy
        if tagpy is None:
            try:
                import tagpy
            except ImportError:
                ui.show_msg(
                    self.window,
                    _("Taglib and/or tagpy not found, tag editing support disabled."
                      ),
                    _("Edit Tags"),
                    'editTagsError',
                    gtk.BUTTONS_CLOSE,
                    response_cb=ui.dialog_destroy)
                ui.change_cursor(None)
                return
            # Set default tag encoding to utf8.. fixes some reported bugs.
            import tagpy.id3v2 as id3v2
            id3v2.FrameFactory.instance().setDefaultTextEncoding(
                tagpy.StringType.UTF8)

        # Make sure tagpy is at least 0.91
        if hasattr(tagpy.Tag.title, '__call__'):
            ui.show_msg(
                self.window,
                _("Tagpy version < 0.91. Please upgrade to a newer version, tag editing support disabled."
                  ),
                _("Edit Tags"),
                'editTagsError',
                gtk.BUTTONS_CLOSE,
                response_cb=ui.dialog_destroy)
            ui.change_cursor(None)
            return

        if not os.path.isdir(misc.file_from_utf8(music_dir)):
            ui.show_msg(
                self.window,
                _("The path") + " " + music_dir + " " +
                _("does not exist. Please specify a valid music directory in preferences."
                  ),
                _("Edit Tags"),
                'editTagsError',
                gtk.BUTTONS_CLOSE,
                response_cb=ui.dialog_destroy)
            ui.change_cursor(None)
            return

# XXX file list was created here

        if len(files) == 0:
            ui.change_cursor(None)
            return

        # Initialize:
        self.tagnum = -1

        tags = [{
            'title': '',
            'artist': '',
            'album': '',
            'year': '',
            'track': '',
            'genre': '',
            'comment': '',
            'title-changed': False,
            'artist-changed': False,
            'album-changed': False,
            'year-changed': False,
            'track-changed': False,
            'genre-changed': False,
            'comment-changed': False,
            'fullpath': misc.file_from_utf8(filename),
            'mpdpath': path
        } for filename, path in zip(files, temp_mpdpaths)]

        if not os.path.exists(tags[0]['fullpath']):
            ui.change_cursor(None)
            ui.show_msg(
                self.window,
                _("File ") + "\"" + tags[0]['fullpath'] + "\"" +
                _(" not found. Please specify a valid music directory in preferences."
                  ),
                _("Edit Tags"),
                'editTagsError',
                gtk.BUTTONS_CLOSE,
                response_cb=ui.dialog_destroy)
            return
        if not self.tags_next_tag(tags):
            ui.change_cursor(None)
            ui.show_msg(self.window,
                        _("No music files with editable tags found."),
                        _("Edit Tags"),
                        'editTagsError',
                        gtk.BUTTONS_CLOSE,
                        response_cb=ui.dialog_destroy)
            return
        editwindow = ui.dialog(parent=self.window,
                               flags=gtk.DIALOG_MODAL,
                               role='editTags',
                               resizable=False,
                               separator=False)
        editwindow.set_size_request(375, -1)
        table = gtk.Table(9, 2, False)
        table.set_row_spacings(2)
        self.filelabel = ui.label(select=True, wrap=True)
        filehbox = gtk.HBox()
        sonataicon = ui.image(stock='sonata', stocksize=gtk.ICON_SIZE_DND, x=1)
        expandbutton = ui.button(" ")
        self.set_expandbutton_state(expandbutton)
        expandvbox = gtk.VBox()
        expandvbox.pack_start(ui.label(), True, True)
        expandvbox.pack_start(expandbutton, False, False)
        expandvbox.pack_start(ui.label(), True, True)
        expandbutton.connect('clicked', self.toggle_path)
        blanklabel = ui.label(w=5, h=12)
        filehbox.pack_start(sonataicon, False, False, 2)
        filehbox.pack_start(self.filelabel, True, True, 2)
        filehbox.pack_start(expandvbox, False, False, 2)
        filehbox.pack_start(blanklabel, False, False, 2)

        titlelabel, titleentry, titlebutton, titlehbox = self._create_label_entry_button_hbox(
            _("Title"))
        artistlabel, artistentry, artistbutton, artisthbox = self._create_label_entry_button_hbox(
            _("Artist"))
        albumlabel, albumentry, albumbutton, albumhbox = self._create_label_entry_button_hbox(
            _("Album"))
        yearlabel, yearentry, yearbutton, yearhbox = self._create_label_entry_button_hbox(
            _("Year"))
        yearentry.set_size_request(50, -1)
        tracklabel, trackentry, trackbutton, trackhbox = self._create_label_entry_button_hbox(
            "  " + _("Track"), True)
        trackentry.set_size_request(50, -1)
        yearandtrackhbox = gtk.HBox()
        yearandtrackhbox.pack_start(yearhbox, True, True, 0)
        yearandtrackhbox.pack_start(trackhbox, True, True, 0)

        yearentry.connect("insert_text", self.tags_win_entry_constraint, True)
        trackentry.connect("insert_text", self.tags_win_entry_constraint,
                           False)

        genrelabel = ui.label(text=_("Genre") + ":", x=1)
        genrecombo = ui.comboentry(items=self.tags_win_genres(), wrap=2)
        genreentry = genrecombo.get_child()
        genrehbox = gtk.HBox()
        genrebutton = ui.button()
        genrebuttonvbox = self.tags_win_create_apply_all_button(
            genrebutton, genreentry)
        genrehbox.pack_start(genrelabel, False, False, 2)
        genrehbox.pack_start(genrecombo, True, True, 2)
        genrehbox.pack_start(genrebuttonvbox, False, False, 2)

        commentlabel, commententry, commentbutton, commenthbox = self._create_label_entry_button_hbox(
            _("Comment"))

        ui.set_widths_equal([
            titlelabel, artistlabel, albumlabel, yearlabel, genrelabel,
            commentlabel, sonataicon
        ])
        genrecombo.set_size_request(-1, titleentry.size_request()[1])
        tablewidgets = [
            ui.label(), filehbox,
            ui.label(), titlehbox, artisthbox, albumhbox, yearandtrackhbox,
            genrehbox, commenthbox,
            ui.label()
        ]
        for i, widget in enumerate(tablewidgets):
            table.attach(widget, 1, 2, i + 1, i + 2, gtk.FILL | gtk.EXPAND,
                         gtk.FILL | gtk.EXPAND, 2, 0)
        editwindow.vbox.pack_start(table)
        saveall_button = None
        if len(files) > 1:
            # Only show save all button if more than one song being edited.
            saveall_button = ui.button(text=_("Save _All"))
            editwindow.action_area.pack_start(saveall_button)
        editwindow.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)
        editwindow.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)
        editwindow.connect('delete_event', self.tags_win_hide, tags)
        entries = [
            titleentry, artistentry, albumentry, yearentry, trackentry,
            genreentry, commententry
        ]
        buttons = [
            titlebutton, artistbutton, albumbutton, yearbutton, trackbutton,
            genrebutton, commentbutton
        ]
        entries_names = [
            "title", "artist", "album", "year", "track", "genre", "comment"
        ]
        editwindow.connect('response', self.tags_win_response, tags, entries,
                           entries_names)
        if saveall_button:
            saveall_button.connect('clicked', self.tags_win_save_all,
                                   editwindow, tags, entries, entries_names)

        for button, name, entry in zip(buttons, entries_names, entries):
            entry.connect('changed', self.tags_win_entry_changed)
            button.connect('clicked', self.tags_win_apply_all, name, tags,
                           entry)

        self.tags_win_update(editwindow, tags, entries, entries_names)
        ui.change_cursor(None)
        self.filelabel.set_size_request(
            editwindow.size_request()[0] - titlelabel.size_request()[0] - 70,
            -1)
        editwindow.show_all()
Пример #14
0
    def current_update(self, prevstatus_playlist, new_playlist_length):
        if self.connected():

            if self.sonata_loaded():
                playlistposition = self.current.get_visible_rect()[1]

            self.current.freeze_child_notify()

            if not self.current_update_skip:

                if not self.filterbox_visible:
                    self.current.set_model(None)

                if prevstatus_playlist:
                    changed_songs = mpdh.call(self.client, 'plchanges', prevstatus_playlist)
                else:
                    changed_songs = mpdh.call(self.client, 'plchanges', 0)
                    self.current_songs = []

                newlen = int(new_playlist_length)
                currlen = len(self.currentdata)

                for track in changed_songs:
                    pos = mpdh.get(track, 'pos', 0, True)

                    items = [formatting.parse(part, track,
                                  True)
                         for part in self.columnformat]
                    if self.aimp_headers:
                        items += [""]

                    if pos < currlen:
                        # Update attributes for item:
                        i = self.currentdata.get_iter((pos, ))
                        trackid = mpdh.get(track, 'id',
                                    0, True)
                        if trackid != self.currentdata.get_value(i, 0):
                            self.currentdata.set_value(i, 0, trackid)
                        for index in range(len(items)):
                            if items[index] != self.currentdata.get_value(i, index + 1):
                                self.currentdata.set_value(i, index + 1, items[index])
                        if pos < len(self.current_songs):
                            self.current_songs[pos] = track
                        elif pos == len(self.current_songs):
                            self.current_songs.append(track)
                        else:
                            raise Exception
                    else:
                        # Add new item:
                        self.currentdata.append([mpdh.get(track, 'id', 0, True)] + items)
                        self.current_songs.append(track)

                if newlen == 0:
                    self.currentdata.clear()
                    self.current_songs = []
                else:
                    # Remove excess songs:
                    for i in range(currlen-newlen):
                        it = self.currentdata.get_iter((currlen-1-i,))
                        self.currentdata.remove(it)
                    self.current_songs = self.current_songs[:newlen]

                if not self.filterbox_visible:
                    self.current.set_model(self.currentdata)

            self.current_update_skip = False

            # Update AIMP headers
            if len(self.current_songs) > 0:
                self.currentdata.set_value(self.currentdata.get_iter(0), len(self.columnformat)+1, aimpheaders.by_filename(mpdh.get(self.current_songs[0], 'file')))
                for i in range(1, len(self.current_songs)):
                    this_header = aimpheaders.by_filename(mpdh.get(self.current_songs[i], 'file'))
                    prev_header = aimpheaders.by_filename(mpdh.get(self.current_songs[i-1], 'file'))
                    if this_header != prev_header:
                        self.currentdata.set_value(self.currentdata.get_iter(i), len(self.columnformat)+1, this_header)
                    else:
                        self.currentdata.set_value(self.currentdata.get_iter(i), len(self.columnformat)+1, '')

            # Update statusbar time:
            self.total_time = 0
            for track in self.current_songs:
                try:
                    self.total_time = self.total_time + mpdh.get(track, 'time', 0, True)
                except:
                    pass

            if 'pos' in self.songinfo():
                currsong = mpdh.get(self.songinfo(), 'pos', 0,
                            True)
                self.boldrow(currsong)
                self.prev_boldrow = currsong

            if self.filterbox_visible:
                # Refresh filtered results:
                self.prevtodo = "RETAIN_POS_AND_SEL" # Hacky, but this ensures we retain the self.current position/selection
                self.plpos = playlistposition
                self.searchfilter_feed_loop(self.filterpattern)
            elif self.sonata_loaded():
                self.playlist_retain_view(self.current, playlistposition)
                self.current.thaw_child_notify()

            self.header_update_column_indicators()
            self.update_statusbar()
            ui.change_cursor(None)
Пример #15
0
    def on_tags_edit(self, files, temp_mpdpaths, music_dir):
        """Display the editing dialog"""
        # Try loading module
        global tagpy
        if tagpy is None:
            try:
                import tagpy
            except ImportError:
                ui.show_msg(self.window, _("Taglib and/or tagpy not found, tag editing support disabled."), _("Edit Tags"), 'editTagsError', gtk.BUTTONS_CLOSE, response_cb=ui.dialog_destroy)
                ui.change_cursor(None)
                return
            # Set default tag encoding to utf8.. fixes some reported bugs.
            import tagpy.id3v2 as id3v2
            id3v2.FrameFactory.instance().setDefaultTextEncoding(tagpy.StringType.UTF8)

        # Make sure tagpy is at least 0.91
        if hasattr(tagpy.Tag.title, '__call__'):
            ui.show_msg(self.window, _("Tagpy version < 0.91. Please upgrade to a newer version, tag editing support disabled."), _("Edit Tags"), 'editTagsError', gtk.BUTTONS_CLOSE, response_cb=ui.dialog_destroy)
            ui.change_cursor(None)
            return

        if not os.path.isdir(misc.file_from_utf8(music_dir)):
            ui.show_msg(self.window, _("The path %s does not exist. Please specify a valid music directory in preferences.") % music_dir, _("Edit Tags"), 'editTagsError', gtk.BUTTONS_CLOSE, response_cb=ui.dialog_destroy)
            ui.change_cursor(None)
            return

                # XXX file list was created here

        if len(files) == 0:
            ui.change_cursor(None)
            return

        # Initialize:
        self.tagnum = -1

        tags = [{'title':'', 'artist':'', 'album':'', 'year':'', 'track':'',
             'genre':'', 'comment':'', 'title-changed':False,
             'artist-changed':False, 'album-changed':False,
             'year-changed':False, 'track-changed':False,
             'genre-changed':False, 'comment-changed':False,
             'fullpath':misc.file_from_utf8(filename),
             'mpdpath':path}
            for filename, path in zip(files, temp_mpdpaths)]

        if not os.path.exists(tags[0]['fullpath']):
            ui.change_cursor(None)
            ui.show_msg(self.window, _("File '%s' not found. Please specify a valid music directory in preferences.") % tags[0]['fullpath'], _("Edit Tags"), 'editTagsError', gtk.BUTTONS_CLOSE, response_cb=ui.dialog_destroy)
            return
        if not self.tags_next_tag(tags):
            ui.change_cursor(None)
            ui.show_msg(self.window, _("No music files with editable tags found."), _("Edit Tags"), 'editTagsError', gtk.BUTTONS_CLOSE, response_cb=ui.dialog_destroy)
            return
        editwindow = ui.dialog(parent=self.window, flags=gtk.DIALOG_MODAL, role='editTags', resizable=False, separator=False)
        editwindow.set_size_request(375, -1)
        table = gtk.Table(9, 2, False)
        table.set_row_spacings(2)
        self.filelabel = ui.label(select=True, wrap=True)
        filehbox = gtk.HBox()
        sonataicon = ui.image(stock='sonata', stocksize=gtk.ICON_SIZE_DND, x=1)
        expandbutton = ui.button(" ")
        self.set_expandbutton_state(expandbutton)
        expandvbox = gtk.VBox()
        expandvbox.pack_start(ui.label(), True, True)
        expandvbox.pack_start(expandbutton, False, False)
        expandvbox.pack_start(ui.label(), True, True)
        expandbutton.connect('clicked', self.toggle_path)
        blanklabel = ui.label(w=5, h=12)
        filehbox.pack_start(sonataicon, False, False, 2)
        filehbox.pack_start(self.filelabel, True, True, 2)
        filehbox.pack_start(expandvbox, False, False, 2)
        filehbox.pack_start(blanklabel, False, False, 2)

        titlelabel, titleentry, titlebutton, titlehbox = self._create_label_entry_button_hbox(_("Title:"))
        artistlabel, artistentry, artistbutton, artisthbox = self._create_label_entry_button_hbox(_("Artist:"))
        albumlabel, albumentry, albumbutton, albumhbox = self._create_label_entry_button_hbox(_("Album:"))
        yearlabel, yearentry, yearbutton, yearhbox = self._create_label_entry_button_hbox(_("Year:"))
        yearentry.set_size_request(50,-1)
        tracklabel, trackentry, trackbutton, trackhbox = self._create_label_entry_button_hbox("  " + _("Track:"), True)
        trackentry.set_size_request(50,-1)
        yearandtrackhbox = gtk.HBox()
        yearandtrackhbox.pack_start(yearhbox, True, True, 0)
        yearandtrackhbox.pack_start(trackhbox, True, True, 0)

        yearentry.connect("insert_text", self.tags_win_entry_constraint, True)
        trackentry.connect("insert_text", self.tags_win_entry_constraint, False)

        genrelabel = ui.label(text=_("Genre:"), x=1)
        genrecombo = ui.comboentry(items=self.tags_win_genres(), wrap=2)
        genreentry = genrecombo.get_child()
        genrehbox = gtk.HBox()
        genrebutton = ui.button()
        genrebuttonvbox = self.tags_win_create_apply_all_button(genrebutton,
                                                                genreentry)
        genrehbox.pack_start(genrelabel, False, False, 2)
        genrehbox.pack_start(genrecombo, True, True, 2)
        genrehbox.pack_start(genrebuttonvbox, False, False, 2)

        commentlabel, commententry, commentbutton, commenthbox = self._create_label_entry_button_hbox(_("Comment:"))

        ui.set_widths_equal([titlelabel, artistlabel, albumlabel, yearlabel, genrelabel, commentlabel, sonataicon])
        genrecombo.set_size_request(-1, titleentry.size_request()[1])
        tablewidgets = [ui.label(), filehbox, ui.label(), titlehbox, artisthbox, albumhbox, yearandtrackhbox, genrehbox, commenthbox, ui.label()]
        for i, widget in enumerate(tablewidgets):
            table.attach(widget, 1, 2, i+1, i+2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 2, 0)
        editwindow.vbox.pack_start(table)
        saveall_button = None
        if len(files) > 1:
            # Only show save all button if more than one song being edited.
            saveall_button = ui.button(text=_("Save _All"))
            editwindow.action_area.pack_start(saveall_button)
        editwindow.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)
        editwindow.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)
        editwindow.connect('delete_event', self.tags_win_hide, tags)
        entries = [titleentry, artistentry, albumentry, yearentry, trackentry, genreentry, commententry]
        buttons = [titlebutton, artistbutton, albumbutton, yearbutton, trackbutton, genrebutton, commentbutton]
        entries_names = ["title", "artist", "album", "year", "track", "genre", "comment"]
        editwindow.connect('response', self.tags_win_response, tags, entries, entries_names)
        if saveall_button:
            saveall_button.connect('clicked', self.tags_win_save_all, editwindow, tags, entries, entries_names)

        for button, name, entry in zip(buttons, entries_names, entries):
            entry.connect('changed', self.tags_win_entry_changed)
            button.connect('clicked', self.tags_win_apply_all, name, tags, entry)

        self.tags_win_update(editwindow, tags, entries, entries_names)
        ui.change_cursor(None)
        self.filelabel.set_size_request(editwindow.size_request()[0] - titlelabel.size_request()[0] - 70, -1)
        editwindow.show_all()