/* Gnome-Streamer * Copyright (C) <1999> Erik Walthinsen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include struct element_select_classlist { gchar *name; GSList *subclasses; GSList *factories; }; struct element_select_details { GstElementFactory *factory; GtkWidget *longname, *description, *version, *author, *copyright; }; static gint compare_name(gconstpointer a,gconstpointer b) { return (strcmp(((GstElementFactory *)a)->name, ((GstElementFactory *)b)->name)); } gint str_compare(gconstpointer a,gconstpointer b) { return (strcmp((gchar *)a,(gchar *)b)); } /* this function creates a GtkCTreeNode with the contents of the classtree */ static void make_ctree(GtkCTree *tree,GtkCTreeNode *parent, struct element_select_classlist *class) { GSList *traverse; GtkCTreeNode *classnode, *node = NULL; gchar *data[2]; data[0] = g_strdup(class->name); data[1] = NULL; classnode = gtk_ctree_insert_node(tree,parent,NULL,data,0, NULL,NULL,NULL,NULL,FALSE,TRUE); gtk_ctree_node_set_selectable(tree,classnode,FALSE); traverse = class->subclasses; while (traverse) { make_ctree(tree,classnode, (struct element_select_classlist *)(traverse->data)); traverse = g_slist_next(traverse); } traverse = class->factories; while (traverse) { GstElementFactory *factory = (GstElementFactory *)(traverse->data); data[0] = g_strdup(factory->name); data[1] = g_strdup(factory->details->description); node = gtk_ctree_insert_node(tree,classnode,NULL,data,0, NULL,NULL,NULL,NULL,TRUE,FALSE); gtk_ctree_node_set_row_data_full(tree,node,factory,NULL); traverse = g_slist_next(traverse); } } static void ctree_select(GtkWidget *widget,gint row,gint column, GdkEventButton *bevent,gpointer data) { GtkCTree *tree = GTK_CTREE(widget); GtkCTreeNode *node; GstElementFactory *factory; struct element_select_details *details; node = gtk_ctree_node_nth(tree,row); factory = (GstElementFactory *)gtk_ctree_node_get_row_data(tree,node); if (!factory) return; details = (struct element_select_details *)data; details->factory = factory; gtk_entry_set_text(GTK_ENTRY(details->longname), factory->details->longname); gtk_entry_set_text(GTK_ENTRY(details->description), factory->details->description); gtk_entry_set_text(GTK_ENTRY(details->version), factory->details->version); gtk_entry_set_text(GTK_ENTRY(details->author), factory->details->author); gtk_entry_set_text(GTK_ENTRY(details->copyright), factory->details->copyright); if (bevent && bevent->type == GDK_2BUTTON_PRESS) gtk_main_quit(); } GstElementFactory *element_select_dialog() { GtkWidget *dialog; gchar *titles[2]; GtkWidget *ctree; GtkWidget *scroller; GtkTable *table; GtkWidget *detailslabel; GtkWidget *detailshsep; GtkWidget *longname, *description, *version, *author, *copyright; GList *elements; GstElementFactory *element; gchar **classes, **class; GSList *classlist; GSList *classtree, *treewalk; GSList **curlist; struct element_select_classlist *branch; struct element_select_details details; /* first create the dialog and associated stuff */ dialog = gnome_dialog_new("Select Element", GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); gnome_dialog_set_close(GNOME_DIALOG(dialog),TRUE); gnome_dialog_close_hides(GNOME_DIALOG(dialog),TRUE); gnome_dialog_set_default(GNOME_DIALOG(dialog),GNOME_OK); titles[0] = "Element "; titles[1] = "Description"; ctree = gtk_ctree_new_with_titles(2,0,titles); gtk_widget_set_usize(ctree,400,350); scroller = gtk_scrolled_window_new(NULL,NULL); gtk_container_add(GTK_CONTAINER(scroller),ctree); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller), GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),scroller, TRUE,TRUE,0); /* create the details table and put a title on it */ table = GTK_TABLE(gtk_table_new(2,7,FALSE)); detailslabel = gtk_label_new("Element Details:"); gtk_misc_set_alignment(GTK_MISC(detailslabel),0.0,0.5); gtk_table_attach(table,detailslabel,0,2,0,1,GTK_FILL|GTK_EXPAND,0,0,0); /* then a separator to keep the title separate */ detailshsep = gtk_hseparator_new(); gtk_table_attach(table,detailshsep,0,2,1,2,GTK_FILL|GTK_EXPAND,0,0,0); /* the long name of the element */ longname = gtk_label_new("Name:"); gtk_misc_set_alignment(GTK_MISC(longname),1.0,0.5); gtk_table_attach(table,longname,0,1,2,3,GTK_FILL,0,5,0); details.longname = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(details.longname),FALSE); gtk_table_attach(table,details.longname,1,2,2,3,GTK_FILL|GTK_EXPAND,0,0,0); /* the description */ description = gtk_label_new("Description:"); gtk_misc_set_alignment(GTK_MISC(description),1.0,0.5); gtk_table_attach(table,description,0,1,3,4,GTK_FILL,0,5,0); details.description = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(details.description),FALSE); gtk_table_attach(table,details.description,1,2,3,4,GTK_FILL|GTK_EXPAND,0,0,0); /* the version */ version = gtk_label_new("Version:"); gtk_misc_set_alignment(GTK_MISC(version),1.0,0.5); gtk_table_attach(table,version,0,1,4,5,GTK_FILL,0,5,0); details.version = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(details.version),FALSE); gtk_table_attach(table,details.version,1,2,4,5,GTK_FILL|GTK_EXPAND,0,0,0); /* the author */ author = gtk_label_new("Author:"); gtk_misc_set_alignment(GTK_MISC(author),1.0,0.5); gtk_table_attach(table,author,0,1,6,7,GTK_FILL,0,5,0); details.author = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(details.author),FALSE); gtk_table_attach(table,details.author,1,2,6,7,GTK_FILL|GTK_EXPAND,0,0,0); /* the copyright */ copyright = gtk_label_new("Copyright:"); gtk_misc_set_alignment(GTK_MISC(copyright),1.0,0.5); gtk_table_attach(table,copyright,0,1,7,8,GTK_FILL,0,5,0); details.copyright = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(details.copyright),FALSE); gtk_table_attach(table,details.copyright,1,2,7,8,GTK_FILL|GTK_EXPAND,0,0,0); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),GTK_WIDGET(table), TRUE,TRUE,0); /* first create a sorted (by class) tree of all the factories */ classtree = NULL; elements = gst_elementfactory_get_list(); while (elements) { element = (GstElementFactory *)(elements->data); /* split up the factory's class */ classes = g_strsplit(element->details->class,"/",0); class = classes; curlist = &classtree; /* walk down the class tree to find where to place this element */ /* the goal is for treewalk to point to the right class branch */ /* when we exit this thing, branch is pointing where we want */ while (*class) { treewalk = *curlist; /* walk the current level of class to see if we have the class */ while (treewalk) { branch = (struct element_select_classlist *)(treewalk->data); /* see if this class matches what we're looking for */ if (!strcmp(branch->name,*class)) { /* if so, we progress down the list into this one's list */ curlist = &branch->subclasses; break; } treewalk = g_slist_next(treewalk); } /* if treewalk == NULL, it wasn't in the list. add one */ if (treewalk == NULL) { /* curlist is pointer to list */ branch = g_new0(struct element_select_classlist,1); branch->name = g_strdup(*class); *curlist = g_slist_insert_sorted(*curlist,branch,str_compare); curlist = &branch->subclasses; } class++; } /* theoretically branch points where we want now */ branch->factories = g_slist_insert_sorted(branch->factories,element, compare_name); elements = g_list_next(elements); } /* now fill in the ... */ gtk_clist_freeze(GTK_CLIST(ctree)); treewalk = classtree; while (treewalk) { make_ctree(GTK_CTREE(ctree),NULL, (struct element_select_classlist *)(treewalk->data)); treewalk = g_slist_next(treewalk); } gtk_clist_thaw(GTK_CLIST(ctree)); gtk_signal_connect(GTK_OBJECT(ctree),"select_row", GTK_SIGNAL_FUNC(ctree_select),&details); gtk_widget_show_all(GTK_WIDGET(dialog)); details.factory = NULL; if (gnome_dialog_run_and_close(GNOME_DIALOG(dialog)) == GNOME_CANCEL) return NULL; else return details.factory; }; /* this is available so we can do a quick test of this thing */ #ifdef ELEMENTSELECT_MAIN int main(int argc,char *argv[]) { GstElementFactory *chosen; gst_init(&argc,&argv); gst_plugin_load_all(); gnome_init("elementselect_test","0.0.0",argc,argv); chosen = element_select_dialog(); if (chosen) g_print("selected '%s'\n",chosen->name); else g_print("didn't choose any\n"); exit(0); } #endif /* ELEMENTSELECT_MAIN */