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_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON))
247 back_button.connect ("clicked", self.press_back_cb)
248 back_button.set_expand (True)
249 button_box.insert (back_button, -1)
251 next_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON))
252 next_button.connect ("clicked", self.press_next_cb)
253 next_button.set_expand (True)
254 button_box.insert (next_button, -1)
256 self.add_toolbar (button_box)
261 def set_data_in_view (self, song):
263 Place in the screen the song information.
264 Song is a tuple like (filename, 'Music', title, artist, album, mime)
266 assert len (song) == 6
268 self.filename_data.set_markup ("<small>" + song[URI_COLUMN] + "</small>")
269 self.title_entry.set_text (song[TITLE_COLUMN])
272 # Disconnect the value-change signal to avoid extra album art retrievals
273 if (self.album_button.handler_is_connected (self.album_change_handler)):
274 self.album_button.disconnect (self.album_change_handler)
276 if (self.artist_button.handler_is_connected (self.artist_change_handler)):
277 self.artist_button.disconnect (self.artist_change_handler)
279 # Set values in the picker buttons
281 self.artist_button.set_active (self.artists_list.index(song[ARTIST_COLUMN]))
283 print "'%s' not in artist list!?" % (song[ARTIST_COLUMN])
284 self.artist_button.set_value ("")
285 except AttributeError:
286 print "WARNING: Use set_artist_alternatives method to set a list of artists"
289 self.album_button.set_active (self.albums_list.index (song[ALBUM_COLUMN]))
291 print "'%s' is not in the album list!?" % (song[ALBUM_COLUMN])
292 self.album_button.set_value ("")
293 except AttributeError:
294 print "WARNING: Use set_album_alternatives method to set a list of artists"
296 # Reconnect the signals!
297 self.album_change_handler = self.album_button.connect ("value-changed",
298 self.album_selection_cb)
300 self.artist_change_handler = self.artist_button.connect ("value-changed",
301 self.artist_selection_cb)
303 # Set the album art given the current data
304 self.set_album_art (song[ALBUM_COLUMN])
306 if (not song[MIME_COLUMN] in self.writer.get_supported_mimes ()):
307 self.artist_button.set_sensitive (False)
308 self.album_button.set_sensitive (False)
309 self.title_entry.set_sensitive (False)
311 self.artist_button.set_sensitive (True)
312 self.album_button.set_sensitive (True)
313 self.title_entry.set_sensitive (True)
315 def set_album_art (self, album):
318 thumb = album_art_spec.getCoverArtThumbFileName (album)
319 print "%s -> %s" % (album, thumb)
320 if (os.path.exists (thumb)):
321 self.album_art.set_from_file (thumb)
325 self.album_art.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
328 def clicked_play (self, widget):
329 if (self.player.is_playing ()):
332 song = self.songs_list [self.song_counter]
333 self.player.play ("file://" + song[URI_COLUMN])
335 def album_selection_cb (self, widget):
337 On album change, add the album the local list of albums and the selector
338 if it doesn't exist already. So we show the new entry in the selector next time.
340 song = self.get_current_row ()
341 if (not widget.get_value () in self.albums_list):
342 print "Inserting ", widget.get_value ()
343 widget.get_selector ().prepend_text (widget.get_value ())
344 self.albums_list.insert (0, widget.get_value ())
345 self.set_album_art (widget.get_value ())
347 def artist_selection_cb (self, widget):
349 On artist change, add the artist the local list of artists and the selector
350 if it doesn't exist already. So we show the new entry in the selector next time
352 song = self.get_current_row ()
353 if (not widget.get_value () in self.artists_list):
354 print "Inserting artist", widget.get_value ()
355 widget.get_selector ().prepend_text (widget.get_value ())
356 self.artists_list.insert (0, widget.get_value ())
359 if __name__ == "__main__":
361 TEST_DATA = [("/home/user/Music/dylan.mp3", "Music", "Bob Dylan", "Subterranean homesick blues", "Bring it all back home", "audio/mpeg"),
362 ("/home/user/mufix/a.mp3", "Music", "", "title", "Album 2", "a/b"),
363 ("/media/mmc1/Attachments/b.m4a", "Music", "", "b", "Album 9", "audio/mpeg"),
364 ("/home/user/mufix/3.mp2", "Music", "", "titlex", "Album 3", "audio/mpeg")]
366 model = gtk.ListStore (str, str, str, str, str, str)
370 window = MussorgskyEditPanel ()
371 window.set_artist_alternatives (["", "Bob Dylan"])
372 window.set_album_alternatives (["", "Bring it all back home", "Album 2", "Album 9", "Album 3"])
373 window.set_model (model)
374 window.connect ("destroy", gtk.main_quit)