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 filename_label = gtk.Label ()
190 filename_label.set_markup ("<small>Filename:</small>")
191 filename_row.pack_start (filename_label, expand=False, padding=12);
192 self.filename_data = gtk.Label ("")
193 filename_row.pack_start (self.filename_data, expand=True)
195 #filename_row.pack_start (play_button, expand=False, fill=False)
196 view_vbox.pack_start (filename_row, expand=False);
198 central_panel = gtk.HBox (spacing=12)
200 table = gtk.Table (3, 2, False)
201 table.set_col_spacings (12)
202 table.set_row_spacings (12)
204 central_panel.pack_start (table, fill=True)
205 view_vbox.pack_start (central_panel, expand=True, fill=True)
208 label_title = gtk.Label ("Title:")
209 table.attach (label_title, 0, 1, 0, 1, 0)
210 self.title_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
211 table.attach (self.title_entry, 1, 2, 0, 1)
214 self.artist_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
215 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
216 self.artist_button.set_title ("Artist: ")
217 # Set data will set the selector
218 table.attach (self.artist_button, 0, 2, 1, 2)
222 self.album_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
223 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
224 self.album_button.set_title ("Album: ")
225 # set_data will set the selector
226 table.attach (self.album_button, 0, 2, 2, 3)
230 self.album_art = gtk.Image ()
231 self.album_art.set_size_request (124, 124)
232 central_panel.pack_start (self.album_art, expand=False, fill=False)
235 button_box = gtk.Toolbar ()
237 play_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON))
238 play_button.connect ("clicked", self.clicked_play)
239 play_button.set_expand (True)
240 button_box.insert (play_button, -1)
242 separator = gtk.SeparatorToolItem ()
243 separator.set_expand (True)
244 button_box.insert (separator, -1)
246 back_img = gtk.Image ()
247 back_img.set_from_icon_name ("general_back", gtk.ICON_SIZE_BUTTON)
248 back_button = gtk.ToolButton (back_img)
249 back_button.connect ("clicked", self.press_back_cb)
250 back_button.set_expand (True)
251 button_box.insert (back_button, -1)
253 next_img = gtk.Image ()
254 next_img.set_from_icon_name ("general_forward", gtk.ICON_SIZE_BUTTON)
255 next_button = gtk.ToolButton (next_img)
256 next_button.connect ("clicked", self.press_next_cb)
257 next_button.set_expand (True)
258 button_box.insert (next_button, -1)
260 self.add_toolbar (button_box)
265 def set_data_in_view (self, song):
267 Place in the screen the song information.
268 Song is a tuple like (filename, 'Music', title, artist, album, mime)
270 assert len (song) == 6
272 self.filename_data.set_markup ("<small>" + song[URI_COLUMN] + "</small>")
273 self.title_entry.set_text (song[TITLE_COLUMN])
276 # Disconnect the value-change signal to avoid extra album art retrievals
277 if (self.album_button.handler_is_connected (self.album_change_handler)):
278 self.album_button.disconnect (self.album_change_handler)
280 if (self.artist_button.handler_is_connected (self.artist_change_handler)):
281 self.artist_button.disconnect (self.artist_change_handler)
283 # Set values in the picker buttons
285 self.artist_button.set_active (self.artists_list.index(song[ARTIST_COLUMN]))
287 print "'%s' not in artist list!?" % (song[ARTIST_COLUMN])
288 self.artist_button.set_value ("")
289 except AttributeError:
290 print "WARNING: Use set_artist_alternatives method to set a list of artists"
293 self.album_button.set_active (self.albums_list.index (song[ALBUM_COLUMN]))
295 print "'%s' is not in the album list!?" % (song[ALBUM_COLUMN])
296 self.album_button.set_value ("")
297 except AttributeError:
298 print "WARNING: Use set_album_alternatives method to set a list of artists"
300 # Reconnect the signals!
301 self.album_change_handler = self.album_button.connect ("value-changed",
302 self.album_selection_cb)
304 self.artist_change_handler = self.artist_button.connect ("value-changed",
305 self.artist_selection_cb)
307 # Set the album art given the current data
308 self.set_album_art (song[ALBUM_COLUMN])
310 if (not song[MIME_COLUMN] in self.writer.get_supported_mimes ()):
311 self.artist_button.set_sensitive (False)
312 self.album_button.set_sensitive (False)
313 self.title_entry.set_sensitive (False)
315 self.artist_button.set_sensitive (True)
316 self.album_button.set_sensitive (True)
317 self.title_entry.set_sensitive (True)
319 def set_album_art (self, album):
322 thumb = album_art_spec.getCoverArtThumbFileName (album)
323 print "%s -> %s" % (album, thumb)
324 if (os.path.exists (thumb)):
325 self.album_art.set_from_file (thumb)
329 self.album_art.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
332 def clicked_play (self, widget):
333 if (self.player.is_playing ()):
336 song = self.get_current_row ()
337 self.player.play ("file://" + song[URI_COLUMN])
339 def album_selection_cb (self, widget):
341 On album change, add the album the local list of albums and the selector
342 if it doesn't exist already. So we show the new entry in the selector next time.
344 song = self.get_current_row ()
345 if (not widget.get_value () in self.albums_list):
346 print "Inserting ", widget.get_value ()
347 widget.get_selector ().prepend_text (widget.get_value ())
348 self.albums_list.insert (0, widget.get_value ())
349 self.set_album_art (widget.get_value ())
351 def artist_selection_cb (self, widget):
353 On artist change, add the artist the local list of artists and the selector
354 if it doesn't exist already. So we show the new entry in the selector next time
356 song = self.get_current_row ()
357 if (not widget.get_value () in self.artists_list):
358 print "Inserting artist", widget.get_value ()
359 widget.get_selector ().prepend_text (widget.get_value ())
360 self.artists_list.insert (0, widget.get_value ())
363 if __name__ == "__main__":
365 TEST_DATA = [("/home/user/Music/dylan.mp3", "Music", "Bob Dylan", "Subterranean homesick blues", "Bring it all back home", "audio/mpeg"),
366 ("/home/user/mufix/a.mp3", "Music", "", "title", "Album 2", "a/b"),
367 ("/media/mmc1/Attachments/b.m4a", "Music", "", "b", "Album 9", "audio/mpeg"),
368 ("/home/user/mufix/3.mp2", "Music", "", "titlex", "Album 3", "audio/mpeg")]
370 model = gtk.ListStore (str, str, str, str, str, str)
374 window = MussorgskyEditPanel ()
375 window.set_artist_alternatives (["", "Bob Dylan"])
376 window.set_album_alternatives (["", "Bring it all back home", "Album 2", "Album 9", "Album 3"])
377 window.set_model (model)
378 window.connect ("destroy", gtk.main_quit)