#include #include #include #include "plugin.h" gchar * serverstats_format_time(unsigned long seconds); /* Allow gmpc to check the version the plugin is compiled against */ int plugin_api_version = PLUGIN_API_VERSION; /** * Browser extention */ gmpcPlBrowserPlugin serverstats_gbp = { /** add */ serverstats_add, /** selected */ serverstats_selected, /** unselected */ serverstats_unselected, /** cat_selection_changed */ NULL, /* */ NULL, NULL, NULL, NULL, NULL }; /** * Define the plugin structure */ gmpcPlugin plugin = { /* name */ "Statistics", /* version */ {0,15,0}, /* type */ GMPC_PLUGIN_PL_BROWSER, /* id, set by gmpc */ 0, /* path to plugin, not filled by gmpc */ NULL, /* init function */ serverstats_plugin_init, /* server */ NULL, /** playlist extention struct */ &serverstats_gbp, /** Status changed */ NULL, /** Connection changed */ serverstats_connection_changed, /** Preferences */ NULL, /** Metadata */ NULL, /** enable/disable */ serverstats_get_enabled, serverstats_set_enabled }; enum { SERVERSTATS_MPD_VERSION, SERVERSTATS_MPD_UPTIME, SERVERSTATS_MPD_PLAYTIME, SERVERSTATS_MPD_DB_PLAYTIME, SERVERSTATS_MPD_DB_ARTISTS, SERVERSTATS_MPD_DB_ALBUMS, SERVERSTATS_MPD_DB_SONGS, SERVERSTATS_NUM_FIELDS }; static GtkTreeRowReference *serverstats_ref = NULL; static GtkWidget *serverstats_event= NULL, *serverstats_tree = NULL,*serverstats_combo = NULL; static GtkWidget *serverstats_labels[SERVERSTATS_NUM_FIELDS]; /** * Get/Set enable */ int serverstats_get_enabled(void) { return cfg_get_single_value_as_int_with_default(config, "serverstats", "enable", TRUE); } void serverstats_set_enabled(int enabled) { cfg_set_single_value_as_int(config, "serverstats", "enable", enabled); if(enabled) { if(serverstats_ref == NULL) { serverstats_add(GTK_WIDGET(playlist3_get_category_tree_view())); } } else { GtkTreePath *path = gtk_tree_row_reference_get_path(serverstats_ref); if (path){ GtkTreeIter iter; if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter, path)){ gtk_tree_store_remove(playlist3_get_category_tree_store(), &iter); } gtk_tree_path_free(path); gtk_tree_row_reference_free(serverstats_ref); serverstats_ref = NULL; } } } /** * Playlist browser functions */ static void serverstats_add(GtkWidget *category_tree) { GtkTreePath *path; GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(category_tree)); GtkTreeIter iter; /** * don't do anything if we are disabled */ if(!cfg_get_single_value_as_int_with_default(config, "serverstats", "enable", TRUE)) return; /** * Add ourslef to the list */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); gtk_tree_store_set(GTK_TREE_STORE(model), &iter, PL3_CAT_TYPE, plugin.id, PL3_CAT_TITLE,"Server Statistics", PL3_CAT_INT_ID, "/", PL3_CAT_ICON_ID, "mpd", PL3_CAT_PROC, TRUE, PL3_CAT_ICON_SIZE,GTK_ICON_SIZE_DND,-1); /** * remove odl reference if exists */ if (serverstats_ref) { gtk_tree_row_reference_free(serverstats_ref); serverstats_ref = NULL; } /** * create reference to ourself in the list */ path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter); if (path) { serverstats_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path); gtk_tree_path_free(path); } } static void serverstats_clear() { int i; for(i=0;i < SERVERSTATS_NUM_FIELDS;i++) { gtk_label_set_text(GTK_LABEL(serverstats_labels[i]), ""); } } static void serverstats_update() { gchar *value = NULL; serverstats_clear(); if(!mpd_check_connected(connection))return; mpd_stats_update(connection); /** Version */ value = mpd_server_get_version(connection); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_VERSION]), value); free(value); /** Uptime */ value = serverstats_format_time(mpd_stats_get_uptime(connection)); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_UPTIME]), value); g_free(value); /** Playtime*/ value = serverstats_format_time(mpd_stats_get_playtime(connection)); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_PLAYTIME]), value); g_free(value); /** DB Playtime*/ value = serverstats_format_time(mpd_stats_get_db_playtime(connection)); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_PLAYTIME]), value); g_free(value); /** DB ARTIST*/ value = g_strdup_printf("%i", mpd_stats_get_total_artists(connection)); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_ARTISTS]), value); g_free(value); /** DB ALBUMS*/ value = g_strdup_printf("%i", mpd_stats_get_total_albums(connection)); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_ALBUMS]), value); g_free(value); /** DB SONGS*/ value = g_strdup_printf("%i", mpd_stats_get_total_songs(connection)); gtk_label_set_text(GTK_LABEL(serverstats_labels[SERVERSTATS_MPD_DB_SONGS]), value); g_free(value); } void serverstats_combo_changed(GtkComboBox *box, GtkWidget *pb) { if(!mpd_check_connected(connection)) return; GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(serverstats_tree)); int tag = gtk_combo_box_get_active(box); GtkTreeIter iter; gtk_widget_show(pb); /** set stuff */ gtk_tree_view_set_model(GTK_TREE_VIEW(serverstats_tree), NULL); gtk_widget_set_sensitive(GTK_WIDGET(box), FALSE); gtk_list_store_clear(GTK_LIST_STORE(model)); mpd_database_search_field_start(connection, tag); MpdData *node ,*data = mpd_database_search_commit(connection); int max_i = 0; int hits = 0; int total = 0; for(node = mpd_data_get_first(data);node != NULL; node = (MpdData *)mpd_data_get_next_real(node, FALSE)) total++; for(node = mpd_data_get_first(data); node != NULL; node = mpd_data_get_next(node)) { int i = 0; MpdData *data2 =NULL; mpd_database_search_start(connection, TRUE); mpd_database_search_add_constraint(connection, tag,node->tag); data2 = mpd_database_search_commit(connection); for(data2 = mpd_data_get_first(data2); data2; data2 = mpd_data_get_next(data2)) i+=data2->song->time; gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, i, 1,node->tag, -1); max_i = MAX(max_i, i); /** * Update view */ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb),hits/(double)total); while(gtk_events_pending()) gtk_main_iteration(); hits++; if(!mpd_check_connected(connection)) { mpd_data_free(data); gtk_list_store_clear(GTK_LIST_STORE(model)); gtk_widget_hide(pb); gtk_tree_view_set_model(GTK_TREE_VIEW(serverstats_tree), model); gtk_tree_view_set_search_column(GTK_TREE_VIEW(serverstats_tree), 1); gtk_widget_set_sensitive(GTK_WIDGET(box), TRUE); return; } } if(gtk_tree_model_get_iter_first(model, &iter)) { do{ gint i; gchar *value = NULL; gtk_tree_model_get(model, &iter, 0, &i, -1); gint d = (gint)100*(i/(double)max_i); value = serverstats_format_time(i); gtk_list_store_set(GTK_LIST_STORE(model), &iter, 2, d, 3,value,-1); g_free(value); }while(gtk_tree_model_iter_next(model, &iter)); } gtk_widget_hide(pb); gtk_tree_view_set_model(GTK_TREE_VIEW(serverstats_tree), model); gtk_tree_view_set_search_column(GTK_TREE_VIEW(serverstats_tree), 1); gtk_widget_set_sensitive(GTK_WIDGET(box), TRUE); } static gboolean serverstats_body_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { cairo_t *cr= gdk_cairo_create(GTK_WIDGET(widget)->window); cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width (cr, 1); cairo_rectangle(cr, event->area.x,event->area.y,event->area.width, event->area.height); gdk_cairo_set_source_color(cr, &(widget->style->base[GTK_STATE_NORMAL])); cairo_fill(cr); gtk_paint_shadow(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_IN,&(event->area), widget, "scrolled_window", widget->allocation.x , widget->allocation.y, widget->allocation.width, widget->allocation.height); cairo_destroy(cr); return FALSE; } static void serverstats_header_style_changed(GtkWidget *vbox, GtkStyle *style, GtkWidget *vp) { gtk_widget_modify_bg(vp,GTK_STATE_NORMAL, &(GTK_WIDGET(vbox)->style->light[GTK_STATE_SELECTED])); } static void serverstats_init() { /** Get an allready exposed widgets to grab theme colors from. */ GtkWidget *colw = (GtkWidget *)playlist3_get_category_tree_view(); GtkWidget *label = NULL; GtkWidget *table = NULL; GtkWidget *event = NULL; GtkWidget *serverstats_vbox = gtk_vbox_new(FALSE, 0); serverstats_event = gtk_event_box_new(); gtk_widget_set_app_paintable(serverstats_event,TRUE); g_signal_connect(G_OBJECT(serverstats_event), "expose-event", G_CALLBACK(serverstats_body_expose_event), NULL); gtk_container_add(GTK_CONTAINER(serverstats_event),serverstats_vbox); gtk_container_set_border_width(GTK_CONTAINER(serverstats_vbox),2); /* wrap in event box to set bg color */ event = gtk_event_box_new(); gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(colw->style->light[GTK_STATE_SELECTED])); g_signal_connect(G_OBJECT(serverstats_vbox), "style-set", G_CALLBACK(serverstats_header_style_changed), event); /* set label and padding */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label),12,12); gtk_label_set_markup(GTK_LABEL(label), "Statistics"); gtk_container_add(GTK_CONTAINER(event), label); gtk_box_pack_start(GTK_BOX(serverstats_vbox),event, FALSE, TRUE, 0); gtk_widget_show_all(event); label = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(serverstats_vbox),label, FALSE, TRUE, 0); gtk_widget_show(label); /** * Data list */ table = gtk_table_new(SERVERSTATS_NUM_FIELDS+2, 2,FALSE); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_table_set_row_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 12); /** Database */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_label_set_markup(GTK_LABEL(label), "Server"); gtk_table_attach(GTK_TABLE(table),label, 0,2,0,1,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd version */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Version:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,1,2,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_VERSION]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,1,2,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd Uptime */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Uptime:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_UPTIME]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd Playtime */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Time Playing:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,3,4,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_PLAYTIME]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,3,4,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Database */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_label_set_markup(GTK_LABEL(label), "Database"); gtk_table_attach(GTK_TABLE(table),label, 0,2,4,5,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd Playtime */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Total playtime:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,5,6,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_DB_PLAYTIME]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,5,6,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd Artists*/ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Number of artists:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,6,7,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_DB_ARTISTS]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,6,7,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd Albums */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Number of albums:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,7,8,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_DB_ALBUMS]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,7,8,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** Mpd Songs */ label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_misc_set_padding(GTK_MISC(label), 12,0); gtk_label_set_markup(GTK_LABEL(label), "Number of songs:"); gtk_table_attach(GTK_TABLE(table),label, 0,1,8,9,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); label = serverstats_labels[SERVERSTATS_MPD_DB_SONGS]= gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table),label, 1,2,8,9,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0); /** * Add table */ gtk_box_pack_start(GTK_BOX(serverstats_vbox), table, FALSE, TRUE,0); gtk_widget_show_all(table); /** * Stats treeview */ { GtkWidget *combo = NULL; GtkWidget *sw = NULL,*tree = NULL; GtkListStore *store; GtkTreeViewColumn *column; GtkCellRenderer *renderer; int i; GtkWidget *pb = gtk_progress_bar_new(); serverstats_combo = combo = gtk_combo_box_new_text(); for(i=0;istr; g_string_free(str, FALSE); return ret; } void serverstats_plugin_init(void) { gchar *path = NULL; /* GtkIconSet *set; GtkIconFactory *factory; GdkPixbuf *pb; // factory = gtk_icon_factory_new (); path = g_strdup_printf("%s%c%s%c%s",plugin.path,G_DIR_SEPARATOR, "serverstats",G_DIR_SEPARATOR,"mpd.png"); pb = gdk_pixbuf_new_from_file (path ,NULL); set = gtk_icon_set_new_from_pixbuf (pb); gtk_icon_factory_add (factory, "serverstats-mpd", set); g_free(path); g_object_unref(pb); gtk_icon_factory_add_default (factory); */ path = g_strdup_printf("%s%c%s",plugin.path,G_DIR_SEPARATOR, "serverstats"); gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),path); g_free(path); } void serverstats_connection_changed(MpdObj *mi, int connect,void *usedata) { if(!connect && serverstats_tree) { GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(serverstats_tree)); serverstats_clear(); if(model) gtk_list_store_clear(GTK_LIST_STORE(model)); gtk_combo_box_set_active(GTK_COMBO_BOX(serverstats_combo), -1); } }