1 #!/usr/bin/env python2.5
4 from mutagen_backend import MutagenBackend
5 from player_backend import MediaPlayer
7 from album_art import MussorgskyAlbumArt
10 # Fields in the tuple!
17 class MussorgskyEditPanel (hildon.StackableWindow):
19 def __init__ (self, songs_list=None, albums_list=None, artists_list=None):
20 hildon.StackableWindow.__init__ (self)
21 self.set_border_width (12)
23 self.album_callback_id = -1
24 self.album_change_handler = -1
25 self.artist_change_handler = -1
26 self.writer = MutagenBackend ()
27 self.player = MediaPlayer ()
28 self.album_art_retriever = MussorgskyAlbumArt ()
29 self.albums_list = [a [0] for a in albums_list]
30 self.artists_list = [a [0] for a in artists_list]
33 self.set_songs_list (songs_list)
38 def update_title (self):
39 self.set_title ("Edit (%d/%d)" % (self.song_counter+1, len (self.songs_list)))
42 def set_songs_list (self, songs_list):
43 if (songs_list and len (songs_list) > 0):
44 self.songs_list = songs_list
45 self.set_data_in_view (songs_list [0])
48 def press_back_cb (self, widget):
49 if (self.player.is_playing ()):
52 if (self.banner and self.banner.get_property("visible")):
53 self.banner.destroy ()
55 if (self.album_callback_id != -1):
56 gobject.source_remove (self.album_callback_id)
57 self.album_callback_id = -1
59 if self.__is_view_dirty ():
60 print "Modified data. Save!"
63 if (self.song_counter > 0):
64 self.song_counter -= 1
65 self.set_data_in_view (self.songs_list [self.song_counter])
70 def press_next_cb (self, widget):
71 if (self.player.is_playing ()):
74 if (self.banner and self.banner.get_property("visible")):
75 self.banner.destroy ()
77 if (self.album_callback_id != -1):
78 gobject.source_remove (self.album_callback_id)
79 self.album_callback_id = -1
81 if self.__is_view_dirty ():
82 print "Modified data. Save!"
85 if (self.song_counter < len (self.songs_list) -1):
86 self.song_counter += 1
87 self.set_data_in_view (self.songs_list [self.song_counter])
92 def save_metadata (self):
93 # Save the data in the online model to show the appropiate data
94 # in the UI while tracker process the update.
95 song = self.songs_list [self.song_counter]
97 new_song = (song[FILE_URI], song[1],
98 self.artist_button.get_value (),
99 self.title_entry.get_text (),
100 self.album_button.get_value (),
102 self.songs_list [self.song_counter] = new_song
104 self.writer.save_metadata_on_file (new_song[FILE_URI],
106 self.artist_button.get_value (),
107 self.title_entry.get_text (),
108 self.album_button.get_value ())
110 # This error in case of tracker returning unexistent files.
111 # Uhm.... for instance after removing a memory card we are editing!
112 dialog = gtk.MessageDialog (self,
113 gtk.DIALOG_DESTROY_WITH_PARENT,
121 def __is_view_dirty (self):
123 True if the data has been modified in the widgets
125 song = self.songs_list [self.song_counter]
127 return not (self.filename_data.get_text() == song[FILE_URI] and
128 self.artist_button.get_value () == song[ARTIST_KEY] and
129 self.title_entry.get_text () == song[TITLE_KEY] and
130 self.album_button.get_value () == song[ALBUM_KEY] )
133 def __create_view (self):
134 view_vbox = gtk.VBox (homogeneous=False, spacing = 12)
136 filename_row = gtk.HBox ()
137 filename_label = gtk.Label ("Filename:")
138 filename_row.pack_start (filename_label, expand=False, padding=12);
139 self.filename_data = gtk.Label ("")
140 filename_row.pack_start (self.filename_data, expand=True)
142 play_button = hildon.Button (hildon.BUTTON_STYLE_NORMAL, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
143 img = gtk.image_new_from_stock (gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
144 play_button.set_image (img)
145 play_button.connect ("clicked", self.clicked_play)
146 filename_row.pack_start (play_button, expand=False, fill=False)
147 view_vbox.pack_start (filename_row, expand=False);
149 central_panel = gtk.HBox (spacing=12)
151 table = gtk.Table (3, 2, False)
152 table.set_col_spacings (12)
153 table.set_row_spacings (12)
155 central_panel.pack_start (table, fill=True)
156 view_vbox.pack_start (central_panel, expand=True, fill=True)
159 label_title = gtk.Label ("Title:")
160 table.attach (label_title, 0, 1, 0, 1, 0)
161 self.title_entry = gtk.Entry()
162 table.attach (self.title_entry, 1, 2, 0, 1)
165 artist_selector = hildon.TouchSelectorEntry (text=True)
166 for a in self.artists_list:
167 artist_selector.append_text (a)
168 self.artist_button = hildon.PickerButton (hildon.BUTTON_STYLE_NORMAL,
169 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
170 self.artist_button.set_title ("Artist: ")
171 self.artist_button.set_selector (artist_selector)
172 table.attach (self.artist_button, 0, 2, 1, 2)
176 album_selector = hildon.TouchSelectorEntry (text=True)
177 for a in self.albums_list:
178 album_selector.append_text (a)
179 self.album_button = hildon.PickerButton (hildon.BUTTON_STYLE_NORMAL,
180 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
181 self.album_button.set_title ("Album: ")
182 self.album_button.set_selector (album_selector)
183 table.attach (self.album_button, 0, 2, 2, 3)
187 album_art_button = gtk.Button ()
188 self.album_art = gtk.Image ()
189 self.album_art.set_size_request (124, 124)
190 album_art_button.add (self.album_art)
191 album_art_button.connect ("clicked", self.clicked_album_art)
192 central_panel.pack_start (album_art_button, expand=False, fill=False)
195 button_box = gtk.HButtonBox ()
196 button_box.set_layout (gtk.BUTTONBOX_END)
198 back_button = hildon.Button (hildon.BUTTON_STYLE_NORMAL, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
199 img = gtk.image_new_from_stock (gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON)
200 back_button.set_image (img)
201 back_button.connect ("clicked", self.press_back_cb)
202 button_box.pack_start (back_button, expand=True, fill=True, padding=6)
204 next_button = hildon.Button (hildon.BUTTON_STYLE_NORMAL, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
205 img = gtk.image_new_from_stock (gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON)
206 next_button.set_image (img)
207 next_button.connect ("clicked", self.press_next_cb)
208 button_box.pack_start (next_button, expand=True, fill=True, padding=6)
210 view_vbox.pack_start (button_box, expand=False, fill=True, padding=6)
214 #menu = hildon.AppMenu ()
215 #go_to = hildon.Button (hildon.BUTTON_STYLE_NORMAL,
216 # hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
217 #go_to.set_title ("Go to")
218 #go_to.connect ("clicked", self.go_to_cb)
221 #self.set_app_menu (menu)
224 def go_to_cb (self, widget):
227 def set_data_in_view (self, song):
229 Place in the screen the song information.
230 Song is a tuple like (filename, 'Music', title, artist, album, mime)
232 assert len (song) == 6
234 self.filename_data.set_text (song[FILE_URI])
235 self.title_entry.set_text (song[TITLE_KEY])
238 # Disconnect the value-change signal to avoid extra album art retrievals
239 if (self.album_button.handler_is_connected (self.album_change_handler)):
240 self.album_button.disconnect (self.album_change_handler)
242 if (self.artist_button.handler_is_connected (self.artist_change_handler)):
243 self.artist_button.disconnect (self.artist_change_handler)
245 # Set values in the picker buttons
247 self.artist_button.set_active (self.artists_list.index(song[ARTIST_KEY]))
249 print "'%s' not in artist list!?" % (song[ARTIST_KEY])
250 self.artist_button.set_value ("")
253 self.album_button.set_active (self.albums_list.index (song[ALBUM_KEY]))
255 print "'%s' is not in the album list!?" % (song[ALBUM_KEY])
256 self.album_button.set_value ("")
258 # Reconnect the signals!
259 self.album_change_handler = self.album_button.connect ("value-changed",
260 self.album_selection_cb)
262 self.artist_change_handler = self.artist_button.connect ("value-changed",
263 self.artist_selection_cb)
265 # Set the album art given the current data
267 if (song[ALBUM_KEY]):
268 thumb = album_art_spec.getCoverArtThumbFileName (song[ALBUM_KEY])
269 print "%s -> %s" % (song[ALBUM_KEY], thumb)
270 if (os.path.exists (thumb)):
271 self.album_art.set_from_file (thumb)
274 self.album_callback_id = gobject.idle_add (self.retrieve_album_art,
275 song[ARTIST_KEY], song[ALBUM_KEY])
278 self.album_art.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
280 if (not song[MIME_KEY] in self.writer.get_supported_mimes ()):
281 print "show notification"
282 self.banner = hildon.Banner ()
283 self.banner.set_text ("Unsupported format (%s)" % song[MIME_KEY])
284 self.banner.show_all ()
286 def retrieve_album_art (self, artist, album):
287 print "trying to get the album art"
288 (img, thumb) = self.album_art_retriever.get_album_art (artist, album)
290 self.album_art.set_from_file (thumb)
292 print "Unable to retrieve album art"
296 def clicked_play (self, widget):
297 if (self.player.is_playing ()):
300 song = self.songs_list [self.song_counter]
301 self.player.play ("file://" + song[FILE_URI])
303 def clicked_album_art (self, widget):
304 print "implement me, please"
306 def album_selection_cb (self, widget):
308 On album change, add the album the local list of albums and the selector
309 if it doesn't exist already. So we show the new entry in the selector next time.
311 song = self.songs_list [self.song_counter]
312 if (not widget.get_value () in self.albums_list):
313 print "Inserting ", widget.get_value ()
314 widget.get_selector ().prepend_text (widget.get_value ())
315 self.albums_list.insert (0, widget.get_value ())
316 self.retrieve_album_art (song[ARTIST_KEY], widget.get_value ())
318 def artist_selection_cb (self, widget):
320 On artist change, add the artist the local list of artists and the selector
321 if it doesn't exist already. So we show the new entry in the selector next time
323 song = self.songs_list [self.song_counter]
324 if (not widget.get_value () in self.artists_list):
325 print "Inserting artist", widget.get_value ()
326 widget.get_selector ().prepend_text (widget.get_value ())
327 self.artists_list.insert (0, widget.get_value ())
330 if __name__ == "__main__":
332 TEST_DATA = [("/home/user/Music/dylan.mp3", "Music", "Bob Dylan", "Subterranean homesick blues", "Bring it all back home", "audio/mpeg"),
333 ("/home/user/mufix/a.mp3", "Music", "", "title", "Album 2", "a/b"),
334 ("/media/mmc1/Attachments/b.m4a", "Music", "", "b", "Album 9", "audio/mpeg"),
335 ("/home/user/mufix/3.mp2", "Music", "", "titlex", "Album 3", "audio/mpeg")]
337 ALBUMS = [["Album %d" % i] for i in range (0, 10)] + [["Bring it all back home"]]
338 ARTISTS = [["Artist %d" % i] for i in range (0, 10)] + [["Bob Dylan"]]
339 window = MussorgskyEditPanel (TEST_DATA, ALBUMS, ARTISTS)
340 window.connect ("destroy", gtk.main_quit)