Re: [Rhythmbox-devel] [RFC] Multiple library locations



Great! Will the libraries appear in separate menu entries also? It would
be great if one could add a separate library for e.g audiobooks, have
that entry appear as a separate item in the menu, and rename it
'Audiobooks'...

If there are separate entries, I believe it solves some of the issues...

Mats

On Wed, 2009-03-25 at 19:01 +0100, Christian Becke wrote:
> Hi all,
> 
> currently, if you use multiple library locations, browser state for
> additional library sources is lost when rhythmbox is restarted.
> I made a patch making additional library sources preserve state across
> restarts[1].
> 
> Until now, additional library sources can only be added by editing the
> gconf key "/apps/rhythmbox/library_locations" using e.g. gconf-editor -
> so I am planing to edit the preferences dialog to allow selection of
> multiple library locations (see attached python demo).
> 
> There are some implementation details that have to be decided upon:
> 
> * If you have configured multiple library locations, and you choose to
> remove one of them, what should happen to the songs from the removed
> location? Should they be removed from the library or should they be
> kept? If they are removed, what about the metadata (play counts,
> ratings, etc.)?
> Currently, if you remove a song from the library (by right-clicking a
> song and selecting "Remove"), the removal time is recorded in RhythmDB
> and metadata is kept for a certain time (configurable via the gconf key
> "/apps/rhythmbox/grace_period"). So if you add the song again to your
> library during grace_time, metadata will still be there. Should this
> apply to songs from a removed library location as well?
> 
> * If you rip a CD using rb, where should the files be saved? Currently,
> they are put in the first library location. Should there be some ui to
> choose where to put them?
> 
> * Should there be drag and drop support, allowing to move files between
> different library sources within rb?
> 
> Please try the patch from [1] and the attached python demo of the new
> preferences dialog I have in mind, and tell me your thoughts.
> 
> 
> Regards,
> 
> Chris
> 
> [1] http://bugzilla.gnome.org/show_bug.cgi?id=523162
> plain text document attachment (library_prefs_example.py)
> #!/usr/bin/python
> 
> import gobject
> import gtk
> import gtk.glade
> import urlparse
> 
> LIBRARY_PREFS_GLADE = "library-prefs-example.glade"
> 
> COL_LIBRARY_LOCATION = 0
> COL_NEW_FILES_LOCATION = 1
> 
> class UI:
> 
> 	def __init__ (self):
> 		self.gladeXML = gtk.glade.XML (LIBRARY_PREFS_GLADE)
> 		self.gladeXML.signal_autoconnect (self)
> 		locations_tv = self.gladeXML.get_widget ("library_locations_treeview")
> 		self.library_locations_filechooserdialog = self.gladeXML.get_widget ("library_locations_filechooserdialog")
> 		self.remove_library_location_messagedialog = self.gladeXML.get_widget ("remove_library_location_messagedialog")
> 		self.keep_metadata_checkbutton = self.gladeXML.get_widget ("keep_metadata_checkbutton")
> 		
> 		self.locations = gtk.ListStore (gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
> 		self.locations_tree_selection = locations_tv.get_selection ()
> 		self.locations_tree_selection.set_mode (gtk.SELECTION_MULTIPLE)
> 		locations_tv.set_model (self.locations)
> 		locations_column = gtk.TreeViewColumn ("Library Locations")
> 		locations_column.set_expand (True)
> 		locations_tv.append_column (locations_column)
> 		cr = gtk.CellRendererText ()
> 		locations_column.pack_start (cr, True)
> 		locations_column.add_attribute (cr, 'text', COL_LIBRARY_LOCATION)
> 
> 		new_files_column = gtk.TreeViewColumn ("Put new files here")
> 		new_files_column.set_expand (False)
> 		locations_tv.append_column (new_files_column)
> 		cr = gtk.CellRendererToggle ()
> 		cr.set_radio (True)
> 		cr.connect ("toggled", self.on_new_files_location_toggled)
> 		new_files_column.pack_start (cr, True)
> 		new_files_column.add_attribute (cr, 'active', COL_NEW_FILES_LOCATION)
> 
> 	def run (self):
> 		gtk.main ()
> 
> 	def run_library_locations_filechooserdialog (self):
> 		locations = []
> 		resp = self.library_locations_filechooserdialog.run ()
> 		if resp == gtk.RESPONSE_OK:
> 			locations = self.library_locations_filechooserdialog.get_uris ()
> 		self.library_locations_filechooserdialog.hide ()
> 		return locations
> 
> 	def new_files_location_toggled_foreach_func (self, model, path, it, toggled):
> 		if int (path[0]) == int (toggled):
> 			model.set_value (it, COL_NEW_FILES_LOCATION, True)
> 		else:
> 			model.set_value (it, COL_NEW_FILES_LOCATION, False)
> 		return False
> 
> 	def on_new_files_location_toggled (self, cr, path):
> 		self.locations.foreach (self.new_files_location_toggled_foreach_func, path)
> 		return False
> 
> 	def on_quit (self, *args, **kwargs):
> 		gtk.main_quit ()
> 	
> 	def location_is_valid_foreach_func (self, model, path, it, data):
> 		loc = urlparse.urlsplit (model.get_value (it, COL_LIBRARY_LOCATION))
> 		new = data[0]
> 		if new.scheme == loc.scheme:
> 			if new.path == loc.path or new.path.startswith (loc.path) or loc.path.startswith (new.path):
> 				data[1] = False
> 				return True
> 	
> 	def location_is_valid (self, location):
> 		data = [urlparse.urlsplit (location), True]
> 		self.locations.foreach (self.location_is_valid_foreach_func, data)
> 		return data[1]
> 		
> 	def update_new_files_location_foreach_func (self, model, path, it, found):
> 		if model.get_value (it, COL_NEW_FILES_LOCATION):
> 			found[0] = it
> 			return False
> 	
> 	def update_new_files_location (self):
> 		found = [None]
> 		self.locations.foreach (self.update_new_files_location_foreach_func, found)
> 		if not found[0]:
> 			gobject.idle_add (self.on_new_files_location_toggled, None, 0)
> 		return False
> 
> 	def on_button_add_clicked (self, button):
> 		locations = self.run_library_locations_filechooserdialog ()
> 		location_added = False
> 		invalid_locations = []
> 		for loc in locations:
> 			if self.location_is_valid (loc):
> 				self.locations.append ([loc, False])
> 				location_added = True
> 			else:
> 				invalid_locations.append (loc)
> 
> 		if location_added:
> 			gobject.idle_add (self.update_new_files_location)
> 
> 		if invalid_locations:
> 			dlg = gtk.MessageDialog (parent=self.gladeXML.get_widget ("window1"),
> 					flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
> 					type=gtk.MESSAGE_ERROR,
> 					buttons=gtk.BUTTONS_OK,
> 					message_format="Some location(s) could not be added")
> 			dlg.format_secondary_text ("The following location(s) could not be added to the list of library locations:\n\n"
> 					"%s\n\n"
> 					"Possible reasons: either the location itself, "
> 					"one of its subfolders, or one of its parent folders is already added.\n"
> 					"Nested folders can not be added as library locations." % 
> 					"\n".join (invalid_locations))
> 			dlg.run ()
> 			dlg.destroy ()
> 	
> 	def on_button_remove_clicked (self, button):
> 		resp = self.remove_library_location_messagedialog.run ()
> 		if resp == gtk.RESPONSE_OK:
> 			keep_metadata = self.keep_metadata_checkbutton.get_active ()
> 			if keep_metadata:
> 				print "Would remove songs from library, keeping metadata in rhythmdb."
> 			else:
> 				print "Would remove songs from library, removing metadata from rhythmdb."
> 			(model, pathlist) = self.locations_tree_selection.get_selected_rows ()
> 			pathlist.reverse ()
> 			new_files_location_removed = False
> 			for path in pathlist:
> 				it = model.get_iter (path)
> 				new_files_location_removed = (new_files_location_removed
> 						or model.get_value (it, COL_NEW_FILES_LOCATION))
> 				model.remove (it)
> 			if new_files_location_removed:
> 				gobject.idle_add (self.update_new_files_location)
> 		self.remove_library_location_messagedialog.hide ()
> 
> 
> if __name__ == '__main__':
> 	ui = UI ()
> 	ui.run ()
> _______________________________________________
> rhythmbox-devel mailing list
> rhythmbox-devel gnome org
> http://mail.gnome.org/mailman/listinfo/rhythmbox-devel



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]