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_title ("Edit")
22 self.set_border_width (12)
24 self.album_callback_id = -1
25 self.album_change_handler = -1
26 self.artist_change_handler = -1
27 self.writer = MutagenBackend ()
28 self.player = MediaPlayer ()
29 self.album_art_retriever = MussorgskyAlbumArt ()
30 self.albums_list = [a [0] for a in albums_list]
31 self.artists_list = [a [0] for a in artists_list]
32 self.add (self.__create_view ())
34 self.set_songs_list (songs_list)
38 def set_songs_list (self, songs_list):
39 if (songs_list and len (songs_list) > 0):
40 self.songs_list = songs_list
41 self.set_data_in_view (songs_list [0])
44 def press_back_cb (self, widget):
45 if (self.player.is_playing ()):
48 if (self.banner and self.banner.get_property("visible")):
49 self.banner.destroy ()
51 if (self.album_callback_id != -1):
52 gobject.source_remove (self.album_callback_id)
53 self.album_callback_id = -1
55 if self.__is_view_dirty ():
56 print "Modified data. Save!"
59 if (self.song_counter > 0):
60 self.song_counter -= 1
61 self.set_data_in_view (self.songs_list [self.song_counter])
63 def press_next_cb (self, widget):
64 if (self.player.is_playing ()):
67 if (self.banner and self.banner.get_property("visible")):
68 self.banner.destroy ()
70 if (self.album_callback_id != -1):
71 gobject.source_remove (self.album_callback_id)
72 self.album_callback_id = -1
74 if self.__is_view_dirty ():
75 print "Modified data. Save!"
78 if (self.song_counter < len (self.songs_list) -1):
79 self.song_counter += 1
80 self.set_data_in_view (self.songs_list [self.song_counter])
84 def save_metadata (self):
85 # Save the data in the online model to show the appropiate data
86 # in the UI while tracker process the update.
87 song = self.songs_list [self.song_counter]
89 new_song = (song[FILE_URI], song[1],
90 self.artist_button.get_value (),
91 self.title_entry.get_text (),
92 self.album_button.get_value (),
94 self.songs_list [self.song_counter] = new_song
96 self.writer.save_metadata_on_file (new_song[FILE_URI],
98 self.artist_button.get_value (),
99 self.title_entry.get_text (),
100 self.album_button.get_value ())
102 # This error in case of tracker returning unexistent files.
103 # Uhm.... for instance after removing a memory card we are editing!
104 dialog = gtk.MessageDialog (self,
105 gtk.DIALOG_DESTROY_WITH_PARENT,
113 def __is_view_dirty (self):
115 True if the data has been modified in the widgets
117 song = self.songs_list [self.song_counter]
119 return not (self.filename_data.get_text() == song[FILE_URI] and
120 self.artist_button.get_value () == song[ARTIST_KEY] and
121 self.title_entry.get_text () == song[TITLE_KEY] and
122 self.album_button.get_value () == song[ALBUM_KEY] )
125 def __create_view (self):
126 view_vbox = gtk.VBox (homogeneous=False, spacing = 12)
128 filename_row = gtk.HBox ()
129 filename_label = gtk.Label ("Filename:")
130 filename_row.pack_start (filename_label, expand=False, padding=12);
131 self.filename_data = gtk.Label ("")
132 filename_row.pack_start (self.filename_data, expand=True)
134 play_button = hildon.Button (hildon.BUTTON_STYLE_NORMAL, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
135 img = gtk.image_new_from_stock (gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
136 play_button.set_image (img)
137 play_button.connect ("clicked", self.clicked_play)
138 filename_row.pack_start (play_button, expand=False, fill=False)
139 view_vbox.pack_start (filename_row, expand=False);
141 central_panel = gtk.HBox (spacing=12)
143 table = gtk.Table (3, 2, False)
144 table.set_col_spacings (12)
145 table.set_row_spacings (12)
147 central_panel.pack_start (table, fill=True)
148 view_vbox.pack_start (central_panel, expand=True, fill=True)
151 label_title = gtk.Label ("Title:")
152 table.attach (label_title, 0, 1, 0, 1, 0)
153 self.title_entry = gtk.Entry()
154 table.attach (self.title_entry, 1, 2, 0, 1)
157 artist_selector = hildon.hildon_touch_selector_new_text ()
158 for a in self.artists_list:
159 artist_selector.append_text (a)
160 self.artist_button = hildon.PickerButton (hildon.BUTTON_STYLE_NORMAL,
161 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
162 self.artist_button.set_title ("Artist: ")
163 self.artist_button.set_selector (artist_selector)
164 table.attach (self.artist_button, 0, 2, 1, 2)
168 album_selector = hildon.hildon_touch_selector_new_text ()
169 for a in self.albums_list:
170 album_selector.append_text (a)
171 self.album_button = hildon.PickerButton (hildon.BUTTON_STYLE_NORMAL,
172 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
173 self.album_button.set_title ("Album: ")
174 self.album_button.set_selector (album_selector)
175 table.attach (self.album_button, 0, 2, 2, 3)
179 album_art_button = gtk.Button ()
180 self.album_art = gtk.Image ()
181 self.album_art.set_size_request (124, 124)
182 album_art_button.add (self.album_art)
183 album_art_button.connect ("clicked", self.clicked_album_art)
184 central_panel.pack_start (album_art_button, expand=False, fill=False)
187 button_box = gtk.HButtonBox ()
188 button_box.set_layout (gtk.BUTTONBOX_END)
190 back_button = hildon.Button (hildon.BUTTON_STYLE_NORMAL, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
191 img = gtk.image_new_from_stock (gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON)
192 back_button.set_image (img)
193 back_button.connect ("clicked", self.press_back_cb)
194 button_box.pack_start (back_button, expand=True, fill=True, padding=6)
196 next_button = hildon.Button (hildon.BUTTON_STYLE_NORMAL, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
197 img = gtk.image_new_from_stock (gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON)
198 next_button.set_image (img)
199 next_button.connect ("clicked", self.press_next_cb)
200 button_box.pack_start (next_button, expand=True, fill=True, padding=6)
202 view_vbox.pack_start (button_box, expand=False, fill=True, padding=6)
207 def set_data_in_view (self, song):
209 Place in the screen the song information.
210 Song is a tuple like (filename, 'Music', title, artist, album, mime)
212 assert len (song) == 6
214 self.filename_data.set_text (song[FILE_URI])
215 self.title_entry.set_text (song[TITLE_KEY])
218 # Disconnect the value-change signal to avoid extra album art retrievals
219 if (self.album_button.handler_is_connected (self.album_change_handler)):
220 self.album_button.disconnect (self.album_change_handler)
222 if (self.artist_button.handler_is_connected (self.artist_change_handler)):
223 self.artist_button.disconnect (self.artist_change_handler)
225 # Set values in the picker buttons
227 self.artist_button.set_active (self.artists_list.index(song[ARTIST_KEY]))
229 print "'%s' not in artist list!?" % (song[ARTIST_KEY])
230 self.artist_button.set_value ("")
233 self.album_button.set_active (self.albums_list.index (song[ALBUM_KEY]))
235 print "'%s' is not in the album list!?" % (song[ALBUM_KEY])
236 self.album_button.set_value ("")
238 # Reconnect the signals!
239 self.album_change_handler = self.album_button.connect ("value-changed",
240 self.album_selection_cb)
242 self.artist_change_handler = self.artist_button.connect ("value-changed",
243 self.artist_selection_cb)
245 # Set the album art given the current data
247 if (song[ALBUM_KEY]):
248 thumb = album_art_spec.getCoverArtThumbFileName (song[ALBUM_KEY])
249 print "%s -> %s" % (song[ALBUM_KEY], thumb)
250 if (os.path.exists (thumb)):
251 self.album_art.set_from_file (thumb)
254 self.album_callback_id = gobject.idle_add (self.retrieve_album_art,
255 song[ARTIST_KEY], song[ALBUM_KEY])
258 self.album_art.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
260 if (not song[MIME_KEY] in self.writer.get_supported_mimes ()):
261 print "show notification"
262 self.banner = hildon.Banner ()
263 self.banner.set_text ("Unsupported format (%s)" % song[MIME_KEY])
264 self.banner.show_all ()
266 def retrieve_album_art (self, artist, album):
267 print "trying to get the album art"
268 (img, thumb) = self.album_art_retriever.get_album_art (artist, album)
270 self.album_art.set_from_file (thumb)
272 print "Unable to retrieve album art"
276 def clicked_play (self, widget):
277 if (self.player.is_playing ()):
280 song = self.songs_list [self.song_counter]
281 self.player.play ("file://" + song[FILE_URI])
283 def clicked_album_art (self, widget):
284 print "implement me, please"
286 def album_selection_cb (self, widget):
288 On album change, add the album the local list of albums and the selector
289 if it doesn't exist already. So we show the new entry in the selector next time.
291 song = self.songs_list [self.song_counter]
292 if (not widget.get_value () in self.albums_list):
293 print "Inserting ", widget.get_value ()
294 widget.get_selector ().prepend_text (widget.get_value ())
295 self.albums_list.insert (0, widget.get_value ())
296 self.retrieve_album_art (song[ARTIST_KEY], widget.get_value ())
298 def artist_selection_cb (self, widget):
300 On artist change, add the artist the local list of artists and the selector
301 if it doesn't exist already. So we show the new entry in the selector next time
303 song = self.songs_list [self.song_counter]
304 if (not widget.get_value () in self.artists_list):
305 print "Inserting artist", widget.get_value ()
306 widget.get_selector ().prepend_text (widget.get_value ())
307 self.artists_list.insert (0, widget.get_value ())
310 if __name__ == "__main__":
312 TEST_DATA = [("/home/user/Music/dylan.mp3", "Music", "Bob Dylan", "Subterranean homesick blues", "Bring it all back home", "audio/mpeg"),
313 ("/home/user/mufix/a.mp3", "Music", "", "title", "Album 2", "a/b"),
314 ("/media/mmc1/Attachments/b.m4a", "Music", "", "b", "Album 9", "audio/mpeg"),
315 ("/home/user/mufix/3.mp2", "Music", "", "titlex", "Album 3", "audio/mpeg")]
317 ALBUMS = [["Album %d" % i] for i in range (0, 10)] + [["Bring it all back home"]]
318 ARTISTS = [["Artist %d" % i] for i in range (0, 10)] + [["Bob Dylan"]]
319 window = MussorgskyEditPanel (TEST_DATA, ALBUMS, ARTISTS)
320 window.connect ("destroy", gtk.main_quit)