2 #include <gmpc/plugin.h>
3 #include <gmpc/playlist3-messages.h>
4 #include <gmpc/gmpc-metaimage.h>
6 #include <libmpd/libmpd-internal.h>
9 #include "exo-wrap-table.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
);
22 static void filter_list(GtkEntry
*entry
, gpointer data
);
23 void update_view(void);
27 gmpcPlBrowserPlugin albumview_gbp
= {
31 .selected
= albumview_selected
,
33 .unselected
= albumview_unselected
,
38 * Define the plugin structure
44 .version
= {PLUGIN_MAJOR_VERSION
,PLUGIN_MINOR_VERSION
,PLUGIN_MICRO_VERSION
},
46 .plugin_type
= GMPC_PLUGIN_PL_BROWSER
,
48 .init
= albumview_plugin_init
,
49 /** playlist extention struct */
50 .browser
= &albumview_gbp
,
51 /** Connection changed */
52 .mpd_connection_changed
= albumview_connection_changed
,
54 .get_enabled
= albumview_get_enabled
,
55 .set_enabled
= albumview_set_enabled
,
57 .save_yourself
= albumview_browser_save_myself
60 static GtkTreeRowReference
*albumview_ref
= NULL
;
61 static GtkWidget
*albumview_vbox
= NULL
, *albumview_tree
= NULL
,*albumview_combo
= NULL
;
62 static gboolean cancel_query
= FALSE
;
67 int albumview_get_enabled(void)
69 return cfg_get_single_value_as_int_with_default(config
, "albumview", "enable", TRUE
);
72 void albumview_set_enabled(int enabled
)
74 cfg_set_single_value_as_int(config
, "albumview", "enable", enabled
);
77 if(albumview_ref
== NULL
)
79 albumview_add(GTK_WIDGET(playlist3_get_category_tree_view()));
84 GtkTreePath
*path
= gtk_tree_row_reference_get_path(albumview_ref
);
85 GtkTreeModel
*model
= gtk_tree_row_reference_get_model(albumview_ref
);
88 if (gtk_tree_model_get_iter(model
, &iter
, path
)){
89 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
91 gtk_tree_path_free(path
);
92 gtk_tree_row_reference_free(albumview_ref
);
99 * Playlist browser functions
101 static void albumview_add(GtkWidget
*category_tree
)
104 GtkTreeModel
*model
= GTK_TREE_MODEL(playlist3_get_category_tree_store());
108 * don't do anything if we are disabled
110 if(!cfg_get_single_value_as_int_with_default(config
, "albumview", "enable", TRUE
)) return;
112 * Add ourslef to the list
114 pos
= cfg_get_single_value_as_int_with_default(config
, "albumview","position",2);
115 playlist3_insert_browser(&iter
, pos
);
116 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
,
117 PL3_CAT_TYPE
, plugin
.id
,
118 PL3_CAT_TITLE
,"Album View",
119 PL3_CAT_ICON_ID
, "gtk-open",
122 * remove odl reference if exists
125 gtk_tree_row_reference_free(albumview_ref
);
126 albumview_ref
= NULL
;
129 * create reference to ourself in the list
131 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(model
), &iter
);
133 albumview_ref
= gtk_tree_row_reference_new(model
, path
);
134 gtk_tree_path_free(path
);
137 static void albumview_browser_save_myself(void)
141 GtkTreePath
*path
= gtk_tree_row_reference_get_path(albumview_ref
);
144 gint
*indices
= gtk_tree_path_get_indices(path
);
145 debug_printf(DEBUG_INFO
,"Saving myself to position: %i\n", indices
[0]);
146 cfg_set_single_value_as_int(config
, "albumview","position",indices
[0]);
147 gtk_tree_path_free(path
);
152 GtkWidget
*entry
= NULL
;
153 int album_size
= 200;
154 int supported_columns
= 1;
155 void size_changed(GtkWidget
*widget
, GtkAllocation
*alloc
)
157 int columns
= (alloc
->width
-20)/(album_size
+25);
158 if(columns
!= supported_columns
)
160 supported_columns
= columns
;
161 g_log(AV_LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "update columns: %i %i %i\n", alloc
->width
-20,columns
, album_size
);
162 if(entry
&& GTK_WIDGET_IS_SENSITIVE(entry
))
168 void album_size_changed(GtkRange
*spin
)
170 int new_size
= ((int)gtk_range_get_value(spin
))*20;
171 if(new_size
!= album_size
) {
172 album_size
= new_size
;
173 size_changed(albumview_vbox
, &(albumview_vbox
->allocation
));
175 if(entry && GTK_WIDGET_IS_SENSITIVE(entry))
181 cfg_set_single_value_as_int(config
, "albumview", "zoom-level", (int)gtk_range_get_value(spin
));
183 static gboolean
expose_event(GtkWidget
*wid
, GdkEventExpose
*event
, gpointer data
)
185 /* TODO improve this, somehow applying the clipmask fail. */
186 int offset
= ((event
->area
.y
)%(album_size
+40));
187 int step
= (album_size
+40)- offset
;
188 int start
= event
->area
.y
;
189 int flip
= ((int)(event
->area
.y
+step
-5)/(album_size
+40))&1;
190 int stop
= event
->area
.y
+event
->area
.height
;
191 cairo_t
*cc
= gdk_cairo_create(GTK_WIDGET(wid
)->window
);
194 cairo_set_source_rgba(cc
, 1.0,1.0,1.0,1.0);
196 cairo_set_source_rgba(cc
, 0.8,0.8,0.8,1.0);
197 cairo_rectangle(cc
, 0, start
, wid
->allocation
.width
,step
);
200 step
= album_size
+40;
201 flip
= (flip
== 1)?0:1;
206 static GtkWidget
*hscale
= NULL
;
207 static void albumview_init()
209 /** Get an allready exposed widgets to grab theme colors from. */
210 GtkWidget
*colw
= (GtkWidget
*)playlist3_get_category_tree_view();
211 GtkWidget
*label
= NULL
;
212 GtkWidget
*event
= gtk_event_box_new();//(NULL, NULL);//gtk_event_box_new();
214 albumview_vbox
= gtk_vbox_new(FALSE
, 0);
216 album_size
= 20*cfg_get_single_value_as_int_with_default(config
, "albumview", "zoom-level", 10);
217 g_signal_connect(G_OBJECT(albumview_vbox
), "size-allocate", G_CALLBACK(size_changed
), NULL
);
219 GtkWidget
*sw
= gtk_hbox_new(FALSE
, 6);//gtk_scrolled_window_new(NULL, NULL);
220 GtkWidget
*iv
= albumview_tree
= gtk_vbox_new(FALSE
, 6);
221 hscale
= gtk_hscale_new_with_range(0,1,1);
222 g_signal_connect(G_OBJECT(hscale
), "value-changed", G_CALLBACK(position_changed
), NULL
);
224 entry
= gtk_entry_new();
225 gtk_box_pack_start(GTK_BOX(albumview_vbox
), entry
, FALSE
, FALSE
, 0);
226 g_signal_connect(G_OBJECT(entry
),"changed", G_CALLBACK(filter_list
), NULL
);
228 GtkWidget
*spin
= gtk_hscale_new_with_range(1, 12, 1);
229 gtk_scale_set_draw_value(GTK_SCALE(spin
), FALSE
);
230 gtk_range_set_value(GTK_RANGE(spin
), album_size
);
231 gtk_box_pack_start(GTK_BOX(albumview_vbox
), spin
, FALSE
, FALSE
, 0);
233 #if GTK_CHECK_VERSION(2,16,0)
235 gtk_scale_add_mark(GTK_SCALE(spin
), (gdouble
)i
,GTK_POS_TOP
, NULL
);
239 gtk_range_set_value(GTK_RANGE(spin
), cfg_get_single_value_as_int_with_default(config
, "albumview", "zoom-level", 10));
240 g_signal_connect(G_OBJECT(spin
), "value-changed", G_CALLBACK(album_size_changed
), NULL
);
243 gtk_box_pack_start(GTK_BOX(albumview_vbox
),sw
, TRUE
, TRUE
, 0);
244 gtk_widget_modify_bg(event
, GTK_STATE_NORMAL
,&(albumview_vbox
->style
->white
));
245 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event
), TRUE
);
246 gtk_widget_set_app_paintable(GTK_WIDGET(event
),TRUE
);
247 g_signal_connect(G_OBJECT(event
), "expose-event", G_CALLBACK(expose_event
), NULL
);
249 gtk_box_pack_start(GTK_BOX(sw
),event
, TRUE
, TRUE
, 0);//gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), event);
250 gtk_box_pack_start(GTK_BOX(albumview_vbox
),hscale
, FALSE
, FALSE
, 0);//gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), event);
251 // gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
252 gtk_container_add(GTK_CONTAINER(event
), iv
);
254 gtk_widget_show_all(albumview_vbox
);
255 /* maintain my own reference to the widget, so it won't get destroyed removing
258 g_object_ref(albumview_vbox
);
262 static void albumview_selected(GtkWidget
*container
)
264 if(albumview_vbox
== NULL
) {
266 albumview_connection_changed(connection
,1,NULL
);
268 gtk_container_add(GTK_CONTAINER(container
), albumview_vbox
);
269 gtk_widget_show(albumview_vbox
);
272 static void albumview_unselected(GtkWidget
*container
)
274 gtk_container_remove(GTK_CONTAINER(container
), albumview_vbox
);
279 void albumview_plugin_init(void)
281 gchar
*path
= gmpc_plugin_get_data_path(&plugin
);
282 gchar
*url
= g_build_path(G_DIR_SEPARATOR_S
,path
, "albumview", NULL
);
283 debug_printf(DEBUG_WARNING
,"Found url: %s\n", url
);
286 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),url
);
291 #define TIMER_SUB(start,stop,diff) diff.tv_usec = stop.tv_usec - start.tv_usec;\
292 diff.tv_sec = stop.tv_sec - start.tv_sec;\
293 if(diff.tv_usec < 0) {\
295 diff.tv_usec += G_USEC_PER_SEC; \
297 static gint
__add_sort(gpointer aa
, gpointer bb
, gpointer data
)
299 MpdData_real
*a
= *(MpdData_real
**)aa
;
300 MpdData_real
*b
= *(MpdData_real
**)bb
;
301 if(!a
|| !b
) return 0;
302 if(a
->type
== MPD_DATA_TYPE_SONG
&& b
->type
== MPD_DATA_TYPE_SONG
)
304 if(a
->song
->artist
&& b
->song
->artist
)
309 sa
= g_utf8_strdown(a
->song
->artist
, -1);
310 sb
= g_utf8_strdown(b
->song
->artist
, -1);
311 val
= g_utf8_collate(sa
,sb
);
315 val = (a == NULL)?((b==NULL)?0:-1):1;
322 MpdData
*complete_list
= NULL
;
324 int max
= 0, current
= 0;
326 static gboolean
load_list_itterate(MpdData
*data
)
328 MpdData
*data2
= NULL
;
330 if(max
>0 && current
%25 == 0){
331 gchar
*temp
= g_strdup_printf("%i of %i albums loaded", current
, max
);
332 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb
), current
/(double)max
);
333 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pb
), temp
);
339 mpd_database_search_field_start(connection
, MPD_TAG_ITEM_ARTIST
);
340 mpd_database_search_add_constraint(connection
, MPD_TAG_ITEM_ALBUM
, (data
)->tag
);
341 data2
= mpd_database_search_commit(connection
);
344 mpd_Song
*song
= mpd_newSong();
345 song
->album
= g_strdup((data
)->tag
);
346 song
->artist
= g_strdup(data2
->tag
);
347 if(!mpd_data_is_last(data2
))
349 /* test if server supports album artist */
350 if(mpd_server_tag_supported(connection
, MPD_TAG_ITEM_ALBUM_ARTIST
))
352 mpd_database_search_field_start(connection
, MPD_TAG_ITEM_ALBUM_ARTIST
);
353 mpd_database_search_add_constraint(connection
, MPD_TAG_ITEM_ALBUM
, (data
)->tag
);
354 MpdData
*data3
= mpd_database_search_commit(connection
);
355 if(mpd_data_is_last(data3
)){
356 song
->albumartist
= g_strdup(data3
->tag
);
362 mpd_data_free(data3
);
369 mpd_data_free(data2
);
371 complete_list
= mpd_new_data_struct_append(complete_list
);
372 complete_list
->song
= song
;
373 complete_list
->type
= MPD_DATA_TYPE_SONG
;
378 (data
) = mpd_data_get_next((data
));
383 complete_list
= (MpdData
*)misc_sort_mpddata(mpd_data_get_first(complete_list
), (GCompareDataFunc
)__add_sort
, NULL
);
384 g_log(AV_LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
,"update view\n");
385 gtk_widget_destroy(pb
);
386 for(iter
= (MpdData_real
*)complete_list
; iter
; iter
= iter
->next
) items
++;
388 gtk_widget_set_sensitive(entry
, TRUE
);
389 filter_list(GTK_ENTRY(entry
), NULL
);
393 g_idle_add((GSourceFunc
)load_list_itterate
, data
);
397 static GList
*current_item
= NULL
;
398 static GtkWidget
*table
= NULL
;
399 static void load_list(void)
401 if(complete_list
)mpd_data_free(complete_list
);
402 complete_list
= NULL
;
403 if(current_item
) g_list_free(current_item
);
407 pb
= gtk_progress_bar_new();
408 gtk_box_pack_start(GTK_BOX(albumview_tree
), pb
, FALSE
, FALSE
, 0);
409 gtk_widget_show_all(albumview_tree
);
410 mpd_database_search_field_start(connection
, MPD_TAG_ITEM_ALBUM
);
411 MpdData
*iter
,*data
= mpd_database_search_commit(connection
);
414 gtk_widget_set_sensitive(entry
, FALSE
);
415 for(iter
= data
; iter
; iter
= mpd_data_get_next_real(iter
, FALSE
)) max
++;
416 g_idle_add((GSourceFunc
)load_list_itterate
, data
);
418 void albumview_connection_changed(MpdObj
*mi
, int connect
,void *usedata
)
421 if(connect
&& albumview_vbox
)
425 else if(albumview_vbox
){
426 mpd_data_free(complete_list
);
427 complete_list
= NULL
;
430 static void album_add(GtkWidget
*button
, mpd_Song
*song
)
432 mpd_database_search_start(connection
,TRUE
);
434 mpd_database_search_add_constraint(connection
, MPD_TAG_ITEM_ALBUM
, song
->album
);
435 if(song
->albumartist
&& strlen(song
->albumartist
) >0){
436 mpd_database_search_add_constraint(connection
, MPD_TAG_ITEM_ALBUM_ARTIST
, song
->albumartist
);
438 mpd_database_search_add_constraint(connection
, MPD_TAG_ITEM_ARTIST
, song
->artist
);
440 MpdData
*data
= mpd_database_search_commit(connection
);
441 for(;data
;data
= mpd_data_get_next(data
)){
442 mpd_playlist_queue_add(connection
, data
->song
->file
);
444 mpd_playlist_queue_commit(connection
);
446 static void album_view(GtkWidget
*button
,mpd_Song
*song
)
448 if (song
&& song
->artist
&& song
->album
) {
450 info2_fill_album_view(song
->artist
, song
->album
);
454 static void album_replace(GtkWidget
*button
, mpd_Song
*song
)
456 mpd_playlist_clear(connection
);
457 album_add(button
, song
);
458 mpd_player_play(connection
);
460 static gboolean
album_button_press(GtkWidget
*item
, GdkEventButton
*event
, mpd_Song
*song
)
462 g_log(AV_LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "button press event %i\n", event
->button
);
463 if(event
->button
== 1 && event
->type
== GDK_BUTTON_PRESS
)
465 GtkWidget
*menu
= gtk_menu_new();
468 item
= gtk_image_menu_item_new_with_label("Album information");
469 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
470 gtk_image_new_from_stock(GTK_STOCK_INFO
, GTK_ICON_SIZE_MENU
));
471 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
472 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(album_view
), song
);
474 item
= gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD
,NULL
);
475 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
476 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(album_add
), song
);
478 /* replace the replace widget */
479 item
= gtk_image_menu_item_new_with_label("Replace");
480 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
481 gtk_image_new_from_stock(GTK_STOCK_REDO
, GTK_ICON_SIZE_MENU
));
482 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
483 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(album_replace
), song
);
484 gtk_widget_show_all(menu
);
485 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 0, event
->time
);
487 else if (event
->button
== 2){
488 album_add(NULL
, song
);
493 static guint update_timeout
= 0;
495 static void filter_list(GtkEntry
*entry
, gpointer data
)
497 GRegex
*regex
= NULL
;
500 const gchar
*search_query
= gtk_entry_get_text(entry
);
501 MpdData_real
*complete_list_iter
= NULL
;
502 if(search_query
[0] != '\0')
504 gchar
*str
= g_strdup(search_query
);
505 gchar
**test
= g_strsplit(g_strstrip(str
), " ", -1);
507 GString
*s
= g_string_new("((?:");
508 GError
*error
= NULL
;
510 for(i
=0;test
&& test
[i
];i
++){
511 gchar
*temp
= g_regex_escape_string(test
[i
], -1);
512 s
= g_string_append(s
, ".*");
513 s
= g_string_append(s
, temp
);
514 s
= g_string_append(s
, ".*");
515 if(test
[i
+1] != NULL
)
516 s
= g_string_append(s
, "|");
519 g_string_append_printf(s
,"){%i})",i
);
520 g_log(AV_LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
,"regex: %s\n", s
->str
);
521 regex
= g_regex_new(s
->str
, G_REGEX_CASELESS
|G_REGEX_EXTENDED
, 0,&error
);;
524 g_string_free(s
, TRUE
);
525 for(complete_list_iter
= (MpdData_real
*) mpd_data_get_first(complete_list
);
527 complete_list_iter
= mpd_data_get_next_real(complete_list_iter
, FALSE
))
529 if(g_regex_match(regex
,complete_list_iter
->song
->album
,0,NULL
)||
530 g_regex_match(regex
,complete_list_iter
->song
->artist
,0,NULL
)||
531 (complete_list_iter
->song
->albumartist
&& g_regex_match(regex
,complete_list_iter
->song
->albumartist
,0,NULL
))){
533 list
= g_list_append(list
, complete_list_iter
);
538 g_log(AV_LOG_DOMAIN
, G_LOG_LEVEL_WARNING
," error creating regex: %s\n", error
->message
);
541 g_regex_unref(regex
);
543 if(current_item
) g_list_free(current_item
);
544 current_item
= g_list_first(list
);
546 gtk_range_set_range(GTK_RANGE(hscale
), 0, (items
>0)?items
:1);
547 gtk_range_set_value(GTK_RANGE(hscale
), 0);
551 static void position_changed(GtkRange
*range
, gpointer data
)
553 gint i
=0,value
= (int)gtk_range_get_value(range
);
554 current_item
= g_list_first(current_item
);
555 for(i
=0;i
<value
&& current_item
&& current_item
->next
; current_item
= current_item
->next
){i
++;}
558 static gboolean
update_view_real(void)
560 MpdData
*complete_list_iter
;
561 const char *search_query
= gtk_entry_get_text(GTK_ENTRY(entry
));
566 MpdData
*data
= NULL
;
567 GList
*entries
= NULL
;
568 GList
*list
= (table
)?gtk_container_get_children(GTK_CONTAINER(table
)):NULL
;
570 GRegex
*regex
= NULL
;
572 g_log(AV_LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
,"search query: %s\n", search_query
);
575 gtk_widget_hide(table
);
576 for(iter
= g_list_first(list
); iter
; iter
= iter
->next
){
577 GtkWidget
*widget
= iter
->data
;
578 gtk_container_remove(GTK_CONTAINER(table
), widget
);
585 gtk_widget_show(albumview_tree
);
586 if(current_item
== NULL
){
588 for(complete_list_iter
= mpd_data_get_first(complete_list
);
590 complete_list_iter
= mpd_data_get_next_real(complete_list_iter
, FALSE
))
593 current_item
= g_list_append(current_item
, complete_list_iter
);
595 current_item
= g_list_first(current_item
);
596 gtk_range_set_range(GTK_RANGE(hscale
), 0, items
);
597 gtk_range_set_value(GTK_RANGE(hscale
), 0);
600 int rows
= albumview_tree
->allocation
.height
/(album_size
+40);
602 * Create holding table if it does not exist
605 GtkWidget
*ali
= gtk_alignment_new(0.0, 0.5, 0,0);
606 table
= exo_wrap_table_new(TRUE
);//gtk_table_new(rows, supported_columns, TRUE);
607 gtk_container_add(GTK_CONTAINER(ali
), table
);
608 gtk_box_pack_start(GTK_BOX(albumview_tree
), ali
, FALSE
, FALSE
, 0);
611 /* I know how large it is going to be.. so lets set the size */
612 gtk_widget_set_size_request(table
, supported_columns
*(album_size
+20+6), (rows
)*(album_size
+40));
617 if(current_item
)//(iter = g_list_first(list)))
619 GList
*iter
= current_item
;
623 complete_list_iter
= iter
->data
;
624 if(complete_list_iter
->song
/* && (complete_list_iter->song->artist)[0] != '\0'*/)
626 GtkWidget
*vbox
= complete_list_iter
->userdata
;
630 GtkWidget
*label
= NULL
;
632 /* Wrap it in a vbox */
633 vbox
= gtk_vbox_new(FALSE
, 3);
634 gtk_widget_set_size_request(vbox
, album_size
+20,album_size
+40);
636 item
= gmpc_metaimage_new_size(META_ALBUM_ART
,album_size
);
637 gtk_widget_set_has_tooltip(GTK_WIDGET(item
), FALSE
);
638 gmpc_metaimage_set_squared(GMPC_METAIMAGE(item
), TRUE
);
640 gmpc_metaimage_update_cover_from_song_delayed(GMPC_METAIMAGE(item
), complete_list_iter
->song
);
642 gtk_box_pack_start(GTK_BOX(vbox
), item
, TRUE
, TRUE
, 0);
643 /* Set artist name */
644 if(complete_list_iter
->song
->albumartist
){
645 GtkWidget
*label
= gtk_label_new(complete_list_iter
->song
->albumartist
);
646 gtk_label_set_ellipsize(GTK_LABEL(label
), PANGO_ELLIPSIZE_MIDDLE
);
647 gtk_box_pack_end(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
649 GtkWidget
*label
= gtk_label_new(complete_list_iter
->song
->artist
);
650 gtk_label_set_ellipsize(GTK_LABEL(label
), PANGO_ELLIPSIZE_MIDDLE
);
651 gtk_box_pack_end(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
655 label
= gtk_label_new("");
656 temp
= g_markup_printf_escaped("<b>%s</b>", complete_list_iter
->song
->album
);
657 gtk_label_set_markup(GTK_LABEL(label
), temp
);
659 gtk_label_set_ellipsize(GTK_LABEL(label
), PANGO_ELLIPSIZE_MIDDLE
);
660 gtk_box_pack_end(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
663 /* Attach it to the song */
664 complete_list_iter
->userdata
= g_object_ref_sink(vbox
);
665 complete_list_iter
->freefunc
= (void *)gtk_widget_destroy
;
666 g_object_set_data(G_OBJECT(vbox
), "item", item
);
667 g_signal_connect(item
, "button-press-event",
668 G_CALLBACK(album_button_press
), complete_list_iter
->song
);
672 item
= g_object_get_data(G_OBJECT(vbox
), "item");
673 /* Resize if needed */
674 if(album_size
!= gmpc_metaimage_get_size(GMPC_METAIMAGE(item
))){
675 gtk_widget_set_size_request(vbox
, album_size
+20,album_size
+40);
676 gmpc_metaimage_set_size(GMPC_METAIMAGE(item
), album_size
);
677 gmpc_metaimage_reload_image(GMPC_METAIMAGE(item
));
681 entries
= g_list_prepend(entries
, vbox
);
685 }while(v_items
< (rows
*supported_columns
)&& (iter
= iter
->next
));
686 printf("%p %i\n", iter
, v_items
);
689 if(list
) g_list_free(list
);
692 for(iter
= entries
= g_list_reverse(entries
); iter
; iter
= g_list_next(iter
)){
693 gtk_container_add(GTK_CONTAINER(table
), iter
->data
);
695 if(entries
) g_list_free(entries
);
697 gtk_widget_show_all(albumview_tree
);
702 g_source_remove(update_timeout
);
710 if(update_timeout
!= 0) {
711 g_source_remove(update_timeout
);
713 update_timeout
= g_timeout_add(10, (GSourceFunc
)update_view_real
,NULL
);