Also show artist less albums
[gmpc-albumview.git] / src / plugin.c
blobf35a46a88c277b5ac9552770cf25ffda91322bd4
1 #include <gtk/gtk.h>
2 #include <gmpc/plugin.h>
3 #include <gmpc/playlist3-messages.h>
4 #include <gmpc/gmpc-metaimage.h>
5 #include <gmpc/misc.h>
6 #include <libmpd/libmpd-internal.h>
7 #include <config.h>
8 #include <math.h>
9 #include "exo-wrap-table.h"
10 #include "plugin.h"
12 #define AV_LOG_DOMAIN "AlbumViewPlugin"
14 static gchar * albumview_format_time(unsigned long seconds);
15 static void albumview_browser_save_myself(void);
16 /* Allow gmpc to check the version the plugin is compiled against */
17 int plugin_api_version = PLUGIN_API_VERSION;
18 GtkTreeModel *albumview_model = NULL;
20 static void position_changed(GtkRange *range, gpointer data);
21 void update_view(void);
22 /**
23 * Browser extention
25 gmpcPlBrowserPlugin albumview_gbp = {
26 /** add */
27 .add = albumview_add,
28 /** selected */
29 .selected = albumview_selected,
30 /** unselected */
31 .unselected = albumview_unselected,
35 /**
36 * Define the plugin structure
38 gmpcPlugin plugin = {
39 /* name */
40 .name = "Album View",
41 /* version */
42 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
43 /* type */
44 .plugin_type = GMPC_PLUGIN_PL_BROWSER,
45 /* init function */
46 .init = albumview_plugin_init,
47 /** playlist extention struct */
48 .browser = &albumview_gbp,
49 /** Connection changed */
50 .mpd_connection_changed = albumview_connection_changed,
51 /** enable/disable */
52 .get_enabled = albumview_get_enabled,
53 .set_enabled = albumview_set_enabled,
54 /* Safe myself */
55 .save_yourself = albumview_browser_save_myself
58 static GtkTreeRowReference *albumview_ref = NULL;
59 static GtkWidget *albumview_vbox= NULL, *albumview_tree = NULL,*albumview_combo = NULL;
60 static gboolean cancel_query = FALSE;
61 /**
62 * Get/Set enable
65 int albumview_get_enabled(void)
67 return cfg_get_single_value_as_int_with_default(config, "albumview", "enable", TRUE);
70 void albumview_set_enabled(int enabled)
72 cfg_set_single_value_as_int(config, "albumview", "enable", enabled);
73 if(enabled)
75 if(albumview_ref == NULL)
77 albumview_add(GTK_WIDGET(playlist3_get_category_tree_view()));
80 else
82 GtkTreePath *path = gtk_tree_row_reference_get_path(albumview_ref);
83 GtkTreeModel *model = gtk_tree_row_reference_get_model(albumview_ref);
84 if (path){
85 GtkTreeIter iter;
86 if (gtk_tree_model_get_iter(model, &iter, path)){
87 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
89 gtk_tree_path_free(path);
90 gtk_tree_row_reference_free(albumview_ref);
91 albumview_ref = NULL;
96 /**
97 * Playlist browser functions
99 static void albumview_add(GtkWidget *category_tree)
101 GtkTreePath *path;
102 GtkTreeModel *model = GTK_TREE_MODEL(playlist3_get_category_tree_store());
103 GtkTreeIter iter;
104 gint pos;
106 * don't do anything if we are disabled
108 if(!cfg_get_single_value_as_int_with_default(config, "albumview", "enable", TRUE)) return;
109 /**
110 * Add ourslef to the list
112 pos = cfg_get_single_value_as_int_with_default(config, "albumview","position",2);
113 playlist3_insert_browser(&iter, pos);
114 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
115 PL3_CAT_TYPE, plugin.id,
116 PL3_CAT_TITLE,"Album View",
117 PL3_CAT_ICON_ID, "gtk-open",
118 -1);
119 /**
120 * remove odl reference if exists
122 if (albumview_ref) {
123 gtk_tree_row_reference_free(albumview_ref);
124 albumview_ref = NULL;
127 * create reference to ourself in the list
129 path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter);
130 if (path) {
131 albumview_ref = gtk_tree_row_reference_new(model, path);
132 gtk_tree_path_free(path);
135 static void albumview_browser_save_myself(void)
137 if(albumview_ref)
139 GtkTreePath *path = gtk_tree_row_reference_get_path(albumview_ref);
140 if(path)
142 gint *indices = gtk_tree_path_get_indices(path);
143 debug_printf(DEBUG_INFO,"Saving myself to position: %i\n", indices[0]);
144 cfg_set_single_value_as_int(config, "albumview","position",indices[0]);
145 gtk_tree_path_free(path);
150 GtkWidget *entry = NULL;
151 int album_size = 200;
152 int supported_columns = 1;
153 void size_changed(GtkWidget *widget, GtkAllocation *alloc)
155 int columns = (alloc->width-20)/(album_size +25);
156 if(columns != supported_columns)
158 supported_columns = columns;
159 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "update columns: %i %i %i\n", alloc->width-20,columns, album_size);
160 if(entry && GTK_WIDGET_IS_SENSITIVE(entry))
162 update_view();
166 void album_size_changed(GtkRange *spin)
168 int new_size = ((int)gtk_range_get_value(spin))*20;
169 if(new_size != album_size) {
170 album_size = new_size;
171 size_changed(albumview_vbox, &(albumview_vbox->allocation));
173 if(entry && GTK_WIDGET_IS_SENSITIVE(entry))
175 update_view();
179 cfg_set_single_value_as_int(config, "albumview", "zoom-level", (int)gtk_range_get_value(spin));
181 static gboolean expose_event(GtkWidget *wid, GdkEventExpose *event, gpointer data)
183 /* TODO improve this, somehow applying the clipmask fail. */
184 int offset = ((event->area.y)%(album_size+40));
185 int step = (album_size +40)- offset;
186 int start = event->area.y;
187 int flip = ((int)(event->area.y+step-5)/(album_size+40))&1;
188 int stop = event->area.y+event->area.height;
189 cairo_t *cc = gdk_cairo_create(GTK_WIDGET(wid)->window);
191 if(flip)
192 cairo_set_source_rgba(cc, 1.0,1.0,1.0,1.0);
193 else
194 cairo_set_source_rgba(cc, 0.8,0.8,0.8,1.0);
195 cairo_rectangle(cc, 0, start, wid->allocation.width,step );
196 cairo_fill(cc);
197 start += step;
198 step = album_size+40;
199 flip = (flip == 1)?0:1;
200 }while(start<stop);
201 cairo_destroy(cc);
202 return FALSE;
204 static GtkWidget *hscale = NULL;
205 static void albumview_init()
207 /** Get an allready exposed widgets to grab theme colors from. */
208 GtkWidget *colw = (GtkWidget *)playlist3_get_category_tree_view();
209 GtkWidget *label = NULL;
210 GtkWidget *event = gtk_event_box_new();//(NULL, NULL);//gtk_event_box_new();
211 int i = 0;
212 albumview_vbox = gtk_vbox_new(FALSE, 0);
214 album_size = 20*cfg_get_single_value_as_int_with_default(config, "albumview", "zoom-level", 10);
215 g_signal_connect(G_OBJECT(albumview_vbox), "size-allocate", G_CALLBACK(size_changed), NULL);
217 GtkWidget *sw = gtk_hbox_new(FALSE, 6);//gtk_scrolled_window_new(NULL, NULL);
218 GtkWidget *iv = albumview_tree = gtk_vbox_new(FALSE, 6);
219 hscale = gtk_hscale_new_with_range(0,1,1);
220 g_signal_connect(G_OBJECT(hscale), "value-changed", G_CALLBACK(position_changed), NULL);
222 entry = gtk_entry_new();
223 gtk_box_pack_start(GTK_BOX(albumview_vbox), entry, FALSE, FALSE, 0);
224 g_signal_connect(G_OBJECT(entry),"changed", G_CALLBACK(update_view), NULL);
226 GtkWidget *spin= gtk_hscale_new_with_range(1, 12, 1);
227 gtk_scale_set_draw_value(GTK_SCALE(spin), FALSE);
228 gtk_range_set_value(GTK_RANGE(spin), album_size);
229 gtk_box_pack_start(GTK_BOX(albumview_vbox), spin, FALSE, FALSE, 0);
231 #if GTK_CHECK_VERSION(2,16,0)
232 for(i=1; i<13;i++){
233 gtk_scale_add_mark(GTK_SCALE(spin), (gdouble)i,GTK_POS_TOP, NULL);
235 #endif
237 gtk_range_set_value(GTK_RANGE(spin), cfg_get_single_value_as_int_with_default(config, "albumview", "zoom-level", 10));
238 g_signal_connect(G_OBJECT(spin), "value-changed", G_CALLBACK(album_size_changed), NULL);
241 gtk_box_pack_start(GTK_BOX(albumview_vbox),sw, TRUE, TRUE, 0);
242 gtk_widget_modify_bg(event, GTK_STATE_NORMAL,&(albumview_vbox->style->white));
243 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), TRUE);
244 gtk_widget_set_app_paintable(GTK_WIDGET(event),TRUE);
245 g_signal_connect(G_OBJECT(event), "expose-event", G_CALLBACK(expose_event), NULL);
247 gtk_box_pack_start(GTK_BOX(sw),event, TRUE, TRUE, 0);//gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), event);
248 gtk_box_pack_start(GTK_BOX(albumview_vbox),hscale, FALSE, FALSE, 0);//gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), event);
249 // gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
250 gtk_container_add(GTK_CONTAINER(event), iv);
252 gtk_widget_show_all(albumview_vbox);
253 /* maintain my own reference to the widget, so it won't get destroyed removing
254 * from view
256 g_object_ref(albumview_vbox);
260 static void albumview_selected(GtkWidget *container)
262 if(albumview_vbox== NULL) {
263 albumview_init();
264 albumview_connection_changed(connection,1,NULL);
266 gtk_container_add(GTK_CONTAINER(container), albumview_vbox);
267 gtk_widget_show(albumview_vbox);
270 static void albumview_unselected(GtkWidget *container)
272 gtk_container_remove(GTK_CONTAINER(container), albumview_vbox);
277 void albumview_plugin_init(void)
279 gchar *path = gmpc_plugin_get_data_path(&plugin);
280 gchar *url = g_build_path(G_DIR_SEPARATOR_S,path, "albumview", NULL);
281 debug_printf(DEBUG_WARNING,"Found url: %s\n", url);
284 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),url);
286 g_free(path);
287 g_free(url);
289 #define TIMER_SUB(start,stop,diff) diff.tv_usec = stop.tv_usec - start.tv_usec;\
290 diff.tv_sec = stop.tv_sec - start.tv_sec;\
291 if(diff.tv_usec < 0) {\
292 diff.tv_sec -= 1; \
293 diff.tv_usec += G_USEC_PER_SEC; \
295 static gint __add_sort(gpointer aa, gpointer bb, gpointer data)
297 MpdData_real *a = *(MpdData_real **)aa;
298 MpdData_real *b = *(MpdData_real **)bb;
299 if(!a || !b) return 0;
300 if(a->type == MPD_DATA_TYPE_SONG && b->type == MPD_DATA_TYPE_SONG)
302 if(a->song->artist && b->song->artist)
304 int val;
306 gchar *sa,*sb;
307 sa = g_utf8_strdown(a->song->artist, -1);
308 sb = g_utf8_strdown(b->song->artist, -1);
309 val = g_utf8_collate(sa,sb);
310 g_free(sa);
311 g_free(sb);
312 }/* else {
313 val = (a == NULL)?((b==NULL)?0:-1):1;
315 return val;
318 return -1;
320 MpdData *complete_list = NULL;
321 GtkWidget *pb;
322 int max = 0, current = 0;
324 static gboolean load_list_itterate(MpdData *data)
326 MpdData *data2 = NULL;
327 current++;
328 if(max>0 && current%25 == 0){
329 gchar *temp = g_strdup_printf("%i of %i albums loaded", current, max);
330 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb), current/(double)max);
331 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pb), temp);
332 g_free(temp);
335 if(data)
337 mpd_database_search_field_start(connection, MPD_TAG_ITEM_ARTIST);
338 mpd_database_search_add_constraint(connection, MPD_TAG_ITEM_ALBUM, (data)->tag);
339 data2 = mpd_database_search_commit(connection);
340 if(data2)
342 mpd_Song *song = mpd_newSong();
343 song->album = g_strdup((data)->tag);
344 song->artist = g_strdup(data2->tag);
345 if(!mpd_data_is_last(data2))
347 /* test if server supports album artist */
348 if(mpd_server_tag_supported(connection, MPD_TAG_ITEM_ALBUM_ARTIST))
350 mpd_database_search_field_start(connection, MPD_TAG_ITEM_ALBUM_ARTIST);
351 mpd_database_search_add_constraint(connection, MPD_TAG_ITEM_ALBUM, (data)->tag);
352 MpdData *data3 = mpd_database_search_commit(connection);
353 if(mpd_data_is_last(data3)){
354 song->albumartist = g_strdup(data3->tag);
356 else{
357 mpd_freeSong(song);
358 song = NULL;
360 mpd_data_free(data3);
362 else {
363 mpd_freeSong(song);
364 song = NULL;
367 mpd_data_free(data2);
368 if(song){
369 complete_list = mpd_new_data_struct_append(complete_list);
370 complete_list->song = song;
371 complete_list->type = MPD_DATA_TYPE_SONG;
372 song = NULL;
376 (data) = mpd_data_get_next((data));
378 if(data == NULL){
379 int items = 0;
380 MpdData_real *iter;
381 complete_list = (MpdData *)misc_sort_mpddata(mpd_data_get_first(complete_list), (GCompareDataFunc)__add_sort, NULL);
382 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"update view\n");
383 gtk_widget_destroy(pb);
384 for(iter = (MpdData_real*)complete_list; iter; iter = iter->next) items++;
385 gtk_range_set_range(GTK_RANGE(hscale), 0, items);
386 gtk_range_set_value(GTK_RANGE(hscale), 0);
387 update_view();
389 gtk_widget_set_sensitive(entry, TRUE);
390 return FALSE;
393 g_idle_add((GSourceFunc)load_list_itterate, data);
394 return FALSE;
397 static GtkWidget *table = NULL;
398 static void load_list(void)
400 if(complete_list)mpd_data_free(complete_list);
401 complete_list = NULL;
403 pb = gtk_progress_bar_new();
404 gtk_box_pack_start(GTK_BOX(albumview_tree), pb, FALSE, FALSE, 0);
405 gtk_widget_show_all(albumview_tree);
406 mpd_database_search_field_start(connection, MPD_TAG_ITEM_ALBUM);
407 MpdData *iter,*data = mpd_database_search_commit(connection);
408 max = 0;
409 current = 0;
410 gtk_widget_set_sensitive(entry, FALSE);
411 for(iter = data; iter; iter = mpd_data_get_next_real(iter, FALSE)) max++;
412 g_idle_add((GSourceFunc)load_list_itterate, data);
414 void albumview_connection_changed(MpdObj *mi, int connect,void *usedata)
417 if(connect && albumview_vbox)
419 load_list();
421 else if(albumview_vbox){
422 mpd_data_free(complete_list);
423 complete_list = NULL;
426 static void album_add(GtkWidget *button, mpd_Song *song)
428 mpd_database_search_start(connection,TRUE);
430 mpd_database_search_add_constraint(connection, MPD_TAG_ITEM_ALBUM, song->album);
431 if(song->albumartist && strlen(song->albumartist) >0){
432 mpd_database_search_add_constraint(connection, MPD_TAG_ITEM_ALBUM_ARTIST, song->albumartist);
433 }else{
434 mpd_database_search_add_constraint(connection, MPD_TAG_ITEM_ARTIST, song->artist);
436 MpdData *data = mpd_database_search_commit(connection);
437 for(;data;data = mpd_data_get_next(data)){
438 mpd_playlist_queue_add(connection, data->song->file);
440 mpd_playlist_queue_commit(connection);
442 static void album_view(GtkWidget *button ,mpd_Song *song)
444 if (song && song->artist && song->album) {
445 info2_activate();
446 info2_fill_album_view(song->artist, song->album);
450 static void album_replace(GtkWidget *button, mpd_Song *song)
452 mpd_playlist_clear(connection);
453 album_add(button, song);
454 mpd_player_play(connection);
456 static gboolean album_button_press(GtkWidget *item, GdkEventButton *event, mpd_Song *song)
458 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "button press event %i\n", event->button);
459 if(event->button == 1 && event->type == GDK_BUTTON_PRESS)
461 GtkWidget *menu = gtk_menu_new();
462 GtkWidget *item;
464 item = gtk_image_menu_item_new_with_label("Album information");
465 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
466 gtk_image_new_from_stock(GTK_STOCK_INFO, GTK_ICON_SIZE_MENU));
467 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
468 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(album_view), song);
470 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
471 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
472 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(album_add), song);
474 /* replace the replace widget */
475 item = gtk_image_menu_item_new_with_label("Replace");
476 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
477 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
478 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
479 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(album_replace), song);
480 gtk_widget_show_all(menu);
481 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, event->time);
483 else if (event->button == 2){
484 album_add(NULL, song);
486 return TRUE;
489 static guint update_timeout = 0;
490 static MpdData_real *current_item = NULL;
492 static void position_changed(GtkRange *range, gpointer data)
494 gint i=0,value = (int)gtk_range_get_value(range);
495 current_item = mpd_data_get_first(current_item);
496 for(i=0;i<value && current_item && current_item->next; current_item = current_item->next){i++;}
497 update_view();
499 static gboolean update_view_real(void)
501 MpdData *complete_list_iter;
502 const char *search_query = gtk_entry_get_text(GTK_ENTRY(entry));
503 int i=0;
504 GTimeVal start, stop,diff;
505 int j=0;
506 gchar *artist= NULL;
507 int items =0;
508 MpdData *data = NULL;
509 GList *entries = NULL;
510 GList *list = (table)?gtk_container_get_children(GTK_CONTAINER(table)):NULL;
511 GList *iter;
512 GRegex *regex = NULL;
514 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"search query: %s\n", search_query);
516 g_get_current_time(&start);
517 if(table)
518 gtk_widget_hide(table);
519 for(iter = g_list_first(list); iter; iter = iter->next){
520 GtkWidget *widget = iter->data;
521 gtk_container_remove(GTK_CONTAINER(table), widget);
523 g_list_free(list);
524 list = NULL;
527 g_get_current_time(&stop);
528 TIMER_SUB(start, stop, diff);
529 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Removing old stuff time elapsed: %lu s %lus us\n", diff.tv_sec, diff.tv_usec);
531 gtk_widget_show(albumview_tree);
534 * Create a filtered linked list
536 if(search_query[0] != '\0')
538 gchar *str = g_strdup(search_query);
539 gchar **test = g_strsplit(g_strstrip(str), " ", -1);
540 int i=0;
541 GString *s = g_string_new("((?:");
542 GError *error = NULL;
543 g_free(str);
544 for(i=0;test && test[i];i++){
545 gchar *temp = g_regex_escape_string(test[i], -1);
546 s = g_string_append(s, ".*");
547 s= g_string_append(s, temp);
548 s = g_string_append(s, ".*");
549 if(test[i+1] != NULL)
550 s = g_string_append(s, "|");
551 g_free(temp);
553 g_string_append_printf(s,"){%i})",i);
554 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"regex: %s\n", s->str);
555 regex = g_regex_new(s->str, G_REGEX_CASELESS|G_REGEX_EXTENDED, 0,&error);;
556 if(regex)
558 g_string_free(s, TRUE);
559 for(complete_list_iter = mpd_data_get_first(complete_list);
560 complete_list_iter;
561 complete_list_iter = mpd_data_get_next_real(complete_list_iter, FALSE))
563 if(g_regex_match(regex,complete_list_iter->song->album,0,NULL)||
564 g_regex_match(regex,complete_list_iter->song->artist,0,NULL)||
565 (complete_list_iter->song->albumartist && g_regex_match(regex,complete_list_iter->song->albumartist,0,NULL))){
566 items++;
567 list = g_list_append(list, complete_list_iter);
571 if(error) {
572 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_WARNING," error creating regex: %s\n", error->message);
573 g_error_free(error);
575 g_regex_unref(regex);
576 }else {
578 for(complete_list_iter = mpd_data_get_first(complete_list);
579 complete_list_iter;
580 complete_list_iter = mpd_data_get_next_real(complete_list_iter, FALSE))
582 items++;
583 list = g_list_append(list, complete_list_iter);
587 g_get_current_time(&stop);
588 TIMER_SUB(start, stop, diff);
589 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Searching and filtering list: %lu s %lus us\n", diff.tv_sec, diff.tv_usec);
591 int rows = albumview_tree->allocation.height/(album_size+40);
593 * Create holding table if it does not exist
595 if(!table){
596 GtkWidget *ali = gtk_alignment_new(0.0, 0.5, 0,0);
597 table = exo_wrap_table_new(TRUE);//gtk_table_new(rows, supported_columns, TRUE);
598 gtk_container_add(GTK_CONTAINER(ali), table);
599 gtk_box_pack_start(GTK_BOX(albumview_tree), ali, FALSE, FALSE, 0);
602 /* I know how large it is going to be.. so lets set the size */
603 gtk_widget_set_size_request(table, supported_columns*(album_size+20+6), (rows)*(album_size+40));
605 * Add albums
607 if(current_item == NULL) current_item = mpd_data_get_first(complete_list);
609 if(current_item)//(iter = g_list_first(list)))
611 MpdData_real *iter = current_item;
612 int v_items = 0;
615 complete_list_iter = iter;//iter->data;
616 if(complete_list_iter->song/* && (complete_list_iter->song->artist)[0] != '\0'*/)
618 GtkWidget *vbox = complete_list_iter->userdata;
619 GtkWidget *item;
620 int a,b;
621 if(vbox == NULL){
622 GtkWidget *label = NULL;
623 gchar *temp = NULL;
624 /* Wrap it in a vbox */
625 vbox = gtk_vbox_new(FALSE, 3);
626 gtk_widget_set_size_request(vbox, album_size+20,album_size+40);
628 item = gmpc_metaimage_new_size(META_ALBUM_ART,album_size);
629 gtk_widget_set_has_tooltip(GTK_WIDGET(item), FALSE);
630 gmpc_metaimage_set_squared(GMPC_METAIMAGE(item), TRUE);
632 gmpc_metaimage_update_cover_from_song_delayed(GMPC_METAIMAGE(item), complete_list_iter->song);
634 gtk_box_pack_start(GTK_BOX(vbox), item, TRUE, TRUE, 0);
635 /* Set artist name */
636 if(complete_list_iter->song->albumartist){
637 GtkWidget *label = gtk_label_new(complete_list_iter->song->albumartist);
638 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
639 gtk_box_pack_end(GTK_BOX(vbox), label, FALSE, FALSE, 0);
640 }else{
641 GtkWidget *label = gtk_label_new(complete_list_iter->song->artist);
642 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
643 gtk_box_pack_end(GTK_BOX(vbox), label, FALSE, FALSE, 0);
646 /* Set album name */
647 label = gtk_label_new("");
648 temp = g_markup_printf_escaped("<b>%s</b>", complete_list_iter->song->album);
649 gtk_label_set_markup(GTK_LABEL(label), temp);
650 g_free(temp);
651 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
652 gtk_box_pack_end(GTK_BOX(vbox), label, FALSE, FALSE, 0);
655 /* Attach it to the song */
656 complete_list_iter->userdata = g_object_ref_sink(vbox);
657 complete_list_iter->freefunc = (void *)gtk_widget_destroy;
658 g_object_set_data(G_OBJECT(vbox), "item", item);
659 g_signal_connect(item, "button-press-event",
660 G_CALLBACK(album_button_press), complete_list_iter->song);
663 else{
664 item = g_object_get_data(G_OBJECT(vbox), "item");
665 /* Resize if needed */
666 if(album_size != gmpc_metaimage_get_size(GMPC_METAIMAGE(item))){
667 gtk_widget_set_size_request(vbox, album_size+20,album_size+40);
668 gmpc_metaimage_set_size(GMPC_METAIMAGE(item), album_size);
669 gmpc_metaimage_reload_image(GMPC_METAIMAGE(item));
673 entries = g_list_prepend(entries, vbox);
674 j++;
676 v_items++;
677 }while(v_items < (rows*supported_columns)&& (iter = iter->next));
678 printf("%p %i\n", iter, v_items);
680 /* remove list */
681 if(list) g_list_free(list);
682 list = NULL;
684 g_get_current_time(&stop);
685 TIMER_SUB(start, stop, diff);
686 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Creating/Updating albums time elapsed: %lu s %lus us\n", diff.tv_sec, diff.tv_usec);
687 for(iter = entries = g_list_reverse(entries); iter; iter = g_list_next(iter)){
688 gtk_container_add(GTK_CONTAINER(table), iter->data);
690 if(entries) g_list_free(entries);
691 TIMER_SUB(start, stop, diff);
692 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"adding items to view: %lu s %lus us\n", diff.tv_sec, diff.tv_usec);
694 gtk_widget_show_all(albumview_tree);
695 g_get_current_time(&stop);
696 TIMER_SUB(start, stop, diff);
697 g_log(AV_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Showing widget time elapsed: %lu s %lus us\n", diff.tv_sec, diff.tv_usec);
699 * Remove the timeout
701 if(update_timeout)
702 g_source_remove(update_timeout);
703 update_timeout = 0;
704 return FALSE;
708 void update_view()
710 if(update_timeout != 0) {
711 g_source_remove(update_timeout);
713 update_timeout = g_timeout_add(10, (GSourceFunc)update_view_real,NULL);