Pulse progressbar.
[gmpc.git] / src / vala / gmpc-metadata-editwindow.vala
blobfdcee304e5ea58ddf67ff883925b5c1b619fad85
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 using Config;
21 using Gtk;
22 using Gmpc;
24 private const bool use_transition_tp = Gmpc.use_transition;
26 public class Gmpc.MetaData.EditWindow : Gtk.Window
28 private const string some_unique_name = Config.VERSION;
29 private MPD.Song? song = null;
30 private Gmpc.MetaData.Type query_type = Gmpc.MetaData.Type.ALBUM_ART;
32 private GLib.List<unowned Gmpc.AsyncDownload.Handle> downloads = null;
33 /** fetching handles */
34 private void *handle = null;
35 private void *handle2 = null;
37 private Gtk.HBox pbox = null;
38 private Gtk.Label warning_label = null;
39 private Gtk.Entry artist_entry;
40 private Gtk.Entry album_entry;
41 private Gtk.Entry title_entry;
42 private Gtk.Button cancel = null;
43 private Gtk.Button refresh = null;
44 private Gtk.ComboBox combo = null;
45 private Gtk.ProgressBar bar = null;
47 private uint pulse_callback = 0;
50 private Gtk.ScrolledWindow sw = null;
51 private Gtk.EventBox ilevent = null;
53 private Gtk.VBox itemslist = new Gtk.VBox(false, 6);
55 construct
57 this.type = Gtk.WindowType.TOPLEVEL;
58 int height = config.get_int_with_default(
59 "Metadata Selector" , "window_height", 600);
60 int width = config.get_int_with_default(
61 "Metadata Selector" , "window_width", 480);
63 this.resize(width,height);
64 this.set_border_width(8);
65 /* Connect to allocation changes so I can store new size */
66 this.size_allocate.connect((source, alloc) => {
67 config.set_int(
68 "Metadata Selector" , "window_width", alloc.width);
70 config.set_int(
71 "Metadata Selector" , "window_height", alloc.height);
72 });
75 private void add_entry_image(Gmpc.MetaData.Item met, string? provider, string uri,Gdk.PixbufFormat? format, Gdk.Pixbuf pb, bool is_raw = false, bool is_thumbnail = false)
77 string a;
78 a = "";// Markup.printf_escaped("<b>%s</b>: %s",_("Uri"),uri);
79 if(provider != null)
81 a+= Markup.printf_escaped("\n<b>%s</b>: %s",_("Provider"), provider);
83 if(format != null)
85 a+= Markup.printf_escaped("\n<b>%s</b>: %s",_("Filetype"), format.get_name());
87 if(pb != null)
89 if(is_thumbnail)
91 a+="\n<b>%s</b>: %ix%i (%s) (%s)".printf(_("Size"), pb.width, pb.height,_("width x height"),
92 _("high-res image will be downloaded"));
94 else
96 a+="\n<b>%s</b>: %ix%i (%s)".printf(_("Size"), pb.width, pb.height,_("width x height"));
100 int new_h, new_w;
101 if(pb.width < pb.height)
103 new_h = 150;
104 new_w = (int)((150.0/(double)pb.height)*pb.width);
106 else
108 new_w = 150;
109 new_h = (int)((150.0/(double)pb.width)*pb.height);
113 var hbox = new Gtk.HBox(false, 6);
114 var label = new Gtk.Label("");
115 label.set_ellipsize(Pango.EllipsizeMode.MIDDLE);
116 label.set_markup(a);
117 label.set_line_wrap(true);
118 label.set_alignment(0.0f, 0.5f);
120 var image = new Gtk.Image.from_pixbuf(pb.scale_simple(new_w,new_h,Gdk.InterpType.BILINEAR));
121 image.set_size_request(180,-1);
122 hbox.pack_start(image, false, true, 0);
123 hbox.pack_start(label, true, true, 0);
126 var ali = new Gtk.Alignment(0f,0f,0f,0f);
127 var button = new Gtk.Button.with_label(_("Set"));
129 button.set_data<Gmpc.MetaData.Item>("metadata", met.dup());
130 ali.add(button);
131 hbox.pack_start(ali, false, true, 0);
132 button.clicked.connect(set_metadata);
134 hbox.show_all();
135 this.itemslist.pack_start(hbox,false, true, 0);
136 var sep = new Gtk.HSeparator();
137 sep.set_size_request(-1, 4);
138 sep.show();
139 this.itemslist.pack_start(sep, false, true, 0);
143 private void add_entry_text(MetaData.Item item, string? provider, string uri,string text)
145 string a;
146 a = "";// "<b>%s</b>: %s".printf(_("Uri"),uri);
147 if(provider != null)
149 a+="\n<b>%s</b>: %s".printf(_("Provider"), provider);
151 var hbox = new Gtk.HBox(false, 6);
152 var label = new Gtk.Label("");
153 label.set_markup(a);
154 label.set_ellipsize(Pango.EllipsizeMode.MIDDLE);
155 label.set_line_wrap(true);
156 label.set_alignment(0.0f, 0.0f);
157 label.set_size_request(280,-1);
158 hbox.pack_start(label, false, true, 0);
160 var text_label = new Gtk.Label(text);
161 text_label.set_ellipsize(Pango.EllipsizeMode.END);
162 text_label.set_alignment(0.0f, 0.0f);
163 text_label.set_size_request(180,-1);
164 hbox.pack_start(text_label, true, true, 0);
166 var ali = new Gtk.Alignment(0f,0f,0f,0f);
167 var button = new Gtk.Button.with_label(_("Set"));
168 button.set_data("lyrics",text);
169 button.set_data<MetaData.Item>("metadata", item.dup());
172 ali.add(button);
173 hbox.pack_start(ali, false, true, 0);
174 button.clicked.connect(set_metadata);
176 hbox.show_all();
177 this.itemslist.pack_start(hbox,false, true, 0);
178 var sep = new Gtk.HSeparator();
179 sep.set_size_request(-1, 4);
180 sep.show();
181 this.itemslist.pack_start(sep, false, true, 0);
184 public void callback(void *handle,string? plugin_name,GLib.List<MetaData.Item>? list)
186 stdout.printf("result callback\n");
187 bar.pulse();
188 if(list == null)
190 if(this.handle == handle)
192 this.handle = null;
193 if(this.handle == null && this.downloads == null)
195 this.pbox.hide();
196 if(this.pulse_callback > 0){
197 GLib.Source.remove(this.pulse_callback );
198 this.pulse_callback = 0;
200 this.refresh.sensitive = true;
201 this.ilevent.sensitive = true;
202 this.combo.sensitive = true;
205 if(this.handle2 == handle)
207 this.handle2 = null;
210 if(this.handle == null && this.downloads == null)
212 this.pbox.hide();
213 if(this.pulse_callback > 0){
214 GLib.Source.remove(this.pulse_callback);
215 this.pulse_callback = 0;
217 this.combo.sensitive = true;
218 this.ilevent.sensitive = true;
219 this.refresh.sensitive = true;
223 foreach(unowned MetaData.Item md in list)
226 if(this.query_type == Gmpc.MetaData.Type.ALBUM_ART || this.query_type == Gmpc.MetaData.Type.ARTIST_ART ||
227 this.query_type == Gmpc.MetaData.Type.BACKDROP_ART)
229 if (md.content_type == Gmpc.MetaData.ContentType.RAW)
231 var data = md.get_raw();
232 var load = new Gdk.PixbufLoader();
235 load.write(data);
237 catch (Error e)
239 GLib.debug("Failed to load raw data: %s\n",e.message);
243 load.close();
245 catch (Error e)
247 GLib.debug("Failed to close loader: %s\n",e.message);
250 Gdk.Pixbuf pb = load.get_pixbuf();
251 if(pb!= null)
253 var base16 = GLib.Base64.encode(data);
254 this.add_entry_image(md, md.plugin_name,base16,load.get_format(),pb,true);
258 else
261 if(md.content_type == Gmpc.MetaData.ContentType.TEXT)
263 unowned string uri = md.get_text();
264 add_entry_text(md, md.plugin_name, "n/a", uri);
266 else if(md.content_type == Gmpc.MetaData.ContentType.HTML)
268 string uri = md.get_text_from_html();
269 add_entry_text(md, md.plugin_name, "n/a", uri);
271 else if(md.content_type == Gmpc.MetaData.ContentType.URI)
273 unowned string uri = md.get_uri();
274 if(uri[0] == '/')
278 string content;
279 if(GLib.FileUtils.get_contents(uri,out content))
281 add_entry_text(md, md.plugin_name,uri, content);
284 catch (Error e)
296 private void
297 set_metadata(Gtk.Button button)
299 unowned MetaData.Item? item = button.get_data<MetaData.Item>("metadata");
300 if(item != null)
302 Gmpc.MetaData.set_metadata(this.song, item);
305 public
306 void
307 destroy_popup(Gtk.Button button)
309 this.destroy();
311 private void clear_itemslist()
313 foreach(Gtk.Widget client in this.itemslist.get_children())
315 client.destroy();
319 public void refresh_query(Gtk.Button button)
321 clear_itemslist();
322 GLib.log("MetadataSelector", GLib.LogLevelFlags.LEVEL_DEBUG, "Query metadata");
323 MPD.Song ss = this.song.copy();
324 ss.artist = this.artist_entry.get_text();
325 ss.album = this.album_entry.get_text();
326 ss.title = this.title_entry.get_text();
328 if(this.handle == null && this.handle2 == null)
330 this.pbox.show();
331 if(this.pulse_callback > 0){
332 GLib.Source.remove(this.pulse_callback);
333 this.pulse_callback = 0;
335 this.pulse_callback = GLib.Timeout.add(300, () => {
336 if(this.bar == null) return false;
337 this.bar.pulse();
338 return true;
340 this.refresh.sensitive = false;
341 this.combo.sensitive = false;
342 this.ilevent.sensitive = false;
343 GLib.log("MetadataSelector", GLib.LogLevelFlags.LEVEL_DEBUG,"Start metdata get_list query");
344 this.handle = Gmpc.MetaData.get_list(ss, this.query_type, callback);
345 GLib.log("MetadataSelector", GLib.LogLevelFlags.LEVEL_DEBUG,"Wait");
349 private void combo_box_changed(Gtk.ComboBox comb)
351 clear_itemslist();
352 int active = comb.active;
353 this.title_entry.sensitive = false;
354 this.album_entry.sensitive = false;
355 this.artist_entry.sensitive = false;
356 this.refresh.sensitive = false;
357 this.warning_label.hide();
358 if(active == 0)
360 this.query_type = Gmpc.MetaData.Type.ARTIST_ART;
361 if(this.song.artist != null)
363 this.artist_entry.sensitive = true;
364 this.refresh.sensitive = true;
366 else this.warning_label.show();
368 else if (active == 1)
370 this.query_type = Gmpc.MetaData.Type.ALBUM_ART;
372 if(this.song.artist != null && this.song.album != null)
374 this.artist_entry.sensitive = true;
375 this.album_entry.sensitive = true;
376 this.refresh.sensitive = true;
378 else this.warning_label.show();
380 else if (active == 2)
382 this.query_type = Gmpc.MetaData.Type.SONG_TXT;
384 if(this.song.artist != null && this.song.title != null)
386 this.artist_entry.sensitive = true;
387 this.title_entry.sensitive = true;
388 this.refresh.sensitive = true;
390 else this.warning_label.show();
392 else if (active == 3)
394 this.query_type = Gmpc.MetaData.Type.ALBUM_TXT;
396 if(this.song.artist != null && this.song.album != null)
398 this.artist_entry.sensitive = true;
399 this.album_entry.sensitive = true;
400 this.refresh.sensitive = true;
402 else this.warning_label.show();
404 else if (active == 4)
406 this.query_type = Gmpc.MetaData.Type.ARTIST_TXT;
408 if(this.song.artist != null)
410 this.artist_entry.sensitive = true;
411 this.refresh.sensitive = true;
413 else this.warning_label.show();
415 else if (active == 5)
417 this.query_type = Gmpc.MetaData.Type.SONG_GUITAR_TAB;
419 if(this.song.artist != null && this.song.title != null)
421 this.artist_entry.sensitive = true;
422 this.title_entry.sensitive = true;
423 this.refresh.sensitive = true;
425 else this.warning_label.show();
427 else if ( active == 6)
429 this.query_type = Gmpc.MetaData.Type.BACKDROP_ART;
430 if(this.song.artist != null)
432 this.artist_entry.sensitive = true;
433 this.refresh.sensitive = true;
435 else this.warning_label.show();
439 public
440 EditWindow (MPD.Song song, Gmpc.MetaData.Type type)
442 var vbox = new Gtk.VBox(false, 6);
443 this.song = song.copy();
444 this.query_type = type;
445 this.pbox = new Gtk.HBox(false, 6);
446 this.bar = new Gtk.ProgressBar();
447 vbox.pack_start(this.pbox, false, false, 0);
448 this.cancel = new Gtk.Button.from_stock("gtk-cancel");
449 this.cancel.clicked.connect(this.b_cancel);
450 this.pbox.pack_start(this.bar, true, true, 0);
451 this.pbox.pack_start(this.cancel, false, false, 0);
452 this.bar.show();
453 this.cancel.show();
454 this.pbox.no_show_all = true;
455 this.pbox.hide();
456 if(this.pulse_callback > 0){
457 GLib.Source.remove(this.pulse_callback);
458 this.pulse_callback = 0;
461 sw = new Gtk.ScrolledWindow(null, null);
463 sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
464 sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN);
467 /* Button */
468 var hbox = new Gtk.HBox(false, 6);
470 var button = new Gtk.Button.from_stock("gtk-quit");
471 button.clicked.connect(destroy_popup);
472 hbox.pack_end(button, false, false, 0);
473 vbox.pack_end(hbox, false, false,0);
475 /** Change */
476 this.warning_label = new Gtk.Label("");
477 this.warning_label.set_markup("<span size='x-large'>%s</span>".printf(_("Insufficient information to store/fetch this metadata")));
478 this.warning_label.set_alignment(0.0f, 0.5f);
479 vbox.pack_start(this.warning_label, false, false, 0);
480 this.warning_label.hide();
482 var group = new Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL);
483 var qhbox = new Gtk.HBox(false, 6);
484 Gtk.Label label = null;
486 var list = new Gtk.ListStore(2,typeof(string), typeof(string),-1);
487 list.insert_with_values(null, -1, 0, "media-artist", 1, _("Artist art"));
488 list.insert_with_values(null, -1, 0, "media-album", 1, _("Album art"));
489 list.insert_with_values(null, -1, 0, "gtk-dnd", 1, _("Song lyrics"));
490 list.insert_with_values(null, -1, 0, "media-album", 1, _("Album Info"));
491 list.insert_with_values(null, -1, 0, "media-artist", 1, _("Artist Biography"));
492 list.insert_with_values(null, -1, 0, "media-album", 1, _("Guitar Tab"));
493 list.insert_with_values(null, -1, 0, "media-artist", 1, _("Backdrop"));
495 this.combo = new Gtk.ComboBox.with_model(list);
497 Gtk.CellRenderer renderer = new Gtk.CellRendererPixbuf();
498 this.combo.pack_start(renderer,false);
499 this.combo.add_attribute(renderer, "icon-name", 0);
500 renderer = new Gtk.CellRendererText();
501 this.combo.pack_start(renderer,true);
502 this.combo.add_attribute(renderer, "text", 1);
504 qhbox.pack_start(this.combo, true,true,0);
505 this.combo.changed.connect(combo_box_changed);
507 vbox.pack_start(qhbox, false, false, 0);
510 qhbox = new Gtk.HBox(false, 6);
512 label = new Gtk.Label(_("Artist"));
513 label.set_alignment(0.0f, 0.5f);
514 group.add_widget(label);
515 qhbox.pack_start(label, false, false, 0);
516 var image = new Gtk.Image.from_icon_name("media-artist", Gtk.IconSize.BUTTON);
517 qhbox.pack_start(image, false, false, 0);
519 this.artist_entry = new Gtk.Entry();
520 this.artist_entry.set_text(song.artist);
521 qhbox.pack_start(this.artist_entry, true, true, 0);
522 vbox.pack_start(qhbox, false, false, 0);
524 qhbox = new Gtk.HBox(false, 6);
525 label = new Gtk.Label(_("Album"));
526 label.set_alignment(0.0f, 0.5f);
527 group.add_widget(label);
528 qhbox.pack_start(label, false, false, 0);
529 image = new Gtk.Image.from_icon_name("media-album", Gtk.IconSize.BUTTON);
530 qhbox.pack_start(image, false, false, 0);
531 this.album_entry = new Gtk.Entry();
532 if(song.album != null)
533 this.album_entry.set_text(song.album);
534 qhbox.pack_start(this.album_entry, true, true, 0);
535 vbox.pack_start(qhbox, false, false, 0);
537 qhbox = new Gtk.HBox(false, 6);
538 label = new Gtk.Label(_("Title"));
539 label.set_alignment(0.0f, 0.5f);
540 group.add_widget(label);
541 qhbox.pack_start(label, false, false, 0);
542 image = new Gtk.Image.from_icon_name("media-audiofile", Gtk.IconSize.BUTTON);
543 qhbox.pack_start(image, false, false, 0);
544 this.title_entry = new Gtk.Entry();
545 if(song.title != null)
546 this.title_entry.set_text(song.title);
547 qhbox.pack_start(this.title_entry, true, true, 0);
549 vbox.pack_start(qhbox, false, false, 0);
551 if(type != Gmpc.MetaData.Type.ALBUM_ART || type != Gmpc.MetaData.Type.BACKDROP_ART)
552 this.album_entry.sensitive = false;
555 this.refresh = button = new Gtk.Button.with_label(_("Query"));
556 var ali = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f);
557 ali.add(button);
558 vbox.pack_start(ali, false, false, 0);
559 button.clicked.connect(refresh_query);
563 vbox.pack_start(sw, true, true,0);
564 this.add(vbox);
565 this.hide_on_delete();
566 //sw.add(iv);
567 ilevent = new Gtk.EventBox();
568 this.itemslist.border_width = 8;
569 ilevent.visible_window = true;
570 ilevent.modify_bg(Gtk.StateType.NORMAL,this.style.base[Gtk.StateType.NORMAL]);
571 this.style_set.connect((source, old) =>
573 this.itemslist.get_parent().modify_bg(Gtk.StateType.NORMAL,this.style.base[Gtk.StateType.NORMAL]);
575 ilevent.add(itemslist);
576 sw.add_with_viewport(ilevent);
577 this.show_all();
579 if(type == Gmpc.MetaData.Type.ARTIST_ART) this.combo.set_active(0);
580 else if(type == Gmpc.MetaData.Type.ALBUM_ART) this.combo.set_active(1);
581 else if(type == Gmpc.MetaData.Type.SONG_TXT) this.combo.set_active(2);
582 else if(type == Gmpc.MetaData.Type.ALBUM_TXT) this.combo.set_active(3);
583 else if(type == Gmpc.MetaData.Type.ARTIST_TXT)this.combo.set_active(4);
584 else if(type == Gmpc.MetaData.Type.SONG_GUITAR_TAB)this.combo.set_active(5);
585 else if(type == Gmpc.MetaData.Type.BACKDROP_ART)this.combo.set_active(6);
587 refresh_query(button);
589 public void b_cancel()
591 if(this.handle != null)
593 Gmpc.MetaData.get_list_cancel(this.handle);
594 this.handle = null;
596 if(this.handle2 != null)
598 Gmpc.MetaData.get_list_cancel(this.handle2);
599 this.handle2 = null;
601 this.downloads.first();
602 while(this.downloads != null)
604 unowned Gmpc.AsyncDownload.Handle handle = this.downloads.data;
606 handle.cancel();
607 this.downloads.first();
610 this.pbox.hide();
611 if(this.pulse_callback > 0){
612 GLib.Source.remove(this.pulse_callback );
613 this.pulse_callback = 0;
615 this.refresh.sensitive = true;
616 this.combo.sensitive = true;
618 ~EditWindow()
620 this.b_cancel();