From 799b71233855a09f87d3f23c8bf1daa803129fee Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Tue, 23 Oct 2001 17:43:49 +0000 Subject: [PATCH] this is a major update which adds a tree view of the pipeline and lets you set individual element args through a dyna... Original commit message from CVS: this is a major update which adds a tree view of the pipeline and lets you set individual element args through a dynamically generated gui. If you haven't tried this tool yet then try it now. The next step will be to add gui generation for dynamic params as well. Please email feedback and bug reports to the list --- tools/gstreamer-guilaunch.c | 365 ++++++++++++++++++++++++++++++++++-- 1 file changed, 345 insertions(+), 20 deletions(-) diff --git a/tools/gstreamer-guilaunch.c b/tools/gstreamer-guilaunch.c index ef8745333b..ce5e23c7b3 100644 --- a/tools/gstreamer-guilaunch.c +++ b/tools/gstreamer-guilaunch.c @@ -13,6 +13,7 @@ GtkWidget *start_but, *pause_but, *parse_but, *status; GtkWidget *window; +GtkWidget *prop_box, *dparam_box; GstElement *pipeline; typedef void (*found_handler) (GstElement *element, gint xid, void *priv); @@ -33,7 +34,7 @@ load_history(GtkWidget *pipe_combo) int history_fd; struct stat statbuf; - gchar *map, *current, *next, *entry; + gchar *map, *current, *next, *entry, *last_entry = ""; gchar *history_filename; gint num_entries = 0, entries_limit = 50; GList *history = NULL; @@ -62,10 +63,17 @@ load_history(GtkWidget *pipe_combo) while (current){ if ((next = strstr(current, "\n"))){ - // show entries_limit of the newest entries - if (num_entries-- < entries_limit){ - entry = g_strndup(current, next - current); - history = g_list_prepend(history, entry); + entry = g_strndup(current, next - current); + if ((strlen(entry) == strlen(last_entry)) && strstr(entry, last_entry)){ + g_free(entry); + } + else{ + // show entries_limit of the newest entries + if (num_entries-- < entries_limit){ + entry = g_strndup(current, next - current); + last_entry = entry; + history = g_list_prepend(history, entry); + } } current = next + 1; } @@ -121,7 +129,7 @@ build_debug_page(GtkWidget *notebook) debug_box = gtk_vbox_new(TRUE, 0); debug_buts = gtk_hbox_new(TRUE, 0); - gtk_box_pack_start(GTK_BOX(debug_box),debug_buts,TRUE,TRUE,0); + gtk_box_pack_start(GTK_BOX(debug_box),debug_buts,FALSE,FALSE,0); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), debug_box); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); @@ -221,19 +229,294 @@ xid_handler (GstElement *element, gint xid, void *priv) gtk_object_set_data(GTK_OBJECT(element), "gtk_socket", gtk_socket); } +void +prop_change_callback(GtkWidget *widget, GstElement *element) +{ + gchar *prop_name = gtk_object_get_data(GTK_OBJECT(widget), "prop_name"); + GType prop_type = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(widget), "prop_type")); + GValue *value = g_new0(GValue,1); + g_value_init (value, prop_type); + + g_print("prop %s changed in %s\n", prop_name, gst_element_get_name(element)); + + + switch (prop_type) { + case G_TYPE_STRING: + g_print("setting string\n"); + g_object_set(G_OBJECT(element),prop_name,gtk_entry_get_text(GTK_ENTRY(widget)), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_entry_set_text(GTK_ENTRY(widget), g_value_get_string(value)); + break; + case G_TYPE_BOOLEAN: + g_print("setting bool\n"); + g_object_set(G_OBJECT(element),prop_name,gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), g_value_get_boolean(value)); + break; + case G_TYPE_ULONG: + g_print("setting ulong\n"); + g_object_set(G_OBJECT(element),prop_name,(gulong)(GTK_ADJUSTMENT(widget)->value), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_adjustment_set_value(GTK_ADJUSTMENT(widget), (gfloat)g_value_get_ulong(value)); + break; + case G_TYPE_LONG: + g_print("setting long\n"); + g_object_set(G_OBJECT(element),prop_name,(glong)(GTK_ADJUSTMENT(widget)->value), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_adjustment_set_value(GTK_ADJUSTMENT(widget), (gfloat)g_value_get_long(value)); + break; + case G_TYPE_UINT: + g_print("setting uint\n"); + g_object_set(G_OBJECT(element),prop_name,(guint)(GTK_ADJUSTMENT(widget)->value), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_adjustment_set_value(GTK_ADJUSTMENT(widget), (gfloat)g_value_get_uint(value)); + break; + case G_TYPE_INT: + g_print("setting int\n"); + g_object_set(G_OBJECT(element),prop_name,(gint)(GTK_ADJUSTMENT(widget)->value), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_adjustment_set_value(GTK_ADJUSTMENT(widget), (gfloat)g_value_get_int(value)); + break; + case G_TYPE_FLOAT: + g_print("setting float\n"); + g_object_set(G_OBJECT(element),prop_name,(GTK_ADJUSTMENT(widget)->value), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_adjustment_set_value(GTK_ADJUSTMENT(widget), g_value_get_float(value)); + break; + case G_TYPE_DOUBLE: + g_print("setting double\n"); + g_object_set(G_OBJECT(element),prop_name,(gdouble)(GTK_ADJUSTMENT(widget)->value), NULL); + g_object_get_property(G_OBJECT(element),prop_name,value); + gtk_adjustment_set_value(GTK_ADJUSTMENT(widget), (gfloat)g_value_get_double(value)); + break; + case G_TYPE_ENUM:{ + GtkWidget *menu_item = gtk_menu_get_active(GTK_MENU(widget)); + g_print("setting enum\n"); + g_object_set(G_OBJECT(element),prop_name, + GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(menu_item), "enum_val")), + NULL); + } + break; + default: + break; + } + g_free(value); +} + +void +build_props_box(GstElement *element) +{ + GParamSpec **property_specs; + GValue *value; + gint num_properties,i; + GtkWidget *prop_table; + GtkWidget *prop_label, *prop_align; + GtkWidget *prop_attach_widget; + GtkObject *prop_object; + + const gchar *element_name, *prop_name, *short_name; + + element_name = gst_element_get_name(element); + + property_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS (element), &num_properties); + + prop_table = gtk_table_new(num_properties, 2, FALSE); + gtk_box_pack_start(GTK_BOX(prop_box),prop_table,FALSE,FALSE,0); + + for (i=0;ivalue_type); + prop_name = property_specs[i]->name; + if (strstr(prop_name, "::")){ + short_name = strstr(prop_name, "::") + 2; + } + else { + short_name = prop_name; + } + prop_label = gtk_label_new(short_name); + + + g_object_get_property(G_OBJECT(element),prop_name,value); + prop_align = gtk_alignment_new(1, 0, 0, 0); + gtk_container_add(GTK_CONTAINER(prop_align), prop_label); + gtk_table_attach(GTK_TABLE(prop_table), prop_align, 0, 1, i, i+1, GTK_FILL, GTK_SHRINK, 5, 3); + prop_object = NULL; + prop_attach_widget = NULL; + + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + g_print("got string %s for %s\n", prop_name, element_name); + prop_object = GTK_OBJECT(gtk_entry_new()); + if (g_value_get_string(value)){ + gtk_entry_set_text(GTK_ENTRY(prop_object), g_value_get_string(value)); + } + signal_name = "activate"; + prop_attach_widget = GTK_WIDGET(prop_object); + break; + case G_TYPE_BOOLEAN: + g_print("got bool %s for %s\n", prop_name, element_name); + prop_object = GTK_OBJECT(gtk_check_button_new()); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(prop_object), g_value_get_boolean(value)); + signal_name = "toggled"; + prop_attach_widget = GTK_WIDGET(prop_object); + break; + case G_TYPE_ULONG: + g_print("got ulong %s for %s\n", prop_name, element_name); + prop_object = gtk_adjustment_new(g_value_get_ulong(value), 0, (gfloat)G_MAXLONG * 2.0, 1, 10, 10); + signal_name = "value-changed"; + prop_attach_widget = gtk_spin_button_new(GTK_ADJUSTMENT(prop_object), 1, 0); + break; + case G_TYPE_LONG: + g_print("got long %s for %s\n", prop_name, element_name); + prop_object = gtk_adjustment_new(g_value_get_long(value), G_MINLONG, G_MAXLONG, 1, 10, 10); + signal_name = "value-changed"; + prop_attach_widget = gtk_spin_button_new(GTK_ADJUSTMENT(prop_object), 1, 0); + break; + case G_TYPE_UINT: + g_print("got uint %s for %s\n", prop_name, element_name); + prop_object = gtk_adjustment_new(g_value_get_uint(value), 0, (gfloat)G_MAXINT * 2.0, 1, 10, 10); + prop_attach_widget = gtk_spin_button_new(GTK_ADJUSTMENT(prop_object), 1, 0); + signal_name = "value-changed"; + break; + case G_TYPE_INT: + g_print("got int %s for %s\n", prop_name, element_name); + prop_object = gtk_adjustment_new(g_value_get_int(value), G_MININT, G_MAXINT, 1, 10, 10); + prop_attach_widget = gtk_spin_button_new(GTK_ADJUSTMENT(prop_object), 1, 0); + signal_name = "value-changed"; + break; + case G_TYPE_FLOAT: + g_print("got float %s for %s\n", prop_name, element_name); + prop_object = gtk_adjustment_new(g_value_get_float(value), G_MINFLOAT, G_MAXFLOAT, 1, 10, 10); + prop_attach_widget = gtk_spin_button_new(GTK_ADJUSTMENT(prop_object), 1, 3); + signal_name = "value-changed"; + break; + case G_TYPE_DOUBLE: + g_print("got double %s for %s\n", prop_name, element_name); + prop_object = gtk_adjustment_new(g_value_get_double(value), G_MINDOUBLE, G_MAXDOUBLE, 1, 10, 10); + prop_attach_widget = gtk_spin_button_new(GTK_ADJUSTMENT(prop_object), 1, 3); + signal_name = "value-changed"; + break; + default: + if (G_IS_PARAM_SPEC_ENUM (property_specs[i])) { + GEnumValue *values; + guint j = 0; + g_print("got enum %s for %s\n", prop_name, element_name); + g_value_init (value, G_TYPE_ENUM); + prop_attach_widget = gtk_option_menu_new(); + prop_object = GTK_OBJECT(gtk_menu_new()); + gtk_option_menu_set_menu(GTK_OPTION_MENU(prop_attach_widget), GTK_WIDGET(prop_object)); + signal_name = "selection-done"; + //FIXME when the shim is dead + values = gtk_type_enum_get_values (property_specs[i]->value_type); + + while (values[j].value_name) { + GtkWidget *menu_item; + menu_item = gtk_menu_item_new_with_label(values[j].value_nick); + gtk_menu_append(GTK_MENU(prop_object), menu_item); + gtk_object_set_data(GTK_OBJECT(menu_item), "enum_val", GINT_TO_POINTER(values[j].value)); + if (values[j].value == g_value_get_enum(value)){ + gtk_menu_shell_select_item(GTK_MENU_SHELL(prop_object), menu_item); + gtk_menu_shell_activate_item(GTK_MENU_SHELL(prop_object), menu_item, FALSE); + } + j++; + } + } + break; + } + if (prop_attach_widget){ + gtk_table_attach_defaults(GTK_TABLE(prop_table), prop_attach_widget, 1, 2, i, i+1); + gtk_widget_show(prop_attach_widget); + } + if (property_specs[i]->flags & G_PARAM_WRITABLE){ + if (prop_object){ + gtk_signal_connect (prop_object, signal_name, + GTK_SIGNAL_FUNC (prop_change_callback), element); + gtk_object_set_data(prop_object, "prop_name", g_strdup(short_name)); + gtk_object_set_data(prop_object, "prop_type", GINT_TO_POINTER(G_VALUE_TYPE (value))); + } + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(prop_attach_widget), FALSE); + } + g_free(value); + gtk_widget_show_all(prop_table); + } +} +void +select_child_callback(GtkWidget *tree_item, GstElement *element) +{ + build_props_box(element); +} + +void +clear_edit_panes(GtkWidget *widget, gpointer *data) +{ + GList *children; + + children = gtk_container_children(GTK_CONTAINER(prop_box)); + while (children){ + gtk_container_remove(GTK_CONTAINER(prop_box), GTK_WIDGET(children->data)); + children = g_list_next (children); + } +/* + children = gtk_container_children(GTK_CONTAINER(dparam_box)); + while (children){ + gtk_container_remove(GTK_CONTAINER(prop_box), GTK_WIDGET(children->data)); + children = g_list_next (children); + } +*/ +} + +void +build_tree(GtkWidget *tree_item, GstBin *bin){ + GList *children; + GtkWidget *tree, *item; + + if (GTK_TREE_ITEM_SUBTREE(tree_item) != NULL){ + gtk_tree_item_remove_subtree(GTK_TREE_ITEM(tree_item)); + } + + tree = gtk_tree_new(); + gtk_tree_item_set_subtree(GTK_TREE_ITEM(tree_item), tree); + gtk_widget_show(tree); + + children = gst_bin_get_list(bin); + + while (children) { + GstElement *child; + + child = GST_ELEMENT (children->data); + children = g_list_next (children); + + item = gtk_tree_item_new_with_label(gst_element_get_name(child)); + gtk_object_set_data(GTK_OBJECT(item), "tree", tree); + gtk_signal_connect (GTK_OBJECT (item), "select", + GTK_SIGNAL_FUNC (select_child_callback), child); + gtk_signal_connect (GTK_OBJECT (item), "deselect", + GTK_SIGNAL_FUNC (clear_edit_panes), child); + + + gtk_tree_append(GTK_TREE(tree), item); + gtk_widget_show(item); + + if (GST_IS_BIN (child)){ + build_tree(item, GST_BIN(child)); + gtk_tree_item_expand(GTK_TREE_ITEM(item)); + } + } +} + void parse_callback( GtkWidget *widget, GtkWidget *pipe_combo) { GList *history = (GList*)gtk_object_get_data(GTK_OBJECT(pipe_combo), "history"); FILE *history_file = (FILE*)gtk_object_get_data(GTK_OBJECT(pipe_combo), "history_file"); - + GtkWidget *tree_item = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(widget), "tree_item"); + gchar *last_pipe = (gchar*)gtk_object_get_data(GTK_OBJECT(widget), "last_pipe"); gchar *try_pipe = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(pipe_combo)->entry)); - gchar *write_pipe = g_strdup_printf("%s\n", try_pipe); - - fwrite(write_pipe, sizeof(gchar), strlen(write_pipe), history_file); - fflush(history_file); - + if (pipeline){ g_print("unreffing\n"); gst_object_unref (GST_OBJECT (pipeline)); @@ -244,9 +527,19 @@ parse_callback( GtkWidget *widget, gst_parse_launch (try_pipe, GST_BIN (pipeline)); gtk_widget_set_sensitive(GTK_WIDGET(start_but), TRUE); - history = g_list_prepend(history, try_pipe); - gtk_combo_set_popdown_strings(GTK_COMBO(pipe_combo), history); - g_free(write_pipe); + build_tree(tree_item, GST_BIN(pipeline)); + + if (last_pipe==NULL || !((strlen(try_pipe) == strlen(last_pipe)) && strstr(try_pipe, last_pipe))){ + gchar *write_pipe = g_strdup_printf("%s\n", try_pipe); + gtk_object_set_data(GTK_OBJECT(widget), "last_pipe", try_pipe); + fwrite(write_pipe, sizeof(gchar), strlen(write_pipe), history_file); + fflush(history_file); + history = g_list_prepend(history, try_pipe); + gtk_combo_set_popdown_strings(GTK_COMBO(pipe_combo), history); + g_free(write_pipe); + g_free(last_pipe); + } + } void @@ -254,7 +547,6 @@ start_callback( GtkWidget *widget, gpointer data ) { GtkWidget *pipe_combo = gtk_object_get_data(GTK_OBJECT(widget), "pipe_combo"); - gchar *try_pipe = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(pipe_combo)->entry)); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){ gtk_widget_set_sensitive(GTK_WIDGET(pause_but), TRUE); @@ -296,7 +588,8 @@ pause_callback( GtkWidget *widget, int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *vbox; - GtkWidget *parse_line, *pipe_combo, *notebook; + GtkWidget *parse_line, *pipe_combo, *notebook, *pane; + GtkWidget *tree_root, *tree_root_item, *page_scroll; gst_init(&argc,&argv); @@ -332,13 +625,45 @@ int main(int argc,char *argv[]) { GTK_SIGNAL_FUNC (pause_callback), NULL); gtk_signal_connect (GTK_OBJECT (parse_but), "clicked", GTK_SIGNAL_FUNC (parse_callback), pipe_combo); - + gtk_signal_connect (GTK_OBJECT (parse_but), "clicked", + GTK_SIGNAL_FUNC (clear_edit_panes), NULL); + + gtk_object_set_data(GTK_OBJECT(start_but), "pipe_combo", pipe_combo); - notebook = gtk_notebook_new(); - gtk_box_pack_start(GTK_BOX(vbox),notebook,TRUE,TRUE,0); + tree_root = gtk_tree_new(); + + tree_root_item = gtk_tree_item_new_with_label("pipe"); + gtk_tree_append(GTK_TREE(tree_root), tree_root_item); + gtk_object_set_data(GTK_OBJECT(parse_but), "tree_item", tree_root_item); + gtk_tree_item_expand(GTK_TREE_ITEM(tree_root_item)); + + prop_box = gtk_vbox_new(FALSE, 0); + //dparam_box = gtk_vbox_new(FALSE, 0); + notebook = gtk_notebook_new(); + + page_scroll = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(page_scroll), prop_box); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_scroll, gtk_label_new("Properties")); +/* + page_scroll = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(page_scroll), dparam_box); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_scroll, gtk_label_new("Dynamic Params")); +*/ build_debug_page(notebook); + + page_scroll = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(page_scroll), tree_root); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + pane = gtk_hpaned_new(); + gtk_paned_pack1 (GTK_PANED (pane), page_scroll, TRUE, TRUE); + gtk_paned_pack2 (GTK_PANED (pane), notebook, TRUE, TRUE); + + gtk_box_pack_start(GTK_BOX(vbox),pane,TRUE,TRUE,0); status = gtk_label_new("stopped"); gtk_box_pack_start(GTK_BOX(vbox),status,FALSE,FALSE,0);