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 THEME_PATH = "/usr/share/themes/default"
22 class MussorgskyEditPanel (hildon.StackableWindow):
25 hildon.StackableWindow.__init__ (self)
26 self.set_border_width (12)
27 self.album_change_handler = -1
28 self.artist_change_handler = -1
29 self.writer = MutagenBackend ()
30 self.player = MediaPlayer ()
32 self.data_loaded = False
33 self.artist_list = None
34 self.albums_list = None
35 self.connect ("delete-event", self.close_function)
37 def close_function (self, widget, event):
38 if (not self.data_loaded):
41 if self.__is_view_dirty ():
45 def update_title (self):
46 self.set_title ("Edit (%d/%d)" % (self.model.get_path (self.current)[0] + 1,
49 def get_current_row (self):
50 if (not self.current):
52 return self.model.get (self.current, 0, 1, 2, 3, 4, 5)
54 def set_model (self, model, current=None):
56 if self.artists_list or self.albums_list:
58 except AttributeError, e:
59 print "**** Set album and artist alternatives before setting a model"
64 self.current = current
66 self.current = self.model.get_iter_first ()
67 self.data_loaded = True
68 self.set_data_in_view (self.get_current_row ())
71 def set_current (self, current):
73 Iterator to current element
75 self.current = current
76 self.set_data_in_view (self.get_current_row ())
80 def set_artist_alternatives (self, alternatives):
81 self.artists_list = alternatives
82 artist_selector = hildon.TouchSelectorEntry (text=True)
83 for a in self.artists_list:
84 artist_selector.append_text (a)
85 self.artist_button.set_selector (artist_selector)
87 def set_album_alternatives (self, alternatives):
88 self.albums_list = alternatives
89 album_selector = hildon.TouchSelectorEntry (text=True)
90 for a in self.albums_list:
91 album_selector.append_text (a)
92 self.album_button.set_selector (album_selector)
95 def press_back_cb (self, widget):
96 if (self.player.is_playing ()):
99 if self.__is_view_dirty ():
100 print "Modified data. Save!"
101 self.save_metadata ()
103 path = self.model.get_path (self.current)
107 new_path = ( path[0] -1, )
108 self.current = self.model.get_iter (new_path)
109 self.set_data_in_view (self.get_current_row ())
112 def press_next_cb (self, widget):
113 if (self.player.is_playing ()):
116 if self.__is_view_dirty ():
117 print "Modified data. Save!"
118 self.save_metadata ()
120 self.current = self.model.iter_next (self.current)
121 if (not self.current):
124 self.set_data_in_view (self.get_current_row ())
128 def save_metadata (self):
129 # Save the data in the online model to show the appropiate data
130 # in the UI while tracker process the update.
132 # 0 - filename -> doesn't change
133 # 1 - "Music" -> doesn't change
134 # 5 - mimetype -> doesn't change
135 if (type (self.model) == gtk.TreeModelFilter):
136 m = self.model.get_model ()
137 c = self.model.convert_iter_to_child_iter (self.current)
143 artist = self.artist_button.get_value ()
144 title = self.title_entry.get_text ()
145 album = self.album_button.get_value ()
146 text = "<b>%s</b>\n<small>%s</small>" % (escape_html (title),
147 escape_html (artist) + " / " + escape_html (album))
148 search_str = artist.lower () + " " + title.lower () + " " + album.lower ()
151 ARTIST_COLUMN, artist,
155 SEARCH_COLUMN, search_str)
156 new_song = self.get_current_row ()
158 self.writer.save_metadata_on_file (new_song[URI_COLUMN],
159 new_song[MIME_COLUMN],
160 self.artist_button.get_value (),
161 self.title_entry.get_text (),
162 self.album_button.get_value ())
164 # This error in case of tracker returning unexistent files.
165 # Uhm.... for instance after removing a memory card we are editing!
167 #dialog = gtk.MessageDialog (self,
168 # gtk.DIALOG_DESTROY_WITH_PARENT,
175 def __is_view_dirty (self):
177 True if the data has been modified in the widgets
179 song = self.get_current_row ()
181 return not (self.filename_data.get_text() == song[URI_COLUMN] and
182 self.artist_button.get_value () == song[ARTIST_COLUMN] and
183 self.title_entry.get_text () == song[TITLE_COLUMN] and
184 self.album_button.get_value () == song[ALBUM_COLUMN] )
187 def __create_view (self):
188 view_vbox = gtk.VBox (homogeneous=False, spacing = 12)
190 filename_row = gtk.HBox ()
191 self.filename_data = gtk.Label ("")
192 filename_row.pack_start (self.filename_data, expand=True)
194 #filename_row.pack_start (play_button, expand=False, fill=False)
195 view_vbox.pack_start (filename_row, expand=False);
197 central_panel = gtk.HBox (spacing=12)
199 table = gtk.Table (3, 2, False)
200 table.set_col_spacings (12)
201 table.set_row_spacings (12)
203 central_panel.pack_start (table, fill=True)
204 view_vbox.pack_start (central_panel, expand=True, fill=True)
207 label_title = gtk.Label ("Title:")
208 table.attach (label_title, 0, 1, 0, 1, 0)
209 self.title_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
210 table.attach (self.title_entry, 1, 2, 0, 1)
213 self.artist_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
214 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
215 self.artist_button.set_title ("Artist: ")
216 # Set data will set the selector
217 table.attach (self.artist_button, 0, 2, 1, 2)
221 self.album_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
222 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
223 self.album_button.set_title ("Album: ")
224 # set_data will set the selector
225 table.attach (self.album_button, 0, 2, 2, 3)
229 self.album_art = gtk.Image ()
230 self.album_art.set_size_request (124, 124)
231 central_panel.pack_start (self.album_art, expand=False, fill=False)
234 button_box = gtk.Toolbar ()
235 play_image = os.path.join (THEME_PATH, "mediaplayer", "Play.png")
236 play_button = gtk.ToolButton (gtk.image_new_from_file (play_image))
237 play_button.connect ("clicked", self.clicked_play)
238 play_button.set_expand (True)
239 button_box.insert (play_button, -1)
241 separator = gtk.SeparatorToolItem ()
242 separator.set_expand (True)
243 button_box.insert (separator, -1)
245 back_image = os.path.join (THEME_PATH, "mediaplayer", "Back.png")
246 back_button = gtk.ToolButton (gtk.image_new_from_file (back_image))
247 back_button.connect ("clicked", self.press_back_cb)
248 back_button.set_expand (True)
249 button_box.insert (back_button, -1)
251 next_image = os.path.join (THEME_PATH, "mediaplayer", "Forward.png")
252 next_button = gtk.ToolButton (gtk.image_new_from_file (next_image))
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)