1 /* Gnome-Streamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
21 #include <gst/gst.h>
22 #include <gnome.h>
24 struct element_select_classlist {
25 gchar *name;
26 GSList *subclasses;
27 GSList *factories;
28 };
30 struct element_select_details {
31 GstElementFactory *factory;
32 GtkWidget *longname, *description, *version, *author, *copyright;
33 };
35 static gint compare_name(gconstpointer a,gconstpointer b) {
36 return (strcmp(((GstElementFactory *)a)->name,
37 ((GstElementFactory *)b)->name));
38 }
40 gint str_compare(gconstpointer a,gconstpointer b) {
41 return (strcmp((gchar *)a,(gchar *)b));
42 }
44 /* this function creates a GtkCTreeNode with the contents of the classtree */
45 static void make_ctree(GtkCTree *tree,GtkCTreeNode *parent,
46 struct element_select_classlist *class) {
47 GSList *traverse;
48 GtkCTreeNode *classnode, *node = NULL;
49 gchar *data[2];
51 data[0] = g_strdup(class->name);
52 data[1] = NULL;
53 classnode = gtk_ctree_insert_node(tree,parent,NULL,data,0,
54 NULL,NULL,NULL,NULL,FALSE,TRUE);
55 gtk_ctree_node_set_selectable(tree,classnode,FALSE);
57 traverse = class->subclasses;
58 while (traverse) {
59 make_ctree(tree,classnode,
60 (struct element_select_classlist *)(traverse->data));
61 traverse = g_slist_next(traverse);
62 }
64 traverse = class->factories;
65 while (traverse) {
66 GstElementFactory *factory = (GstElementFactory *)(traverse->data);
67 data[0] = g_strdup(factory->name);
68 data[1] = g_strdup(factory->details->description);
69 node = gtk_ctree_insert_node(tree,classnode,NULL,data,0,
70 NULL,NULL,NULL,NULL,TRUE,FALSE);
71 gtk_ctree_node_set_row_data_full(tree,node,factory,NULL);
72 traverse = g_slist_next(traverse);
73 }
74 }
76 static void ctree_select(GtkWidget *widget,gint row,gint column,
77 GdkEventButton *bevent,gpointer data) {
78 GtkCTree *tree = GTK_CTREE(widget);
79 GtkCTreeNode *node;
80 GstElementFactory *factory;
81 struct element_select_details *details;
82 node = gtk_ctree_node_nth(tree,row);
83 factory = (GstElementFactory *)gtk_ctree_node_get_row_data(tree,node);
84 if (!factory)
85 return;
86 details = (struct element_select_details *)data;
87 details->factory = factory;
89 gtk_entry_set_text(GTK_ENTRY(details->longname),
90 factory->details->longname);
91 gtk_entry_set_text(GTK_ENTRY(details->description),
92 factory->details->description);
93 gtk_entry_set_text(GTK_ENTRY(details->version),
94 factory->details->version);
95 gtk_entry_set_text(GTK_ENTRY(details->author),
96 factory->details->author);
97 gtk_entry_set_text(GTK_ENTRY(details->copyright),
98 factory->details->copyright);
100 if (bevent && bevent->type == GDK_2BUTTON_PRESS)
101 gtk_main_quit();
102 }
105 GstElementFactory *element_select_dialog() {
106 GtkWidget *dialog;
107 gchar *titles[2];
108 GtkWidget *ctree;
109 GtkWidget *scroller;
110 GtkTable *table;
111 GtkWidget *detailslabel;
112 GtkWidget *detailshsep;
113 GtkWidget *longname, *description, *version, *author, *copyright;
115 GList *elements;
116 GstElementFactory *element;
117 gchar **classes, **class;
118 GSList *classlist;
119 GSList *classtree, *treewalk;
120 GSList **curlist;
121 struct element_select_classlist *branch;
122 struct element_select_details details;
124 /* first create the dialog and associated stuff */
125 dialog = gnome_dialog_new("Select Element",
126 GNOME_STOCK_BUTTON_OK,
127 GNOME_STOCK_BUTTON_CANCEL,
128 NULL);
129 gnome_dialog_set_close(GNOME_DIALOG(dialog),TRUE);
130 gnome_dialog_close_hides(GNOME_DIALOG(dialog),TRUE);
131 gnome_dialog_set_default(GNOME_DIALOG(dialog),GNOME_OK);
133 titles[0] = "Element ";
134 titles[1] = "Description";
135 ctree = gtk_ctree_new_with_titles(2,0,titles);
136 gtk_widget_set_usize(ctree,400,350);
138 scroller = gtk_scrolled_window_new(NULL,NULL);
139 gtk_container_add(GTK_CONTAINER(scroller),ctree);
140 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller),
141 GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
142 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),scroller,
143 TRUE,TRUE,0);
145 /* create the details table and put a title on it */
146 table = GTK_TABLE(gtk_table_new(2,7,FALSE));
147 detailslabel = gtk_label_new("Element Details:");
148 gtk_misc_set_alignment(GTK_MISC(detailslabel),0.0,0.5);
149 gtk_table_attach(table,detailslabel,0,2,0,1,GTK_FILL|GTK_EXPAND,0,0,0);
151 /* then a separator to keep the title separate */
152 detailshsep = gtk_hseparator_new();
153 gtk_table_attach(table,detailshsep,0,2,1,2,GTK_FILL|GTK_EXPAND,0,0,0);
155 /* the long name of the element */
156 longname = gtk_label_new("Name:");
157 gtk_misc_set_alignment(GTK_MISC(longname),1.0,0.5);
158 gtk_table_attach(table,longname,0,1,2,3,GTK_FILL,0,5,0);
159 details.longname = gtk_entry_new();
160 gtk_entry_set_editable(GTK_ENTRY(details.longname),FALSE);
161 gtk_table_attach(table,details.longname,1,2,2,3,GTK_FILL|GTK_EXPAND,0,0,0);
163 /* the description */
164 description = gtk_label_new("Description:");
165 gtk_misc_set_alignment(GTK_MISC(description),1.0,0.5);
166 gtk_table_attach(table,description,0,1,3,4,GTK_FILL,0,5,0);
167 details.description = gtk_entry_new();
168 gtk_entry_set_editable(GTK_ENTRY(details.description),FALSE);
169 gtk_table_attach(table,details.description,1,2,3,4,GTK_FILL|GTK_EXPAND,0,0,0);
171 /* the version */
172 version = gtk_label_new("Version:");
173 gtk_misc_set_alignment(GTK_MISC(version),1.0,0.5);
174 gtk_table_attach(table,version,0,1,4,5,GTK_FILL,0,5,0);
175 details.version = gtk_entry_new();
176 gtk_entry_set_editable(GTK_ENTRY(details.version),FALSE);
177 gtk_table_attach(table,details.version,1,2,4,5,GTK_FILL|GTK_EXPAND,0,0,0);
179 /* the author */
180 author = gtk_label_new("Author:");
181 gtk_misc_set_alignment(GTK_MISC(author),1.0,0.5);
182 gtk_table_attach(table,author,0,1,6,7,GTK_FILL,0,5,0);
183 details.author = gtk_entry_new();
184 gtk_entry_set_editable(GTK_ENTRY(details.author),FALSE);
185 gtk_table_attach(table,details.author,1,2,6,7,GTK_FILL|GTK_EXPAND,0,0,0);
187 /* the copyright */
188 copyright = gtk_label_new("Copyright:");
189 gtk_misc_set_alignment(GTK_MISC(copyright),1.0,0.5);
190 gtk_table_attach(table,copyright,0,1,7,8,GTK_FILL,0,5,0);
191 details.copyright = gtk_entry_new();
192 gtk_entry_set_editable(GTK_ENTRY(details.copyright),FALSE);
193 gtk_table_attach(table,details.copyright,1,2,7,8,GTK_FILL|GTK_EXPAND,0,0,0);
195 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),GTK_WIDGET(table),
196 TRUE,TRUE,0);
199 /* first create a sorted (by class) tree of all the factories */
200 classtree = NULL;
201 elements = gst_elementfactory_get_list();
202 while (elements) {
203 element = (GstElementFactory *)(elements->data);
204 /* split up the factory's class */
205 classes = g_strsplit(element->details->class,"/",0);
206 class = classes;
207 curlist = &classtree;
208 /* walk down the class tree to find where to place this element */
209 /* the goal is for treewalk to point to the right class branch */
210 /* when we exit this thing, branch is pointing where we want */
211 while (*class) {
212 treewalk = *curlist;
213 /* walk the current level of class to see if we have the class */
214 while (treewalk) {
215 branch = (struct element_select_classlist *)(treewalk->data);
216 /* see if this class matches what we're looking for */
217 if (!strcmp(branch->name,*class)) {
218 /* if so, we progress down the list into this one's list */
219 curlist = &branch->subclasses;
220 break;
221 }
222 treewalk = g_slist_next(treewalk);
223 }
224 /* if treewalk == NULL, it wasn't in the list. add one */
225 if (treewalk == NULL) {
226 /* curlist is pointer to list */
227 branch = g_new0(struct element_select_classlist,1);
228 branch->name = g_strdup(*class);
229 *curlist = g_slist_insert_sorted(*curlist,branch,str_compare);
230 curlist = &branch->subclasses;
231 }
232 class++;
233 }
234 /* theoretically branch points where we want now */
235 branch->factories = g_slist_insert_sorted(branch->factories,element,
236 compare_name);
237 elements = g_list_next(elements);
238 }
240 /* now fill in the ... */
241 gtk_clist_freeze(GTK_CLIST(ctree));
242 treewalk = classtree;
243 while (treewalk) {
244 make_ctree(GTK_CTREE(ctree),NULL,
245 (struct element_select_classlist *)(treewalk->data));
246 treewalk = g_slist_next(treewalk);
247 }
248 gtk_clist_thaw(GTK_CLIST(ctree));
250 gtk_signal_connect(GTK_OBJECT(ctree),"select_row",
251 GTK_SIGNAL_FUNC(ctree_select),&details);
253 gtk_widget_show_all(GTK_WIDGET(dialog));
255 details.factory = NULL;
256 if (gnome_dialog_run_and_close(GNOME_DIALOG(dialog)) == GNOME_CANCEL)
257 return NULL;
258 else
259 return details.factory;
260 };
263 /* this is available so we can do a quick test of this thing */
264 #ifdef ELEMENTSELECT_MAIN
265 int main(int argc,char *argv[]) {
266 GstElementFactory *chosen;
268 gst_init(&argc,&argv);
269 gst_plugin_load_all();
270 gnome_init("elementselect_test","0.0.0",argc,argv);
271 chosen = element_select_dialog();
272 if (chosen)
273 g_print("selected '%s'\n",chosen->name);
274 else
275 g_print("didn't choose any\n");
276 exit(0);
277 }
278 #endif /* ELEMENTSELECT_MAIN */