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()
def _update_song(self, songinfo): artistlabel = self.info_labels['artist'] tracklabel = self.info_labels['track'] albumlabel = self.info_labels['album'] filelabel = self.info_labels['file'] for name in ['title', 'date', 'genre']: label = self.info_labels[name] label.set_text(mpdh.get(songinfo, name)) tracklabel.set_text(mpdh.get(songinfo, 'track', '', False)) artistlabel.set_markup(misc.link_markup(misc.escape_html( mpdh.get(songinfo, 'artist')), False, False, self.linkcolor)) albumlabel.set_markup(misc.link_markup(misc.escape_html( mpdh.get(songinfo, 'album')), False, False, self.linkcolor)) path = misc.file_from_utf8(os.path.join( self.config.musicdir[self.config.profile_num], mpdh.get(songinfo, 'file'))) if os.path.exists(path): filelabel.set_text(os.path.join( self.config.musicdir[self.config.profile_num], mpdh.get(songinfo, 'file'))) self._editlabel.set_markup(misc.link_markup(_("edit tags"), True, True, self.linkcolor)) else: filelabel.set_text(mpdh.get(songinfo, 'file')) self._editlabel.set_text("")
def _update_song(self, songinfo): artistlabel = self.info_labels['artist'] tracklabel = self.info_labels['track'] albumlabel = self.info_labels['album'] filelabel = self.info_labels['file'] for name in ['title', 'date', 'genre']: label = self.info_labels[name] label.set_text(mpdh.get(songinfo, name)) tracklabel.set_text(mpdh.get(songinfo, 'track', '', False)) artistlabel.set_markup( misc.link_markup(misc.escape_html(mpdh.get(songinfo, 'artist')), False, False, self.linkcolor)) albumlabel.set_markup( misc.link_markup(misc.escape_html(mpdh.get(songinfo, 'album')), False, False, self.linkcolor)) path = misc.file_from_utf8( os.path.join(self.config.musicdir[self.config.profile_num], mpdh.get(songinfo, 'file'))) if os.path.exists(path): filelabel.set_text( os.path.join(self.config.musicdir[self.config.profile_num], mpdh.get(songinfo, 'file'))) self._editlabel.set_markup( misc.link_markup(_('edit tags'), True, True, self.linkcolor)) else: filelabel.set_text(mpdh.get(songinfo, 'file')) self._editlabel.set_text('')
def target_lyrics_filename(self, artist, title, song_dir, force_location=None): # FIXME Why did we have this condition here: if self.conn: if force_location is not None: lyrics_loc = force_location else: lyrics_loc = self.config.lyrics_location # Note: *_ALT searching is for compatibility with other mpd clients (like ncmpcpp): if lyrics_loc == consts.LYRICS_LOCATION_HOME: targetfile = os.path.expanduser("~/.lyrics/" + artist + "-" + title + ".txt") elif lyrics_loc == consts.LYRICS_LOCATION_PATH: targetfile = self.config.musicdir[ self.config. profile_num] + song_dir + "/" + artist + "-" + title + ".txt" elif lyrics_loc == consts.LYRICS_LOCATION_HOME_ALT: targetfile = os.path.expanduser("~/.lyrics/" + artist + " - " + title + ".txt") elif lyrics_loc == consts.LYRICS_LOCATION_PATH_ALT: targetfile = self.config.musicdir[ self.config. profile_num] + song_dir + "/" + artist + " - " + title + ".txt" targetfile = misc.file_exists_insensitive(targetfile) return misc.file_from_utf8(targetfile)
def artwork_get_misc_img_in_path(self, songdir): dir = misc.file_from_utf8(os.path.join(self.config.musicdir[self.config.profile_num], songdir)) if os.path.exists(dir): for name in consts.ART_LOCATIONS_MISC: filename = os.path.join(dir, name) if os.path.exists(filename): return filename return False
def artwork_get_misc_img_in_path(self, songdir): path = misc.file_from_utf8(self.config.musicdir[self.config.profile_num] + songdir) if os.path.exists(path): for name in consts.ART_LOCATIONS_MISC: filename = path + "/" + name if os.path.exists(filename): return filename return False
def target_lyrics_filename(self, artist, title, song_dir, force_location=None): # FIXME Why did we have this condition here: if self.conn: if force_location is not None: lyrics_loc = force_location else: lyrics_loc = self.config.lyrics_location if lyrics_loc == consts.LYRICS_LOCATION_HOME: targetfile = os.path.expanduser("~/.lyrics/" + artist + "-" + title + ".txt") elif lyrics_loc == consts.LYRICS_LOCATION_PATH: targetfile = self.config.musicdir[self.config.profile_num] + song_dir + "/" + artist + "-" + title + ".txt" targetfile = misc.file_exists_insensitive(targetfile) return misc.file_from_utf8(targetfile)
def target_lyrics_filename(self, artist, title, song_dir, force_location=None): # FIXME Why did we have this condition here: if self.conn: lyrics_loc = force_location if force_location else self.config.lyrics_location # Note: *_ALT searching is for compatibility with other mpd clients (like ncmpcpp): file_map = { consts.LYRICS_LOCATION_HOME : ("~/.lyrics", "%s-%s.txt"), consts.LYRICS_LOCATION_PATH : (self.config.musicdir[self.config.profile_num], song_dir, "%s-%s.txt"), consts.LYRICS_LOCATION_HOME_ALT : ("~/.lyrics", "%s - %s.txt"), consts.LYRICS_LOCATION_PATH_ALT : (self.config.musicdir[self.config.profile_num], song_dir, "%s - %s.txt"), } return misc.file_from_utf8(misc.file_exists_insensitive( os.path.expanduser( os.path.join(*file_map[lyrics_loc])) % (artist, title)))
def target_lyrics_filename(self, artist, title, song_dir, force_location=None): # FIXME Why did we have this condition here: if self.conn: lyrics_loc = force_location if force_location else self.config.lyrics_location # Note: *_ALT searching is for compatibility with other mpd clients (like ncmpcpp): if lyrics_loc == consts.LYRICS_LOCATION_HOME: targetfile = os.path.expanduser("~/.lyrics/" + artist + "-" + title + ".txt") elif lyrics_loc == consts.LYRICS_LOCATION_PATH: targetfile = self.config.musicdir[self.config.profile_num] + song_dir + "/" + artist + "-" + title + ".txt" elif lyrics_loc == consts.LYRICS_LOCATION_HOME_ALT: targetfile = os.path.expanduser("~/.lyrics/" + artist + " - " + title + ".txt") elif lyrics_loc == consts.LYRICS_LOCATION_PATH_ALT: targetfile = ( self.config.musicdir[self.config.profile_num] + song_dir + "/" + artist + " - " + title + ".txt" ) targetfile = misc.file_exists_insensitive(targetfile) return misc.file_from_utf8(targetfile)
def on_dnd(self, treeview, drag_context, x, y, selection, _info, timestamp): drop_info = treeview.get_dest_row_at_pos(x, y) if selection.data is not None: if not os.path.isdir(misc.file_from_utf8(self.config.musicdir[self.config.profile_num])): return # DND from outside sonata: uri = selection.data.strip() path = urllib.url2pathname(uri) paths = path.rsplit("\n") mpdpaths = [] # Strip off paranthesis so that we can DND entire music dir # if we wish. musicdir = self.config.musicdir[self.config.profile_num][:-1] for i, path in enumerate(paths): paths[i] = path.rstrip("\r") if paths[i].startswith("file://"): paths[i] = paths[i][7:] elif paths[i].startswith("file:"): paths[i] = paths[i][5:] if paths[i].startswith(musicdir): paths[i] = paths[i][len(self.config.musicdir[self.config.profile_num]) :] if len(paths[i]) == 0: paths[i] = "/" listallinfo = mpdh.call(self.client, "listallinfo", paths[i]) for item in listallinfo: if "file" in item: mpdpaths.append(mpdh.get(item, "file")) elif mpdh.mpd_major_version(self.client) >= 0.14: # Add local file, available in mpd 0.14. This currently won't # work because python-mpd does not support unix socket paths, # which is needed for authentication for local files. It's also # therefore untested. if os.path.isdir(misc.file_from_utf8(paths[i])): filenames = misc.get_files_recursively(paths[i]) else: filenames = [paths[i]] for filename in filenames: if os.path.exists(misc.file_from_utf8(filename)): mpdpaths.append("file://" + urllib.quote(filename)) if len(mpdpaths) > 0: # Items found, add to list at drop position: if drop_info: destpath, position = drop_info if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE): songid = destpath[0] else: songid = destpath[0] + 1 else: songid = len(self.currentdata) for mpdpath in mpdpaths: mpdh.call(self.client, "addid", mpdpath, songid) self.iterate_now() return # Otherwise, it's a DND just within the current playlist model = treeview.get_model() _foobar, selected = self.current_selection.get_selected_rows() # calculate all this now before we start moving stuff drag_sources = [] for path in selected: index = path[0] i = model.get_iter(path) songid = self.current_get_songid(i, model) text = model.get_value(i, 1) drag_sources.append([index, i, songid, text]) # Keep track of the moved iters so we can select them afterwards moved_iters = [] # We will manipulate self.current_songs and model to prevent the entire playlist # from refreshing offset = 0 mpdh.call(self.client, "command_list_ok_begin") for source in drag_sources: index, i, songid, text = source if drop_info: destpath, position = drop_info dest = destpath[0] + offset if dest < index: offset = offset + 1 if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE): self.current_songs.insert(dest, self.current_songs[index]) if dest < index + 1: self.current_songs.pop(index + 1) mpdh.call(self.client, "moveid", songid, dest) else: self.current_songs.pop(index) mpdh.call(self.client, "moveid", songid, dest - 1) model.insert(dest, model[index]) moved_iters += [model.get_iter((dest,))] model.remove(i) else: self.current_songs.insert(dest + 1, self.current_songs[index]) if dest < index: self.current_songs.pop(index + 1) mpdh.call(self.client, "moveid", songid, dest + 1) else: self.current_songs.pop(index) mpdh.call(self.client, "moveid", songid, dest) model.insert(dest + 1, model[index]) moved_iters += [model.get_iter((dest + 1,))] model.remove(i) else: # dest = int(self.status['playlistlength']) - 1 dest = len(self.currentdata) - 1 mpdh.call(self.client, "moveid", songid, dest) self.current_songs.insert(dest + 1, self.current_songs[index]) self.current_songs.pop(index) model.insert(dest + 1, model[index]) moved_iters += [model.get_iter((dest + 1,))] model.remove(i) # now fixup for source in drag_sources: if dest < index: # we moved it back, so all indexes inbetween increased by 1 if dest < source[0] < index: source[0] += 1 else: # we moved it ahead, so all indexes inbetween decreased by 1 if index < source[0] < dest: source[0] -= 1 mpdh.call(self.client, "command_list_end") # we are manipulating the model manually for speed, so... self.current_update_skip = True if drag_context.action == gtk.gdk.ACTION_MOVE: drag_context.finish(True, True, timestamp) self.header_hide_all_indicators(self.current, False) self.iterate_now() gobject.idle_add(self.dnd_retain_selection, treeview.get_selection(), moved_iters)
def on_dnd(self, treeview, drag_context, x, y, selection, _info, timestamp): drop_info = treeview.get_dest_row_at_pos(x, y) if selection.data is not None: if not os.path.isdir( misc.file_from_utf8( self.config.musicdir[self.config.profile_num])): return # DND from outside sonata: uri = selection.data.strip() path = urllib.url2pathname(uri) paths = path.rsplit('\n') mpdpaths = [] # Strip off paranthesis so that we can DND entire music dir # if we wish. musicdir = self.config.musicdir[self.config.profile_num][:-1] for i, path in enumerate(paths): paths[i] = path.rstrip('\r') if paths[i].startswith('file://'): paths[i] = paths[i][7:] elif paths[i].startswith('file:'): paths[i] = paths[i][5:] if paths[i].startswith(musicdir): paths[i] = paths[i][ len(self.config.musicdir[self.config.profile_num]):] if len(paths[i]) == 0: paths[i] = "/" listallinfo = mpdh.call(self.client, 'listallinfo', paths[i]) for item in listallinfo: if 'file' in item: mpdpaths.append(mpdh.get(item, 'file')) elif mpdh.mpd_major_version(self.client) >= 0.14: # Add local file, available in mpd 0.14. This currently won't # work because python-mpd does not support unix socket paths, # which is needed for authentication for local files. It's also # therefore untested. if os.path.isdir(misc.file_from_utf8(paths[i])): filenames = misc.get_files_recursively(paths[i]) else: filenames = [paths[i]] for filename in filenames: if os.path.exists(misc.file_from_utf8(filename)): mpdpaths.append("file://" + urllib.quote(filename)) if len(mpdpaths) > 0: # Items found, add to list at drop position: if drop_info: destpath, position = drop_info if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE): songid = destpath[0] else: songid = destpath[0] + 1 else: songid = len(self.currentdata) for mpdpath in mpdpaths: mpdh.call(self.client, 'addid', mpdpath, songid) self.iterate_now() return # Otherwise, it's a DND just within the current playlist model = treeview.get_model() _foobar, selected = self.current_selection.get_selected_rows() # calculate all this now before we start moving stuff drag_sources = [] for path in selected: index = path[0] i = model.get_iter(path) songid = self.current_get_songid(i, model) text = model.get_value(i, 1) drag_sources.append([index, i, songid, text]) # Keep track of the moved iters so we can select them afterwards moved_iters = [] # We will manipulate self.current_songs and model to prevent the entire playlist # from refreshing offset = 0 mpdh.call(self.client, 'command_list_ok_begin') for source in drag_sources: index, i, songid, text = source if drop_info: destpath, position = drop_info dest = destpath[0] + offset if dest < index: offset = offset + 1 if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE): self.current_songs.insert(dest, self.current_songs[index]) if dest < index + 1: self.current_songs.pop(index + 1) mpdh.call(self.client, 'moveid', songid, dest) else: self.current_songs.pop(index) mpdh.call(self.client, 'moveid', songid, dest - 1) model.insert(dest, model[index]) moved_iters += [model.get_iter((dest, ))] model.remove(i) else: self.current_songs.insert(dest + 1, self.current_songs[index]) if dest < index: self.current_songs.pop(index + 1) mpdh.call(self.client, 'moveid', songid, dest + 1) else: self.current_songs.pop(index) mpdh.call(self.client, 'moveid', songid, dest) model.insert(dest + 1, model[index]) moved_iters += [model.get_iter((dest + 1, ))] model.remove(i) else: #dest = int(self.status['playlistlength']) - 1 dest = len(self.currentdata) - 1 mpdh.call(self.client, 'moveid', songid, dest) self.current_songs.insert(dest + 1, self.current_songs[index]) self.current_songs.pop(index) model.insert(dest + 1, model[index]) moved_iters += [model.get_iter((dest + 1, ))] model.remove(i) # now fixup for source in drag_sources: if dest < index: # we moved it back, so all indexes inbetween increased by 1 if dest < source[0] < index: source[0] += 1 else: # we moved it ahead, so all indexes inbetween decreased by 1 if index < source[0] < dest: source[0] -= 1 mpdh.call(self.client, 'command_list_end') # we are manipulating the model manually for speed, so... self.current_update_skip = True if drag_context.action == gtk.gdk.ACTION_MOVE: drag_context.finish(True, True, timestamp) self.header_hide_all_indicators(self.current, False) self.iterate_now() gobject.idle_add(self.dnd_retain_selection, treeview.get_selection(), moved_iters)
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()
def info_update(self, playing_or_paused, newbitrate, songinfo, update_all, blank_window=False, skip_lyrics=False): # update_all = True means that every tag should update. This is # only the case on song and status changes. Otherwise we only # want to update the minimum number of widgets so the user can # do things like select label text. if playing_or_paused: bitratelabel = self.info_labels[self.info_type[_("Bitrate")]] titlelabel = self.info_labels[self.info_type[_("Title")]] artistlabel = self.info_labels[self.info_type[_("Artist")]] albumlabel = self.info_labels[self.info_type[_("Album")]] datelabel = self.info_labels[self.info_type[_("Date")]] genrelabel = self.info_labels[self.info_type[_("Genre")]] tracklabel = self.info_labels[self.info_type[_("Track")]] filelabel = self.info_labels[self.info_type[_("File")]] if not self.last_info_bitrate or self.last_info_bitrate != newbitrate: bitratelabel.set_text(newbitrate) self.last_info_bitrate = newbitrate if update_all: # Use artist/album Wikipedia links? artist_use_link = False if 'artist' in songinfo: artist_use_link = True album_use_link = False if 'album' in songinfo: album_use_link = True titlelabel.set_text(mpdh.get(songinfo, 'title')) if artist_use_link: artistlabel.set_markup(misc.link_markup(misc.escape_html(mpdh.get(songinfo, 'artist')), False, False, self.linkcolor)) else: artistlabel.set_text(mpdh.get(songinfo, 'artist')) if album_use_link: albumlabel.set_markup(misc.link_markup(misc.escape_html(mpdh.get(songinfo, 'album')), False, False, self.linkcolor)) else: albumlabel.set_text(mpdh.get(songinfo, 'album')) datelabel.set_text(mpdh.get(songinfo, 'date')) genrelabel.set_text(mpdh.get(songinfo, 'genre')) if 'track' in songinfo: tracklabel.set_text(mpdh.getnum(songinfo, 'track', '0', False, 0)) else: tracklabel.set_text("") path = misc.file_from_utf8(self.config.musicdir[self.config.profile_num] + os.path.dirname(mpdh.get(songinfo, 'file'))) if os.path.exists(path): filelabel.set_text(self.config.musicdir[self.config.profile_num] + mpdh.get(songinfo, 'file')) self.info_editlabel.set_markup(misc.link_markup(_("edit tags"), True, True, self.linkcolor)) else: filelabel.set_text(mpdh.get(songinfo, 'file')) self.info_editlabel.set_text("") if 'album' in songinfo: # Update album info: artist, tracks = self.album_return_artist_and_tracks() trackinfo = "" album = mpdh.get(songinfo, 'album') year = mpdh.get(songinfo, 'date', None) if album is not None: albuminfo = album + "\n" playtime = 0 if len(tracks) > 0: for track in tracks: playtime += int(mpdh.get(track, 'time', 0)) if 'title' in track: trackinfo = trackinfo + mpdh.getnum(track, 'track', '0', False, 2) + '. ' + mpdh.get(track, 'title') + '\n' else: trackinfo = trackinfo + mpdh.getnum(track, 'track', '0', False, 2) + '. ' + mpdh.get(track, 'file').split('/')[-1] + '\n' if artist is not None: albuminfo += artist + "\n" if year is not None: albuminfo += year + "\n" albuminfo += misc.convert_time(playtime) + "\n" albuminfo += "\n" + trackinfo else: albuminfo = _("Album info not found.") self.albumText.set_markup(misc.escape_html(albuminfo)) else: self.albumText.set_text(_("Album name not set.")) # Update lyrics: if self.config.show_lyrics and not skip_lyrics: global ServiceProxy if ServiceProxy is None: try: from ZSI import ServiceProxy # Make sure we have the right version.. _test = ServiceProxy.ServiceProxy except: ServiceProxy = None if ServiceProxy is None: self.info_searchlabel.set_text("") self.info_show_lyrics(_("ZSI not found, fetching lyrics support disabled."), "", "", True) elif 'artist' in songinfo and 'title' in songinfo: self.get_lyrics_start(mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), os.path.dirname(mpdh.get(songinfo, 'file'))) else: self.info_searchlabel.set_text("") self.info_show_lyrics(_("Artist or song title not set."), "", "", True) else: blank_window = True if blank_window: for label in self.info_labels: label.set_text("") self.info_editlabel.set_text("") if self.config.show_lyrics: self.info_searchlabel.set_text("") self.info_editlyricslabel.set_text("") self.info_show_lyrics("", "", "", True) self.albumText.set_text("") self.last_info_bitrate = ""
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()
def info_update(self, playing_or_paused, newbitrate, songinfo, update_all, blank_window=False, skip_lyrics=False): # update_all = True means that every tag should update. This is # only the case on song and status changes. Otherwise we only # want to update the minimum number of widgets so the user can # do things like select label text. if playing_or_paused: bitratelabel = self.info_labels[self.info_type[_("Bitrate")]] titlelabel = self.info_labels[self.info_type[_("Title")]] artistlabel = self.info_labels[self.info_type[_("Artist")]] albumlabel = self.info_labels[self.info_type[_("Album")]] datelabel = self.info_labels[self.info_type[_("Date")]] genrelabel = self.info_labels[self.info_type[_("Genre")]] tracklabel = self.info_labels[self.info_type[_("Track")]] filelabel = self.info_labels[self.info_type[_("File")]] if not self.last_info_bitrate or self.last_info_bitrate != newbitrate: bitratelabel.set_text(newbitrate) self.last_info_bitrate = newbitrate if update_all: # Use artist/album Wikipedia links? artist_use_link = False if 'artist' in songinfo: artist_use_link = True album_use_link = False if 'album' in songinfo: album_use_link = True titlelabel.set_text(mpdh.get(songinfo, 'title')) if artist_use_link: artistlabel.set_markup( misc.link_markup( misc.escape_html(mpdh.get(songinfo, 'artist')), False, False, self.linkcolor)) else: artistlabel.set_text(mpdh.get(songinfo, 'artist')) if album_use_link: albumlabel.set_markup( misc.link_markup( misc.escape_html(mpdh.get(songinfo, 'album')), False, False, self.linkcolor)) else: albumlabel.set_text(mpdh.get(songinfo, 'album')) datelabel.set_text(mpdh.get(songinfo, 'date')) genrelabel.set_text(mpdh.get(songinfo, 'genre')) if 'track' in songinfo: tracklabel.set_text( mpdh.getnum(songinfo, 'track', '0', False, 0)) else: tracklabel.set_text("") path = misc.file_from_utf8( self.config.musicdir[self.config.profile_num] + os.path.dirname(mpdh.get(songinfo, 'file'))) if os.path.exists(path): filelabel.set_text( self.config.musicdir[self.config.profile_num] + mpdh.get(songinfo, 'file')) self.info_editlabel.set_markup( misc.link_markup(_("edit tags"), True, True, self.linkcolor)) else: filelabel.set_text(mpdh.get(songinfo, 'file')) self.info_editlabel.set_text("") if 'album' in songinfo: # Update album info: artist, tracks = self.album_return_artist_and_tracks() trackinfo = "" album = mpdh.get(songinfo, 'album') year = mpdh.get(songinfo, 'date', None) if album is not None: albuminfo = album + "\n" playtime = 0 if len(tracks) > 0: for track in tracks: playtime += int(mpdh.get(track, 'time', 0)) if 'title' in track: trackinfo = trackinfo + mpdh.getnum( track, 'track', '0', False, 2) + '. ' + mpdh.get(track, 'title') + '\n' else: trackinfo = trackinfo + mpdh.getnum( track, 'track', '0', False, 2) + '. ' + mpdh.get( track, 'file').split('/')[-1] + '\n' if artist is not None: albuminfo += artist + "\n" if year is not None: albuminfo += year + "\n" albuminfo += misc.convert_time(playtime) + "\n" albuminfo += "\n" + trackinfo else: albuminfo = _("Album info not found.") self.albumText.set_markup(misc.escape_html(albuminfo)) else: self.albumText.set_text(_("Album name not set.")) # Update lyrics: if self.config.show_lyrics and not skip_lyrics: global ServiceProxy if ServiceProxy is None: try: from ZSI import ServiceProxy # Make sure we have the right version.. _test = ServiceProxy.ServiceProxy except: ServiceProxy = None if ServiceProxy is None: self.info_searchlabel.set_text("") self.info_show_lyrics( _("ZSI not found, fetching lyrics support disabled." ), "", "", True) elif 'artist' in songinfo and 'title' in songinfo: self.get_lyrics_start( mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), os.path.dirname(mpdh.get(songinfo, 'file'))) else: self.info_searchlabel.set_text("") self.info_show_lyrics( _("Artist or song title not set."), "", "", True) else: blank_window = True if blank_window: for label in self.info_labels: label.set_text("") self.info_editlabel.set_text("") if self.config.show_lyrics: self.info_searchlabel.set_text("") self.info_editlyricslabel.set_text("") self.info_show_lyrics("", "", "", True) self.albumText.set_text("") self.last_info_bitrate = ""