1 #!/usr/bin/env python2.5
4 from mutagen_backend import MutagenBackend
5 from player_backend import MediaPlayer
6 from utils import escape_html
10 # Fields in the tuple!
11 # Shared with browse_panel
20 class MussorgskyEditPanel (hildon.StackableWindow):
23 hildon.StackableWindow.__init__ (self)
24 self.set_border_width (12)
25 self.album_change_handler = -1
26 self.artist_change_handler = -1
27 self.writer = MutagenBackend ()
28 self.player = MediaPlayer ()
30 self.data_loaded = False
31 self.artist_list = None
32 self.albums_list = None
33 self.connect ("delete-event", self.close_function)
35 def close_function (self, widget, event):
36 if (not self.data_loaded):
39 if self.__is_view_dirty ():
43 def update_title (self):
44 self.set_title ("Edit (%d/%d)" % (self.model.get_path (self.current)[0] + 1,
47 def get_current_row (self):
48 if (not self.current):
50 return self.model.get (self.current, 0, 1, 2, 3, 4, 5)
52 def set_model (self, model, current=None):
54 if self.artists_list or self.albums_list:
56 except AttributeError, e:
57 print "**** Set album and artist alternatives before setting a model"
62 self.current = current
64 self.current = self.model.get_iter_first ()
65 self.data_loaded = True
66 self.set_data_in_view (self.get_current_row ())
69 def set_current (self, current):
71 Iterator to current element
73 self.current = current
74 self.set_data_in_view (self.get_current_row ())
78 def set_artist_alternatives (self, alternatives):
79 self.artists_list = alternatives
80 artist_selector = hildon.TouchSelectorEntry (text=True)
81 for a in self.artists_list:
82 artist_selector.append_text (a)
83 self.artist_button.set_selector (artist_selector)
85 def set_album_alternatives (self, alternatives):
86 self.albums_list = alternatives
87 album_selector = hildon.TouchSelectorEntry (text=True)
88 for a in self.albums_list:
89 album_selector.append_text (a)
90 self.album_button.set_selector (album_selector)
93 def press_back_cb (self, widget):
94 if (self.player.is_playing ()):
97 if self.__is_view_dirty ():
98 print "Modified data. Save!"
101 path = self.model.get_path (self.current)
105 new_path = ( path[0] -1, )
106 self.current = self.model.get_iter (new_path)
107 self.set_data_in_view (self.get_current_row ())
110 def press_next_cb (self, widget):
111 if (self.player.is_playing ()):
114 if self.__is_view_dirty ():
115 print "Modified data. Save!"
116 self.save_metadata ()
118 self.current = self.model.iter_next (self.current)
119 if (not self.current):
122 self.set_data_in_view (self.get_current_row ())
126 def save_metadata (self):
127 # Save the data in the online model to show the appropiate data
128 # in the UI while tracker process the update.
130 # 0 - filename -> doesn't change
131 # 1 - "Music" -> doesn't change
132 # 5 - mimetype -> doesn't change
133 if (type (self.model) == gtk.TreeModelFilter):
134 m = self.model.get_model ()
135 c = self.model.convert_iter_to_child_iter (self.current)
141 artist = self.artist_button.get_value ()
142 title = self.title_entry.get_text ()
143 album = self.album_button.get_value ()
144 text = "<b>%s</b>\n<small>%s</small>" % (escape_html (title),
145 escape_html (artist) + " / " + escape_html (album))
146 search_str = artist.lower () + " " + title.lower () + " " + album.lower ()
149 ARTIST_COLUMN, artist,
153 SEARCH_COLUMN, search_str)
154 new_song = self.get_current_row ()
156 self.writer.save_metadata_on_file (new_song[URI_COLUMN],
157 new_song[MIME_COLUMN],
158 self.artist_button.get_value (),
159 self.title_entry.get_text (),
160 self.album_button.get_value ())
162 # This error in case of tracker returning unexistent files.
163 # Uhm.... for instance after removing a memory card we are editing!
165 #dialog = gtk.MessageDialog (self,
166 # gtk.DIALOG_DESTROY_WITH_PARENT,
173 def __is_view_dirty (self):
175 True if the data has been modified in the widgets
177 song = self.get_current_row ()
179 return not (self.filename_data.get_text() == song[URI_COLUMN] and
180 self.artist_button.get_value () == song[ARTIST_COLUMN] and
181 self.title_entry.get_text () == song[TITLE_COLUMN] and
182 self.album_button.get_value () == song[ALBUM_COLUMN] )
185 def __create_view (self):
186 view_vbox = gtk.VBox (homogeneous=False, spacing = 12)
188 filename_row = gtk.HBox ()
189 self.filename_data = gtk.Label ("")
190 filename_row.pack_start (self.filename_data, expand=True)
192 #filename_row.pack_start (play_button, expand=False, fill=False)
193 view_vbox.pack_start (filename_row, expand=False);
195 central_panel = gtk.HBox (spacing=12)
197 table = gtk.Table (3, 2, False)
198 table.set_col_spacings (12)
199 table.set_row_spacings (12)
201 central_panel.pack_start (table, fill=True)
202 view_vbox.pack_start (central_panel, expand=True, fill=True)
205 label_title = gtk.Label ("Title:")
206 table.attach (label_title, 0, 1, 0, 1, 0)
207 self.title_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
208 table.attach (self.title_entry, 1, 2, 0, 1)
211 self.artist_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
212 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
213 self.artist_button.set_title ("Artist: ")
214 # Set data will set the selector
215 table.attach (self.artist_button, 0, 2, 1, 2)
219 self.album_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
220 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
221 self.album_button.set_title ("Album: ")
222 # set_data will set the selector
223 table.attach (self.album_button, 0, 2, 2, 3)
227 self.album_art = gtk.Image ()
228 self.album_art.set_size_request (124, 124)
229 central_panel.pack_start (self.album_art, expand=False, fill=False)
232 button_box = gtk.Toolbar ()
234 play_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON))
235 play_button.connect ("clicked", self.clicked_play)
236 play_button.set_expand (True)
237 button_box.insert (play_button, -1)
239 separator = gtk.SeparatorToolItem ()
240 separator.set_expand (True)
241 button_box.insert (separator, -1)
243 back_img = gtk.Image ()
244 back_img.set_from_icon_name ("general_back", gtk.ICON_SIZE_BUTTON)
245 back_button = gtk.ToolButton (back_img)
246 back_button.connect ("clicked", self.press_back_cb)
247 back_button.set_expand (True)
248 button_box.insert (back_button, -1)
250 next_img = gtk.Image ()
251 next_img.set_from_icon_name ("general_forward", gtk.ICON_SIZE_BUTTON)
252 next_button = gtk.ToolButton (next_img)
253 next_button.connect ("clicked", self.press_next_cb)
254 next_button.set_expand (True)
255 button_box.insert (next_button, -1)
257 self.add_toolbar (button_box)
262 def set_data_in_view (self, song):
264 Place in the screen the song information.
265 Song is a tuple like (filename, 'Music', title, artist, album, mime)
267 assert len (song) == 6
269 self.filename_data.set_markup ("<small>" + song[URI_COLUMN] + "</small>")
270 self.title_entry.set_text (song[TITLE_COLUMN])
273 # Disconnect the value-change signal to avoid extra album art retrievals
274 if (self.album_button.handler_is_connected (self.album_change_handler)):
275 self.album_button.disconnect (self.album_change_handler)
277 if (self.artist_button.handler_is_connected (self.artist_change_handler)):
278 self.artist_button.disconnect (self.artist_change_handler)
280 # Set values in the picker buttons
282 self.artist_button.set_active (self.artists_list.index(song[ARTIST_COLUMN]))
284 print "'%s' not in artist list!?" % (song[ARTIST_COLUMN])
285 self.artist_button.set_value ("")
286 except AttributeError:
287 print "WARNING: Use set_artist_alternatives method to set a list of artists"
290 self.album_button.set_active (self.albums_list.index (song[ALBUM_COLUMN]))
292 print "'%s' is not in the album list!?" % (song[ALBUM_COLUMN])
293 self.album_button.set_value ("")
294 except AttributeError:
295 print "WARNING: Use set_album_alternatives method to set a list of artists"
297 # Reconnect the signals!
298 self.album_change_handler = self.album_button.connect ("value-changed",
299 self.album_selection_cb)
301 self.artist_change_handler = self.artist_button.connect ("value-changed",
302 self.artist_selection_cb)
304 # Set the album art given the current data
305 self.set_album_art (song[ALBUM_COLUMN])
307 if (not song[MIME_COLUMN] in self.writer.get_supported_mimes ()):
308 self.artist_button.set_sensitive (False)
309 self.album_button.set_sensitive (False)
310 self.title_entry.set_sensitive (False)
312 self.artist_button.set_sensitive (True)
313 self.album_button.set_sensitive (True)
314 self.title_entry.set_sensitive (True)
316 def set_album_art (self, album):
319 thumb = album_art_spec.getCoverArtThumbFileName (album)
320 print "%s -> %s" % (album, thumb)
321 if (os.path.exists (thumb)):
322 self.album_art.set_from_file (thumb)
326 self.album_art.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
329 def clicked_play (self, widget):
330 if (self.player.is_playing ()):
333 song = self.get_current_row ()
334 self.player.play ("file://" + song[URI_COLUMN])
336 def album_selection_cb (self, widget):
338 On album change, add the album the local list of albums and the selector
339 if it doesn't exist already. So we show the new entry in the selector next time.
341 song = self.get_current_row ()
342 if (not widget.get_value () in self.albums_list):
343 print "Inserting ", widget.get_value ()
344 widget.get_selector ().prepend_text (widget.get_value ())
345 self.albums_list.insert (0, widget.get_value ())
346 self.set_album_art (widget.get_value ())
348 def artist_selection_cb (self, widget):
350 On artist change, add the artist the local list of artists and the selector
351 if it doesn't exist already. So we show the new entry in the selector next time
353 song = self.get_current_row ()
354 if (not widget.get_value () in self.artists_list):
355 print "Inserting artist", widget.get_value ()
356 widget.get_selector ().prepend_text (widget.get_value ())
357 self.artists_list.insert (0, widget.get_value ())
360 if __name__ == "__main__":
362 TEST_DATA = [("/home/user/Music/dylan.mp3", "Music", "Bob Dylan", "Subterranean homesick blues", "Bring it all back home", "audio/mpeg"),
363 ("/home/user/mufix/a.mp3", "Music", "", "title", "Album 2", "a/b"),
364 ("/media/mmc1/Attachments/b.m4a", "Music", "", "b", "Album 9", "audio/mpeg"),
365 ("/home/user/mufix/3.mp2", "Music", "", "titlex", "Album 3", "audio/mpeg")]
367 model = gtk.ListStore (str, str, str, str, str, str)
371 window = MussorgskyEditPanel ()
372 window.set_artist_alternatives (["", "Bob Dylan"])
373 window.set_album_alternatives (["", "Bring it all back home", "Album 2", "Album 9", "Album 3"])
374 window.set_model (model)
375 window.connect ("destroy", gtk.main_quit)