Modify version string to post-release version 0.17.99
[gmpc-serverstats.git] / src / plugin.c
blob7e1ebdd7295213ce9fa6811545161eb230ef9f9c
1 /* gmpc-serverstats (GMPC plugin)
2 * Copyright (C) 2006-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
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 #include <gtk/gtk.h>
21 #include <gmpc/plugin.h>
22 #include <gmpc/playlist3-messages.h>
23 #include <libmpd/libmpd-internal.h>
24 #include <config.h>
25 #include "plugin.h"
27 static gchar * serverstats_format_time(unsigned long seconds);
28 static void serverstats_browser_save_myself(void);
29 static void serverstats_status_changed(MpdObj *mi, ChangedStatusType what, void *pointer);
30 /* Allow gmpc to check the version the plugin is compiled against */
31 int plugin_api_version = PLUGIN_API_VERSION;
32 /**
33 * Browser extention
35 gmpcPlBrowserPlugin serverstats_gbp = {
36 /** add */
37 .add = serverstats_add,
38 /** selected */
39 .selected = serverstats_selected,
40 /** unselected */
41 .unselected = serverstats_unselected,
45 /**
46 * Define the plugin structure
48 gmpcPlugin plugin = {
49 /* name */
50 .name = "Statistics",
51 /* version */
52 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
53 /* type */
54 .plugin_type = GMPC_PLUGIN_PL_BROWSER,
55 /* init function */
56 .init = serverstats_plugin_init,
57 /** playlist extention struct */
58 .browser = &serverstats_gbp,
59 /** Connection changed */
60 .mpd_connection_changed = serverstats_connection_changed,
61 .mpd_status_changed = serverstats_status_changed,
62 /** enable/disable */
63 .get_enabled = serverstats_get_enabled,
64 .set_enabled = serverstats_set_enabled,
65 /* Safe myself */
66 .save_yourself = serverstats_browser_save_myself
68 enum {
69 SERVERSTATS_MPD_VERSION,
70 SERVERSTATS_MPD_UPTIME,
71 SERVERSTATS_MPD_PLAYTIME,
72 SERVERSTATS_MPD_DB_PLAYTIME,
73 SERVERSTATS_MPD_DB_ARTISTS,
74 SERVERSTATS_MPD_DB_ALBUMS,
75 SERVERSTATS_MPD_DB_SONGS,
76 SERVERSTATS_MPD_URLHANDLERS,
77 SERVERSTATS_MPD_TAG_TYPES,
78 SERVERSTATS_NUM_FIELDS
80 static GtkTreeRowReference *serverstats_ref = NULL;
81 static GtkWidget *serverstats_event= NULL, *serverstats_tree = NULL,*serverstats_combo = NULL;
82 static GtkWidget *serverstats_labels[SERVERSTATS_NUM_FIELDS];
83 static gboolean cancel_query = FALSE;
84 /**
85 * Get/Set enable
88 int serverstats_get_enabled(void)
90 return cfg_get_single_value_as_int_with_default(config, "serverstats", "enable", TRUE);
93 void serverstats_set_enabled(int enabled)
95 cfg_set_single_value_as_int(config, "serverstats", "enable", enabled);
96 if(enabled)
98 if(serverstats_ref == NULL)
100 serverstats_add(GTK_WIDGET(playlist3_get_category_tree_view()));
103 else
105 GtkTreePath *path = gtk_tree_row_reference_get_path(serverstats_ref);
106 GtkTreeModel *model = gtk_tree_row_reference_get_model(serverstats_ref);
107 if (path){
108 GtkTreeIter iter;
109 if (gtk_tree_model_get_iter(model, &iter, path)){
110 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
112 gtk_tree_path_free(path);
113 gtk_tree_row_reference_free(serverstats_ref);
114 serverstats_ref = NULL;
120 * Playlist browser functions
122 static void serverstats_add(GtkWidget *category_tree)
124 GtkTreePath *path;
125 GtkTreeModel *model = GTK_TREE_MODEL(playlist3_get_category_tree_store());
126 GtkTreeIter iter;
127 gint pos;
129 * don't do anything if we are disabled
131 if(!cfg_get_single_value_as_int_with_default(config, "serverstats", "enable", TRUE)) return;
132 /**
133 * Add ourslef to the list
135 pos = cfg_get_single_value_as_int_with_default(config, "serverstats","position",2);
136 playlist3_insert_browser(&iter, pos);
137 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
138 PL3_CAT_TYPE, plugin.id,
139 PL3_CAT_TITLE,"Server Statistics",
140 PL3_CAT_INT_ID, "/",
141 PL3_CAT_ICON_ID, "mpd",
142 PL3_CAT_PROC, TRUE,
143 PL3_CAT_ICON_SIZE,GTK_ICON_SIZE_DND,-1);
144 /**
145 * remove odl reference if exists
147 if (serverstats_ref) {
148 gtk_tree_row_reference_free(serverstats_ref);
149 serverstats_ref = NULL;
152 * create reference to ourself in the list
154 path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter);
155 if (path) {
156 serverstats_ref = gtk_tree_row_reference_new(model, path);
157 gtk_tree_path_free(path);
160 static void serverstats_browser_save_myself(void)
162 if(serverstats_ref)
164 GtkTreePath *path = gtk_tree_row_reference_get_path(serverstats_ref);
165 if(path)
167 gint *indices = gtk_tree_path_get_indices(path);
168 debug_printf(DEBUG_INFO,"Saving myself to position: %i\n", indices[0]);
169 cfg_set_single_value_as_int(config, "serverstats","position",indices[0]);
170 gtk_tree_path_free(path);
174 static void serverstats_clear()
176 int i;
177 for(i=0;i < SERVERSTATS_NUM_FIELDS;i++)
179 gtk_label_set_text(GTK_LABEL(serverstats_labels[i]), "");
183 static void serverstats_update()
185 gchar **handlers = NULL;
186 gchar *value = NULL;
188 serverstats_clear();
189 if(!mpd_check_connected(connection))return;
190 mpd_stats_update(connection);
191 /** Version */
192 value = mpd_server_get_version(connection);
193 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_VERSION]), value);
194 free(value);
195 /** Uptime */
196 value = serverstats_format_time(mpd_stats_get_uptime(connection));
197 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_UPTIME]), value);
198 g_free(value);
199 /** Playtime*/
200 value = serverstats_format_time(mpd_stats_get_playtime(connection));
201 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_PLAYTIME]), value);
202 g_free(value);
203 /** DB Playtime*/
204 value = serverstats_format_time(mpd_stats_get_db_playtime(connection));
205 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_PLAYTIME]), value);
206 g_free(value);
207 /** DB ARTIST*/
208 value = g_strdup_printf("%i", mpd_stats_get_total_artists(connection));
209 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_ARTISTS]), value);
210 g_free(value);
211 /** DB ALBUMS*/
212 value = g_strdup_printf("%i", mpd_stats_get_total_albums(connection));
213 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_ALBUMS]), value);
214 g_free(value);
215 /** DB SONGS*/
216 value = g_strdup_printf("%i", mpd_stats_get_total_songs(connection));
217 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_SONGS]), value);
218 g_free(value);
219 /** URL_HANDLERS*/
220 handlers = mpd_server_get_url_handlers(connection);
221 if(handlers)
223 value = g_strjoinv(",",handlers);
224 g_strfreev(handlers);
225 handlers = NULL;
227 else
228 value = g_strdup("N/A");
229 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_URLHANDLERS]), value);
230 g_free(value);
232 if(mpd_server_check_version(connection, 0,13,0))
233 handlers = mpd_server_get_tag_types(connection);
234 if(handlers)
236 value = g_strjoinv(",",handlers);
237 g_strfreev(handlers);
238 handlers = NULL;
240 else
241 value = g_strdup("N/A");
242 gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_TAG_TYPES]), value);
243 g_free(value);
246 typedef struct _ss_str{
247 int total;
248 int tag;
249 int hits;
250 MpdData *data;
251 GtkTreeModel *model;
252 GtkWidget *box,*pb;
253 long unsigned max_i;
254 }ss_str;
255 gboolean serverstats_idle_handler(ss_str *s)
257 GtkTreeIter iter;
258 MpdDBStats *stats = NULL;
259 if(s->data == NULL || !mpd_check_connected(connection) || cancel_query)
262 if(gtk_tree_model_get_iter_first(s->model, &iter))
264 do{ gulong i;
265 gchar *value = NULL;
266 gtk_tree_model_get(s->model, &iter, 0, &i, -1);
267 guint d = (guint)100*(i/(double)s->max_i);
268 value = serverstats_format_time(i);
269 gtk_list_store_set(GTK_LIST_STORE(s->model), &iter, 2, d, 3,value,-1);
270 g_free(value);
271 }while(gtk_tree_model_iter_next(s->model, &iter));
274 if(s->data)
275 mpd_data_free(s->data);
276 gtk_tree_view_set_model(GTK_TREE_VIEW(serverstats_tree), s->model);
277 gtk_tree_view_set_search_column(GTK_TREE_VIEW(serverstats_tree), 1);
278 gtk_widget_set_sensitive(GTK_WIDGET(s->box), TRUE);
279 gtk_widget_hide(gtk_widget_get_parent(s->pb));
281 if(cancel_query)
282 gtk_list_store_clear(GTK_LIST_STORE(s->model));
283 g_free(s);
284 cancel_query = FALSE;
285 return FALSE;
287 mpd_database_search_stats_start(connection);
288 mpd_database_search_add_constraint(connection, s->tag,s->data->tag);
290 stats = mpd_database_search_stats_commit(connection);
291 if(stats)
294 gtk_list_store_prepend(GTK_LIST_STORE(s->model), &iter);
295 gtk_list_store_set(GTK_LIST_STORE(s->model), &iter, 0, (unsigned long)(stats->playTime), 1,s->data->tag, -1);
296 s->max_i = MAX(s->max_i, stats->playTime);
298 mpd_database_search_free_stats(stats);
302 /* limit the amount of updating to 0.2 % */
303 if((int)((1000*s->hits)/s->total)%5 == 0)
305 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(s->pb),s->hits/(double)s->total);
307 s->hits++;
308 s->data = mpd_data_get_next(s->data);
309 return TRUE;
312 void serverstats_combo_changed(GtkComboBox *box, GtkWidget *pb)
314 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(serverstats_tree));
315 int tag = gtk_combo_box_get_active(box);
316 GtkTreeIter iter;
318 if(!mpd_check_connected(connection))
319 return;
320 if(!mpd_server_check_version(connection,0,13,0))
322 playlist3_show_error_message("This feature is not supported in mpd older then version 0.13.0.", ERROR_WARNING);
323 return;
325 /* reset the cancel flag */
326 cancel_query = FALSE;
327 /* show progress bar */
329 gtk_widget_show_all(gtk_widget_get_parent(pb));
331 /** make the combo box insensitive and remove the model from the treeview */
332 gtk_tree_view_set_model(GTK_TREE_VIEW(serverstats_tree), NULL);
333 gtk_widget_set_sensitive(GTK_WIDGET(box), FALSE);
336 gtk_list_store_clear(GTK_LIST_STORE(model));
337 mpd_database_search_field_start(connection, tag);
338 MpdData *node ,*data = mpd_database_search_commit(connection);
339 gulong max_i = 0;
341 int hits = 0;
342 int total = 0;
343 for(node = mpd_data_get_first(data);node != NULL; node = (MpdData *)mpd_data_get_next_real(node, FALSE)) total++;
344 ss_str *s = g_malloc0(sizeof(*s));
345 s->total = total;
346 s->model = model;
347 s->data = data;
348 s->hits = 0;
349 s->tag = tag;
350 s->pb = pb;
351 s->box = GTK_WIDGET(box);
352 g_idle_add((GSourceFunc)serverstats_idle_handler,s);
357 static gboolean serverstats_body_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
359 cairo_t *cr= gdk_cairo_create(GTK_WIDGET(widget)->window);
360 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
361 cairo_set_line_width (cr, 1);
363 cairo_rectangle(cr, event->area.x,event->area.y,event->area.width, event->area.height);
364 gdk_cairo_set_source_color(cr, &(widget->style->base[GTK_STATE_NORMAL]));
365 cairo_fill(cr);
366 gtk_paint_shadow(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_IN,&(event->area), widget, "scrolled_window",
367 widget->allocation.x ,
368 widget->allocation.y,
369 widget->allocation.width,
370 widget->allocation.height);
371 cairo_destroy(cr);
372 return FALSE;
374 static void serverstats_header_style_changed(GtkWidget *vbox, GtkStyle *style, GtkWidget *vp)
376 gtk_widget_modify_bg(vp,GTK_STATE_NORMAL, &(GTK_WIDGET(vbox)->style->light[GTK_STATE_SELECTED]));
379 static void cancel_clicked(GtkWidget *cancel, gpointer data)
381 cancel_query = TRUE;
384 static void serverstats_init()
386 /** Get an allready exposed widgets to grab theme colors from. */
387 GtkWidget *colw = (GtkWidget *)playlist3_get_category_tree_view();
388 GtkWidget *label = NULL;
389 GtkWidget *table = NULL;
390 GtkWidget *event = NULL;
391 GtkWidget *serverstats_vbox = gtk_vbox_new(FALSE, 0);
393 serverstats_event = gtk_event_box_new();
394 gtk_widget_set_app_paintable(serverstats_event,TRUE);
395 g_signal_connect(G_OBJECT(serverstats_event), "expose-event", G_CALLBACK(serverstats_body_expose_event), NULL);
397 gtk_container_add(GTK_CONTAINER(serverstats_event),serverstats_vbox);
399 gtk_container_set_border_width(GTK_CONTAINER(serverstats_vbox),2);
401 /* wrap in event box to set bg color */
402 event = gtk_event_box_new();
403 gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(colw->style->light[GTK_STATE_SELECTED]));
405 g_signal_connect(G_OBJECT(serverstats_vbox), "style-set", G_CALLBACK(serverstats_header_style_changed), event);
407 /* set label and padding */
408 label = gtk_label_new("");
409 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
410 gtk_misc_set_padding(GTK_MISC(label),12,12);
411 gtk_label_set_markup(GTK_LABEL(label), "<span size='xx-large' weight='bold'>Statistics</span>");
412 gtk_container_add(GTK_CONTAINER(event), label);
413 gtk_box_pack_start(GTK_BOX(serverstats_vbox),event, FALSE, TRUE, 0);
414 gtk_widget_show_all(event);
416 label = gtk_hseparator_new();
417 gtk_box_pack_start(GTK_BOX(serverstats_vbox),label, FALSE, TRUE, 0);
418 gtk_widget_show(label);
420 * Data list
422 table = gtk_table_new(SERVERSTATS_NUM_FIELDS+2, 2,FALSE);
423 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
424 gtk_table_set_row_spacings(GTK_TABLE(table), 6);
425 gtk_container_set_border_width(GTK_CONTAINER(table), 12);
427 /** Database */
428 label = gtk_label_new("");
429 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
430 gtk_label_set_markup(GTK_LABEL(label), "<span size='x-large' weight='bold'>Server</span>");
431 gtk_table_attach(GTK_TABLE(table),label, 0,2,0,1,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
433 /** Mpd version */
434 label = gtk_label_new("");
435 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
436 gtk_misc_set_padding(GTK_MISC(label), 12,0);
437 gtk_label_set_markup(GTK_LABEL(label), "<b>Version:</b>");
438 gtk_table_attach(GTK_TABLE(table),label, 0,1,1,2,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
439 label = serverstats_labels[SERVERSTATS_MPD_VERSION]= gtk_label_new("");
440 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
441 gtk_table_attach(GTK_TABLE(table),label, 1,2,1,2,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
442 /** Mpd Uptime */
443 label = gtk_label_new("");
444 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
445 gtk_misc_set_padding(GTK_MISC(label), 12,0);
446 gtk_label_set_markup(GTK_LABEL(label), "<b>Uptime:</b>");
447 gtk_table_attach(GTK_TABLE(table),label, 0,1,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
448 label = serverstats_labels[SERVERSTATS_MPD_UPTIME]= gtk_label_new("");
449 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
450 gtk_table_attach(GTK_TABLE(table),label, 1,2,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
451 /** Mpd Playtime */
452 label = gtk_label_new("");
453 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
454 gtk_misc_set_padding(GTK_MISC(label), 12,0);
455 gtk_label_set_markup(GTK_LABEL(label), "<b>Time Playing:</b>");
456 gtk_table_attach(GTK_TABLE(table),label, 0,1,3,4,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
457 label = serverstats_labels[SERVERSTATS_MPD_PLAYTIME]= gtk_label_new("");
458 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
459 gtk_table_attach(GTK_TABLE(table),label, 1,2,3,4,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
460 /** Database */
461 label = gtk_label_new("");
462 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
463 gtk_label_set_markup(GTK_LABEL(label), "<span size='x-large' weight='bold'>Database</span>");
464 gtk_table_attach(GTK_TABLE(table),label, 0,2,4,5,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
465 /** Mpd Playtime */
466 label = gtk_label_new("");
467 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
468 gtk_misc_set_padding(GTK_MISC(label), 12,0);
469 gtk_label_set_markup(GTK_LABEL(label), "<b>Total playtime:</b>");
470 gtk_table_attach(GTK_TABLE(table),label, 0,1,5,6,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
471 label = serverstats_labels[SERVERSTATS_MPD_DB_PLAYTIME]= gtk_label_new("");
472 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
473 gtk_table_attach(GTK_TABLE(table),label, 1,2,5,6,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
474 /** Mpd Artists*/
475 label = gtk_label_new("");
476 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
477 gtk_misc_set_padding(GTK_MISC(label), 12,0);
478 gtk_label_set_markup(GTK_LABEL(label), "<b>Number of artists:</b>");
479 gtk_table_attach(GTK_TABLE(table),label, 0,1,6,7,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
480 label = serverstats_labels[SERVERSTATS_MPD_DB_ARTISTS]= gtk_label_new("");
481 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
482 gtk_table_attach(GTK_TABLE(table),label, 1,2,6,7,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
483 /** Mpd Albums */
484 label = gtk_label_new("");
485 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
486 gtk_misc_set_padding(GTK_MISC(label), 12,0);
487 gtk_label_set_markup(GTK_LABEL(label), "<b>Number of albums:</b>");
488 gtk_table_attach(GTK_TABLE(table),label, 0,1,7,8,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
489 label = serverstats_labels[SERVERSTATS_MPD_DB_ALBUMS]= gtk_label_new("");
490 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
491 gtk_table_attach(GTK_TABLE(table),label, 1,2,7,8,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
492 /** Mpd Songs */
493 label = gtk_label_new("");
494 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
495 gtk_misc_set_padding(GTK_MISC(label), 12,0);
496 gtk_label_set_markup(GTK_LABEL(label), "<b>Number of songs:</b>");
497 gtk_table_attach(GTK_TABLE(table),label, 0,1,8,9,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
498 label = serverstats_labels[SERVERSTATS_MPD_DB_SONGS]= gtk_label_new("");
499 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
500 gtk_table_attach(GTK_TABLE(table),label, 1,2,8,9,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
501 /** Mpd Songs */
502 label = gtk_label_new("");
503 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
504 gtk_misc_set_padding(GTK_MISC(label), 12,0);
505 gtk_label_set_markup(GTK_LABEL(label), "<b>URL Handlers:</b>");
506 gtk_table_attach(GTK_TABLE(table),label, 0,1,9,10,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
507 label = serverstats_labels[SERVERSTATS_MPD_URLHANDLERS]= gtk_label_new("");
508 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
509 gtk_table_attach(GTK_TABLE(table),label, 1,2,9,10,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
510 /** Mpd Songs */
511 label = gtk_label_new("");
512 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
513 gtk_misc_set_padding(GTK_MISC(label), 12,0);
514 gtk_label_set_markup(GTK_LABEL(label), "<b>Tag Types:</b>");
515 gtk_table_attach(GTK_TABLE(table),label, 0,1,10,11,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
516 label = serverstats_labels[SERVERSTATS_MPD_TAG_TYPES]= gtk_label_new("");
517 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
518 gtk_table_attach(GTK_TABLE(table),label, 1,2,10,11,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
521 * Add table
523 gtk_box_pack_start(GTK_BOX(serverstats_vbox), table, FALSE, TRUE,0);
524 gtk_widget_show_all(table);
526 * Stats treeview
529 GtkWidget *combo = NULL;
530 GtkWidget *sw = NULL,*tree = NULL,*hbox=NULL,*cancel;
531 GtkListStore *store;
532 GtkTreeViewColumn *column;
533 GtkCellRenderer *renderer;
534 int i;
535 GtkWidget *pb = gtk_progress_bar_new();
536 serverstats_combo = combo = gtk_combo_box_new_text();
537 for(i=0;i<MPD_TAG_NUM_OF_ITEM_TYPES-2;i++)
539 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), mpdTagItemKeys[i]);
542 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(serverstats_combo_changed), pb);
544 gtk_box_pack_start(GTK_BOX(serverstats_vbox), combo,FALSE, TRUE,0);
545 gtk_widget_show_all(combo);
546 hbox = gtk_hbox_new(FALSE,6);
547 cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
548 g_signal_connect(G_OBJECT(cancel), "clicked", G_CALLBACK(cancel_clicked), NULL);
549 gtk_box_pack_start(GTK_BOX(hbox), pb,TRUE, TRUE,0);
550 gtk_box_pack_start(GTK_BOX(hbox), cancel,FALSE, TRUE,0);
551 gtk_box_pack_start(GTK_BOX(serverstats_vbox), hbox,FALSE, TRUE,0);
553 sw = gtk_scrolled_window_new(NULL, NULL);
554 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
555 gtk_container_set_border_width(GTK_CONTAINER(sw), 6);
557 store = gtk_list_store_new(4, G_TYPE_ULONG, G_TYPE_STRING, G_TYPE_ULONG, G_TYPE_STRING);
558 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), 0,GTK_SORT_DESCENDING);
559 serverstats_tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
560 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(serverstats_tree), FALSE);
561 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(serverstats_tree), TRUE);
562 renderer = gtk_cell_renderer_text_new();
563 g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END,"ellipsize-set", TRUE,"width-chars",30, NULL);
564 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(serverstats_tree),
565 -1, "",
566 renderer,
567 "text", 1,NULL);
568 renderer = gtk_cell_renderer_progress_new();
569 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(serverstats_tree),
570 -1, "",
571 renderer,
572 "value", 2,
573 "text", 3,NULL);
575 gtk_tree_view_set_search_column(GTK_TREE_VIEW(serverstats_tree), 1);
577 gtk_container_add(GTK_CONTAINER(sw), serverstats_tree);
578 gtk_box_pack_start(GTK_BOX(serverstats_vbox), sw, TRUE, TRUE,0);
579 gtk_widget_show_all(sw);
582 gtk_widget_show(serverstats_vbox);
583 /* maintain my own reference to the widget, so it won't get destroyed removing
584 * from view
586 g_object_ref(serverstats_event);
589 static guint timeout_source = 0;
591 static void serverstats_selected(GtkWidget *container)
593 if(serverstats_event== NULL) {
594 serverstats_init();
596 serverstats_update();
597 gtk_container_add(GTK_CONTAINER(container), serverstats_event);
598 gtk_widget_show(serverstats_event);
599 if(timeout_source)
600 g_source_remove(timeout_source);
601 timeout_source = g_timeout_add(30000, (GSourceFunc)serverstats_update, NULL);
604 static void serverstats_unselected(GtkWidget *container)
606 if(timeout_source)
607 g_source_remove(timeout_source);
608 timeout_source = 0;
609 gtk_container_remove(GTK_CONTAINER(container),serverstats_event);
614 static gchar * serverstats_format_time(unsigned long seconds)
616 GString *str = NULL;
617 gulong days = seconds/86400;
618 gulong houres = (seconds % 86400)/3600;
619 gulong minutes = (seconds % 3600)/60;
620 char *ret;
621 if(seconds == 0)
623 return g_strdup("");
625 str = g_string_new("");
626 if(days != 0)
629 g_string_append_printf(str, "%lu %s ", days, (days == 1)?("day"):("days"));
631 if(houres != 0)
633 g_string_append_printf(str, "%lu %s ", houres, (houres == 1)?("hour"):("hours"));
635 if(minutes != 0)
637 g_string_append_printf(str, "%lu %s", minutes,(minutes==1)?("minute"):("minutes"));
639 ret = str->str;
640 g_string_free(str, FALSE);
641 return ret;
645 void serverstats_plugin_init(void)
647 gchar *path = gmpc_plugin_get_data_path(&plugin);
648 gchar *url = g_build_path(G_DIR_SEPARATOR_S,path, "serverstats", NULL);
649 debug_printf(DEBUG_WARNING,"Found url: %s\n", url);
651 gchar *path = NULL;
653 path = g_strdup_printf("%s%c%s",plugin.path,G_DIR_SEPARATOR, "serverstats");
656 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),url);
658 g_free(path);
659 g_free(url);
662 void serverstats_connection_changed(MpdObj *mi, int connect,void *usedata)
665 if(!connect && serverstats_tree)
667 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(serverstats_tree));
668 serverstats_clear();
669 if(model)
670 gtk_list_store_clear(GTK_LIST_STORE(model));
671 gtk_combo_box_set_active(GTK_COMBO_BOX(serverstats_combo), -1);
675 static void serverstats_status_changed(MpdObj *mi, ChangedStatusType what, void *pointer)