1 #!/usr/bin/env python2.5
4 from mutagen_backend import MutagenBackend
5 from player_backend import MediaPlayer
16 class MussorgskyEditPanel (hildon.StackableWindow):
19 hildon.StackableWindow.__init__ (self)
20 self.set_border_width (12)
21 self.album_callback_id = -1
22 self.album_change_handler = -1
23 self.artist_change_handler = -1
24 self.writer = MutagenBackend ()
25 self.player = MediaPlayer ()
27 self.data_loaded = False
28 self.artist_list = None
29 self.albums_list = None
30 self.connect ("delete-event", self.close_function)
32 def close_function (self, widget, event):
33 if (not self.data_loaded):
36 if self.__is_view_dirty ():
40 def update_title (self):
41 self.set_title ("Edit (%d/%d)" % (self.model.get_path (self.current)[0] + 1,
44 def get_current_row (self):
45 if (not self.current):
47 return self.model.get (self.current, 0, 1, 2, 3, 4, 5)
49 def set_model (self, model, current=None):
51 if self.artists_list or self.albums_list:
53 except AttributeError, e:
54 print "**** Set album and artist alternatives before setting a model"
59 self.current = current
61 self.current = self.model.get_iter_first ()
62 self.data_loaded = True
63 self.set_data_in_view (self.get_current_row ())
66 def set_current (self, current):
68 Iterator to current element
70 self.current = current
71 self.set_data_in_view (self.get_current_row ())
75 def set_artist_alternatives (self, alternatives):
76 self.artists_list = alternatives
77 artist_selector = hildon.TouchSelectorEntry (text=True)
78 for a in self.artists_list:
79 artist_selector.append_text (a)
80 self.artist_button.set_selector (artist_selector)
82 def set_album_alternatives (self, alternatives):
83 self.albums_list = alternatives
84 album_selector = hildon.TouchSelectorEntry (text=True)
85 for a in self.albums_list:
86 album_selector.append_text (a)
87 self.album_button.set_selector (album_selector)
90 def press_back_cb (self, widget):
91 if (self.player.is_playing ()):
94 if (self.album_callback_id != -1):
95 gobject.source_remove (self.album_callback_id)
96 self.album_callback_id = -1
98 if self.__is_view_dirty ():
99 print "Modified data. Save!"
100 self.save_metadata ()
102 path = self.model.get_path (self.current)
106 new_path = ( path[0] -1, )
107 self.current = self.model.get_iter (new_path)
108 self.set_data_in_view (self.get_current_row ())
111 def press_next_cb (self, widget):
112 if (self.player.is_playing ()):
115 if (self.album_callback_id != -1):
116 gobject.source_remove (self.album_callback_id)
117 self.album_callback_id = -1
119 if self.__is_view_dirty ():
120 print "Modified data. Save!"
121 self.save_metadata ()
123 self.current = self.model.iter_next (self.current)
124 if (not self.current):
128 self.set_data_in_view (self.get_current_row ())
132 def save_metadata (self):
133 # Save the data in the online model to show the appropiate data
134 # in the UI while tracker process the update.
136 # 0 - filename -> doesn't change
137 # 1 - "Music" -> doesn't change
138 # 5 - mimetype -> doesn't change
139 if (type (self.model) == gtk.TreeModelFilter):
140 print "Ye un filtered"
141 m = self.model.get_model ()
142 c = self.model.convert_iter_to_child_iter (self.current)
149 2, self.artist_button.get_value (),
150 3, self.title_entry.get_text (),
151 4, self.album_button.get_value ())
152 new_song = self.get_current_row ()
154 self.writer.save_metadata_on_file (new_song[FILE_URI],
156 self.artist_button.get_value (),
157 self.title_entry.get_text (),
158 self.album_button.get_value ())
160 # This error in case of tracker returning unexistent files.
161 # Uhm.... for instance after removing a memory card we are editing!
163 #dialog = gtk.MessageDialog (self,
164 # gtk.DIALOG_DESTROY_WITH_PARENT,
171 def __is_view_dirty (self):
173 True if the data has been modified in the widgets
175 song = self.get_current_row ()
177 return not (self.filename_data.get_text() == song[FILE_URI] and
178 self.artist_button.get_value () == song[ARTIST_KEY] and
179 self.title_entry.get_text () == song[TITLE_KEY] and
180 self.album_button.get_value () == song[ALBUM_KEY] )
183 def __create_view (self):
184 view_vbox = gtk.VBox (homogeneous=False, spacing = 12)
186 filename_row = gtk.HBox ()
187 filename_label = gtk.Label ()
188 filename_label.set_markup ("<small>Filename:</small>")
189 filename_row.pack_start (filename_label, expand=False, padding=12);
190 self.filename_data = gtk.Label ("")
191 filename_row.pack_start (self.filename_data, expand=True)
193 #filename_row.pack_start (play_button, expand=False, fill=False)
194 view_vbox.pack_start (filename_row, expand=False);
196 central_panel = gtk.HBox (spacing=12)
198 table = gtk.Table (3, 2, False)
199 table.set_col_spacings (12)
200 table.set_row_spacings (12)
202 central_panel.pack_start (table, fill=True)
203 view_vbox.pack_start (central_panel, expand=True, fill=True)
206 label_title = gtk.Label ("Title:")
207 table.attach (label_title, 0, 1, 0, 1, 0)
208 self.title_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
209 table.attach (self.title_entry, 1, 2, 0, 1)
212 self.artist_button = hildon.PickerButton (gtk.HILDON_SIZE_FINGER_HEIGHT,
213 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
214 self.artist_button.set_title ("Artist: ")
215 # Set data will set the selector
216 table.attach (self.artist_button, 0, 2, 1, 2)
220 self.album_button = hildon.PickerButton (gtk.HILDON_SIZE_FINGER_HEIGHT,
221 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
222 self.album_button.set_title ("Album: ")
223 # set_data will set the selector
224 table.attach (self.album_button, 0, 2, 2, 3)
228 self.album_art = gtk.Image ()
229 self.album_art.set_size_request (124, 124)
230 central_panel.pack_start (self.album_art, expand=False, fill=False)
233 button_box = gtk.Toolbar ()
235 play_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON))
236 play_button.connect ("clicked", self.clicked_play)
237 play_button.set_expand (True)
238 button_box.insert (play_button, -1)
240 separator = gtk.SeparatorToolItem ()
241 separator.set_expand (True)
242 button_box.insert (separator, -1)
244 back_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON))
245 back_button.connect ("clicked", self.press_back_cb)
246 back_button.set_expand (True)
247 button_box.insert (back_button, -1)
249 next_button = gtk.ToolButton (gtk.image_new_from_stock (gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON))
250 next_button.connect ("clicked", self.press_next_cb)
251 next_button.set_expand (True)
252 button_box.insert (next_button, -1)
254 self.add_toolbar (button_box)
259 def set_data_in_view (self, song):
261 Place in the screen the song information.
262 Song is a tuple like (filename, 'Music', title, artist, album, mime)
264 assert len (song) == 6
266 self.filename_data.set_markup ("<small>" + song[FILE_URI] + "</small>")
267 self.title_entry.set_text (song[TITLE_KEY])
270 # Disconnect the value-change signal to avoid extra album art retrievals
271 if (self.album_button.handler_is_connected (self.album_change_handler)):
272 self.album_button.disconnect (self.album_change_handler)
274 if (self.artist_button.handler_is_connected (self.artist_change_handler)):
275 self.artist_button.disconnect (self.artist_change_handler)
277 # Set values in the picker buttons
279 self.artist_button.set_active (self.artists_list.index(song[ARTIST_KEY]))
281 print "'%s' not in artist list!?" % (song[ARTIST_KEY])
282 self.artist_button.set_value ("")
283 except AttributeError:
284 print "WARNING: Use set_artist_alternatives method to set a list of artists"
287 self.album_button.set_active (self.albums_list.index (song[ALBUM_KEY]))
289 print "'%s' is not in the album list!?" % (song[ALBUM_KEY])
290 self.album_button.set_value ("")
291 except AttributeError:
292 print "WARNING: Use set_album_alternatives method to set a list of artists"
294 # Reconnect the signals!
295 self.album_change_handler = self.album_button.connect ("value-changed",
296 self.album_selection_cb)
298 self.artist_change_handler = self.artist_button.connect ("value-changed",
299 self.artist_selection_cb)
301 # Set the album art given the current data
302 self.set_album_art (song[ALBUM_KEY])
304 if (not song[MIME_KEY] in self.writer.get_supported_mimes ()):
305 self.artist_button.set_sensitive (False)
306 self.album_button.set_sensitive (False)
307 self.title_entry.set_sensitive (False)
309 self.artist_button.set_sensitive (True)
310 self.album_button.set_sensitive (True)
311 self.title_entry.set_sensitive (True)
313 def set_album_art (self, album):
316 thumb = album_art_spec.getCoverArtThumbFileName (album)
317 print "%s -> %s" % (album, thumb)
318 if (os.path.exists (thumb)):
319 self.album_art.set_from_file (thumb)
323 self.album_art.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
326 def clicked_play (self, widget):
327 if (self.player.is_playing ()):
330 song = self.songs_list [self.song_counter]
331 self.player.play ("file://" + song[FILE_URI])
333 def album_selection_cb (self, widget):
335 On album change, add the album the local list of albums and the selector
336 if it doesn't exist already. So we show the new entry in the selector next time.
338 song = self.get_current_row ()
339 if (not widget.get_value () in self.albums_list):
340 print "Inserting ", widget.get_value ()
341 widget.get_selector ().prepend_text (widget.get_value ())
342 self.albums_list.insert (0, widget.get_value ())
343 self.set_album_art (widget.get_value ())
345 def artist_selection_cb (self, widget):
347 On artist change, add the artist the local list of artists and the selector
348 if it doesn't exist already. So we show the new entry in the selector next time
350 song = self.get_current_row ()
351 if (not widget.get_value () in self.artists_list):
352 print "Inserting artist", widget.get_value ()
353 widget.get_selector ().prepend_text (widget.get_value ())
354 self.artists_list.insert (0, widget.get_value ())
357 if __name__ == "__main__":
359 TEST_DATA = [("/home/user/Music/dylan.mp3", "Music", "Bob Dylan", "Subterranean homesick blues", "Bring it all back home", "audio/mpeg"),
360 ("/home/user/mufix/a.mp3", "Music", "", "title", "Album 2", "a/b"),
361 ("/media/mmc1/Attachments/b.m4a", "Music", "", "b", "Album 9", "audio/mpeg"),
362 ("/home/user/mufix/3.mp2", "Music", "", "titlex", "Album 3", "audio/mpeg")]
364 model = gtk.ListStore (str, str, str, str, str, str)
368 window = MussorgskyEditPanel ()
369 window.set_artist_alternatives (["", "Bob Dylan"])
370 window.set_album_alternatives (["", "Bring it all back home", "Album 2", "Album 9", "Album 3"])
371 window.set_model (model)
372 window.connect ("destroy", gtk.main_quit)