summaryrefslogtreecommitdiff
path: root/editor/gsteditorelement.c
diff options
context:
space:
mode:
Diffstat (limited to 'editor/gsteditorelement.c')
-rw-r--r--editor/gsteditorelement.c927
1 files changed, 927 insertions, 0 deletions
diff --git a/editor/gsteditorelement.c b/editor/gsteditorelement.c
new file mode 100644
index 000000000..d13c40f4a
--- /dev/null
+++ b/editor/gsteditorelement.c
@@ -0,0 +1,927 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 <gnome.h>
+
+#include <gst/gst.h>
+#include <gst/gstutils.h>
+
+#include "gsteditor.h"
+
+/* class functions */
+static void gst_editor_element_class_init(GstEditorElementClass *klass);
+static void gst_editor_element_init(GstEditorElement *element);
+static void gst_editor_element_set_arg(GtkObject *object,GtkArg *arg,guint id);
+static void gst_editor_element_get_arg(GtkObject *object,GtkArg *arg,guint id);
+static void gst_editor_element_realize(GstEditorElement *element);
+static gint gst_editor_element_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ GstEditorElement *element);
+
+/* events fired by items within self */
+static gint gst_editor_element_resizebox_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ GstEditorElement *element);
+static gint gst_editor_element_group_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ GstEditorElement *element);
+static gint gst_editor_element_state_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ gpointer data);
+
+/* external events (from GstElement) */
+static void gst_editor_element_state_change(GstElement *element,
+ gint state,
+ GstEditorElement *editorelement);
+
+/* utility functions */
+static void gst_editor_element_resize(GstEditorElement *element);
+static void gst_editor_element_set_state(GstEditorElement *element,
+ gint id,gboolean set);
+static void gst_editor_element_sync_state(GstEditorElement *element);
+static void gst_editor_element_move(GstEditorElement *element,
+ gdouble dx,gdouble dy);
+
+
+static gchar *_gst_editor_element_states[] = { "C","R","D","P" };
+
+
+enum {
+ ARG_0,
+ ARG_X,
+ ARG_Y,
+ ARG_WIDTH,
+ ARG_HEIGHT,
+ ARG_X1,
+ ARG_Y1,
+ ARG_X2,
+ ARG_Y2,
+ ARG_ELEMENT,
+};
+
+enum {
+ LAST_SIGNAL
+};
+
+static GtkObjectClass *parent_class;
+static guint gst_editor_element_signals[LAST_SIGNAL] = { 0 };
+
+GtkType gst_editor_element_get_type() {
+ static GtkType element_type = 0;
+
+ if (!element_type) {
+ static const GtkTypeInfo element_info = {
+ "GstEditorElement",
+ sizeof(GstEditorElement),
+ sizeof(GstEditorElementClass),
+ (GtkClassInitFunc)gst_editor_element_class_init,
+ (GtkObjectInitFunc)gst_editor_element_init,
+ NULL,
+ NULL,
+ (GtkClassInitFunc)NULL,
+ };
+ element_type = gtk_type_unique(gtk_object_get_type(),&element_info);
+ }
+ return element_type;
+}
+
+static void gst_editor_element_class_init(GstEditorElementClass *klass) {
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*)klass;
+
+ parent_class = gtk_type_class(gtk_object_get_type());
+
+ gtk_object_add_arg_type("GstEditorElement::x",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
+ ARG_X);
+ gtk_object_add_arg_type("GstEditorElement::y",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
+ ARG_Y);
+ gtk_object_add_arg_type("GstEditorElement::width",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
+ ARG_WIDTH);
+ gtk_object_add_arg_type("GstEditorElement::height",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
+ ARG_HEIGHT);
+ gtk_object_add_arg_type("GstEditorElement::x1",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE,ARG_X1);
+ gtk_object_add_arg_type("GstEditorElement::y1",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE,ARG_Y1);
+ gtk_object_add_arg_type("GstEditorElement::x2",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE,ARG_X2);
+ gtk_object_add_arg_type("GstEditorElement::y2",GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE,ARG_Y2);
+ gtk_object_add_arg_type("GstEditorElement::element",GTK_TYPE_POINTER,
+ GTK_ARG_READABLE,ARG_ELEMENT);
+
+ klass->realize = gst_editor_element_realize;
+ klass->event = gst_editor_element_event;
+
+ object_class->set_arg = gst_editor_element_set_arg;
+ object_class->get_arg = gst_editor_element_get_arg;
+}
+
+static void gst_editor_element_init(GstEditorElement *element) {
+}
+
+GstEditorElement *gst_editor_element_new(GstEditorBin *parent,
+ GstElement *element,
+ const gchar *first_arg_name, ...) {
+ GstEditorElement *editorelement;
+ va_list args;
+
+ g_return_if_fail(parent != NULL);
+ g_return_if_fail(GST_IS_EDITOR_BIN(parent));
+ g_return_if_fail(element != NULL);
+ g_return_if_fail(GST_IS_ELEMENT(element));
+
+ editorelement = GST_EDITOR_ELEMENT(gtk_type_new(GST_TYPE_EDITOR_ELEMENT));
+ editorelement->element = element;
+
+ va_start(args,first_arg_name);
+ gst_editor_element_construct(editorelement,parent,first_arg_name,args);
+ va_end(args);
+
+ return editorelement;
+}
+
+void gst_editor_element_construct(GstEditorElement *element,
+ GstEditorBin *parent,
+ const gchar *first_arg_name,
+ va_list args) {
+ GtkObject *obj = GTK_OBJECT(element);
+ GSList *arg_list = NULL, *info_list = NULL;
+ gchar *error;
+ GstEditorElementClass *elementclass;
+
+// g_print("in gst_editor_element_construct()\n");
+
+ error = gtk_object_args_collect(GTK_OBJECT_TYPE(obj),&arg_list,
+ &info_list,first_arg_name,args);
+ if (error) {
+ g_warning("gst_editor_element_construct(): %s",error);
+ g_free(error);
+ } else {
+ GSList *arg,*info;
+// g_print("setting all the arguments on the element\n");
+ for (arg=arg_list,info=info_list;arg;arg=arg->next,info=info->next)
+ gtk_object_arg_set(obj,arg->data,info->data);
+ gtk_args_collect_cleanup(arg_list,info_list);
+ }
+
+ if (parent)
+ gst_editor_bin_add(parent,element);
+ else if (!GST_IS_EDITOR_BIN(element))
+ g_warning("floating element...\n");
+
+ elementclass = GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
+ if (elementclass->realize)
+ (elementclass->realize)(element);
+}
+
+static void gst_editor_element_set_arg(GtkObject *object,GtkArg *arg,guint id) {
+ GstEditorElement *element;
+ gdouble dx,dy,newwidth,newheight;
+
+ /* get the major types of this object */
+ element = GST_EDITOR_ELEMENT(object);
+
+ switch (id) {
+ case ARG_X:
+ element->x = GTK_VALUE_DOUBLE(*arg);
+ break;
+ case ARG_Y:
+ element->y = GTK_VALUE_DOUBLE(*arg);
+ break;
+ case ARG_WIDTH:
+ element->width = GTK_VALUE_DOUBLE(*arg);
+ element->resize = TRUE;
+ break;
+ case ARG_HEIGHT:
+ element->height = GTK_VALUE_DOUBLE(*arg);
+ element->resize = TRUE;
+ break;
+ case ARG_X1:
+ element->x = GTK_VALUE_DOUBLE(*arg);
+ element->resize = TRUE;
+ break;
+ case ARG_Y1:
+ element->y = GTK_VALUE_DOUBLE(*arg);
+ element->resize = TRUE;
+ break;
+ case ARG_X2:
+ // make sure it's big enough, grow if not
+ element->width = MAX(GTK_VALUE_DOUBLE(*arg),element->minwidth);
+ element->resize = TRUE;
+ break;
+ case ARG_Y2:
+ // make sure it's big enough, grow if not
+ element->height = MAX(GTK_VALUE_DOUBLE(*arg),element->minheight);
+ element->resize = TRUE;
+ break;
+ default:
+ g_warning("gsteditorelement: unknown arg!");
+ break;
+ }
+}
+
+static void gst_editor_element_get_arg(GtkObject *object,GtkArg *arg,guint id) {
+ GstEditorElement *element;
+
+ /* get the major types of this object */
+ element = GST_EDITOR_ELEMENT(object);
+
+ switch (id) {
+ case ARG_X:
+ GTK_VALUE_INT(*arg) = element->x + (element->width / 2.0);
+ break;
+ case ARG_Y:
+ GTK_VALUE_INT(*arg) = element->y + (element->height / 2.0);
+ break;
+ case ARG_WIDTH:
+ GTK_VALUE_INT(*arg) = element->width;
+ break;
+ case ARG_HEIGHT:
+ GTK_VALUE_INT(*arg) = element->height;
+ break;
+ case ARG_X1:
+ GTK_VALUE_INT(*arg) = element->x;
+ break;
+ case ARG_Y1:
+ GTK_VALUE_INT(*arg) = element->y;
+ break;
+ case ARG_X2:
+ GTK_VALUE_INT(*arg) = element->x + element->width;
+ break;
+ case ARG_Y2:
+ GTK_VALUE_INT(*arg) = element->y + element->height;
+ break;
+ case ARG_ELEMENT:
+ GTK_VALUE_POINTER(*arg) = element->element;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void gst_editor_element_realize(GstEditorElement *element) {
+ GnomeCanvasGroup *parentgroup;
+ gint i;
+ gdouble x1,y1,x2,y2;
+ GList *pads;
+ GstPad *pad;
+
+// g_print("realizing editor element %p\n",element);
+
+ /* we have to have a parent by this point */
+ g_return_if_fail(element->parent != NULL);
+
+ // set the state signal of the actual element
+ gtk_signal_connect(GTK_OBJECT(element->element),"state_change",
+ GTK_SIGNAL_FUNC(gst_editor_element_state_change),
+ element);
+
+ // create the bounds if we haven't had them set
+// g_print("centering element at %.2fx%.2f (%.2fx%.2f)\n",
+// element->x,element->y,element->width,element->height);
+
+ /* create the group holding all the stuff for this element */
+ parentgroup = GST_EDITOR_ELEMENT(element->parent)->group;
+ element->group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(parentgroup,
+ gnome_canvas_group_get_type(),
+ "x",element->x - (element->width / 2.0),
+ "y",element->y - (element->height / 2.0),NULL));
+// g_print("origin of group is %.2fx%.2f\n",
+// element->x - (element->width / 2.0),
+// element->y - (element->height / 2.0));
+ g_return_if_fail(element->group != NULL);
+ GST_EDITOR_SET_OBJECT(element->group,element);
+ gtk_signal_connect(GTK_OBJECT(element->group),"event",
+ GTK_SIGNAL_FUNC(gst_editor_element_group_event),element);
+
+ // calculate the inter-group coords (x1,y1,x2,y2 are convenience vars)
+ x1 = 0.0;y1 = 0.0;
+ x2 = element->width;y2 = element->height;
+
+ /* create bordering box */
+ element->border = gnome_canvas_item_new(element->group,
+ gnome_canvas_rect_get_type(),
+ "width_units",2.0,"fill_color","white","outline_color","black",
+ "x1",x1,"y1",y1,"x2",x2,"y2",y2,NULL);
+ g_return_if_fail(element->border != NULL);
+ GST_EDITOR_SET_OBJECT(element->border,element);
+
+ /* create resizing box */
+ element->resizebox = gnome_canvas_item_new(element->group,
+ gnome_canvas_rect_get_type(),
+ "width_units",1.0,"fill_color","white","outline_color","black",
+ "x1",x2-4.0,"y1",y2-4.0,"x2",x2,"y2",y2,NULL);
+ g_return_if_fail(element->resizebox != NULL);
+ GST_EDITOR_SET_OBJECT(element->resizebox,element);
+ gtk_signal_connect(GTK_OBJECT(element->resizebox),"event",
+ GTK_SIGNAL_FUNC(gst_editor_element_resizebox_event),element);
+
+ /* create the title */
+ element->title = gnome_canvas_item_new(element->group,
+ gnome_canvas_text_get_type(),
+ "text",gst_element_get_name(GST_OBJECT(element->element)),
+ "x",x1+1.0,"y",y1+1.0,"anchor",GTK_ANCHOR_NORTH_WEST,
+ "font_gdk",gtk_widget_get_default_style()->font,
+ NULL);
+ g_return_if_fail(element->title != NULL);
+ GST_EDITOR_SET_OBJECT(element->title,element);
+
+ /* create the state boxen */
+ for (i=0;i<4;i++) {
+ element->statebox[i] = gnome_canvas_item_new(element->group,
+ gnome_canvas_rect_get_type(),
+ "width_units",1.0,"fill_color","white","outline_color","black",
+ "x1",0.0,"y1",0.0,"x2",0.0,"y2",0.0,
+ NULL);
+ g_return_if_fail(element->statebox[i] != NULL);
+ GST_EDITOR_SET_OBJECT(element->statebox[i],element);
+ gtk_signal_connect(GTK_OBJECT(element->statebox[i]),"event",
+ GTK_SIGNAL_FUNC(gst_editor_element_state_event),
+ GINT_TO_POINTER(i));
+ element->statetext[i] = gnome_canvas_item_new(element->group,
+ gnome_canvas_text_get_type(),
+ "text",_gst_editor_element_states[i],
+ "x",0.0,"y",0.0,"anchor",GTK_ANCHOR_NORTH_WEST,
+ "font","-*-*-*-*-*-*-6-*-*-*-*-*-*-*",
+ NULL);
+ g_return_if_fail(element->statetext[i] != NULL);
+ GST_EDITOR_SET_OBJECT(element->statetext[i],element);
+ gtk_signal_connect(GTK_OBJECT(element->statetext[i]),"event",
+ GTK_SIGNAL_FUNC(gst_editor_element_state_event),
+ GINT_TO_POINTER(i));
+ }
+ /* and the play box (FIXME: should be icons, not text */
+ element->playbox = gnome_canvas_item_new(element->group,
+ gnome_canvas_rect_get_type(),
+ "width_units",1.0,"fill_color","white","outline_color","black",
+ "x1",0.0,"y1",0.0,"x2",0.0,"y2",0.0,
+ NULL);
+ g_return_if_fail(element->playbox != NULL);
+ GST_EDITOR_SET_OBJECT(element->playbox,element);
+ gtk_signal_connect(GTK_OBJECT(element->playbox),"event",
+ GTK_SIGNAL_FUNC(gst_editor_element_state_event),
+ GINT_TO_POINTER(4));
+ element->playtext = gnome_canvas_item_new(element->group,
+ gnome_canvas_text_get_type(),
+ "text","P",
+ "x",0.0,"y",0.0,"anchor",GTK_ANCHOR_NORTH_WEST,
+ "font","-*-*-*-*-*-*-6-*-*-*-*-*-*-*",
+ NULL);
+ g_return_if_fail(element->playtext != NULL);
+ GST_EDITOR_SET_OBJECT(element->playtext,element);
+ gtk_signal_connect(GTK_OBJECT(element->playtext),"event",
+ GTK_SIGNAL_FUNC(gst_editor_element_state_event),
+ GINT_TO_POINTER(4));
+
+ // get all the pads
+ pads = gst_element_get_pad_list(element->element);
+ while (pads) {
+ pad = GST_PAD(pads->data);
+ gst_editor_element_add_pad(element,pad);
+ pads = g_list_next(pads);
+ }
+
+ element->realized = TRUE;
+
+ // force a resize
+ element->resize = TRUE;
+ gst_editor_element_resize(element);
+
+ // recenter things on the supposed center
+// g_print("recentering element at %.2fx%.2f (%.2fx%.2f)\n",
+// element->x,element->y,element->width,element->height);
+ element->x -= (element->width / 2.0);
+ element->y -= (element->height / 2.0);
+ gnome_canvas_item_set(GNOME_CANVAS_ITEM(element->group),
+ "x",element->x,"y",element->y,NULL);
+// g_print("origin of group is %.2fx%.2f\n",element->x,element->y);
+
+ gst_editor_element_repack(element);
+}
+
+
+static void gst_editor_element_resize(GstEditorElement *element) {
+ gdouble itemwidth,itemheight;
+ gdouble groupwidth,groupheight;
+ GList *pads;
+ GstEditorPad *editorpad;
+ gint i;
+
+ if (element->resize != TRUE) return;
+ element->resize = FALSE;
+
+// g_print("resizing element\n");
+
+ element->minwidth = element->insidewidth;
+ element->minheight = element->insideheight;
+
+ // get the text size and add it into minsize
+ g_return_if_fail(element->title != NULL);
+ itemwidth = gst_util_get_double_arg(GTK_OBJECT(element->title),
+ "text_width") + 2.0;
+ itemheight = gst_util_get_double_arg(GTK_OBJECT(element->title),
+ "text_height") + 2.0;
+ element->titlewidth = itemwidth;
+ element->titleheight = itemheight;
+ element->minwidth = MAX(element->minwidth,itemwidth);
+ element->minheight += itemheight;
+
+ // now do the bottom bar
+ // find the biggest of the state chars
+ element->statewidth = 0.0;element->stateheight = 0.0;
+ for (i=0;i<4;i++) {
+ g_return_if_fail(element->statetext[i] != NULL);
+ itemwidth = gst_util_get_double_arg(GTK_OBJECT(element->statetext[i]),
+ "text_width") - 2.0;
+ itemwidth = gst_util_get_double_arg(GTK_OBJECT(element->statetext[i]),
+ "text_height");
+ element->statewidth = MAX(element->statewidth,itemwidth);
+ element->stateheight = MAX(element->stateheight,itemheight);
+ }
+ // calculate the size of the primary group
+ groupwidth = element->statewidth * 5; // 4 states plus playstate
+ groupheight = element->stateheight;
+ // add in the resize box
+ groupwidth += 7.0; // 2.0 for buffer, 5.0 for actual size
+ groupheight = MAX(groupheight,5.0);
+ // update the minsize
+ element->minwidth = MAX(element->minwidth,groupwidth);
+ element->minheight += groupheight;
+
+ // now go and try to calculate necessary space for the pads
+ element->sinkwidth = 10.0;element->sinkheight = 0.0;element->sinks = 0;
+ pads = element->sinkpads;
+ while (pads) {
+ editorpad = GST_EDITOR_PAD(pads->data);
+ element->sinkwidth = MAX(element->sinkwidth,editorpad->width);
+ element->sinkheight = MAX(element->sinkheight,editorpad->height);
+ element->sinks++;
+ pads = g_list_next(pads);
+ }
+ element->srcwidth = 10.0;element->srcheight = 0.0;element->srcs = 0;
+ pads = element->srcpads;
+ while (pads) {
+ editorpad = GST_EDITOR_PAD(pads->data);
+ element->srcwidth = MAX(element->srcwidth,editorpad->width);
+ element->srcheight = MAX(element->srcheight,editorpad->height);
+ element->srcs++;
+ pads = g_list_next(pads);
+ }
+ // add in the needed space
+ element->minheight += MAX((element->sinkheight*element->sinks),
+ (element->srcheight*element->srcs)) + 4.0;
+ element->minwidth = MAX(element->minwidth,
+ ((element->sinkwidth*element->sinks) +
+ (element->srcwidth*element->srcs) + 4.0));
+// g_print("have %d sinks (%.2fx%.2f) and %d srcs (%.2fx%.2f)\n",
+// element->sinks,element->sinkwidth,element->sinkheight,
+// element->srcs,element->srcwidth,element->srcheight);
+
+ // grow the element to hold all the stuff
+// g_print("minsize is %.2fx%.2f,
+//",element->minwidth,element->minheight);
+// g_print("size was %.2fx%.2f, ",element->width,element->height);
+ element->width = MAX(element->width,element->minwidth);
+ element->height = MAX(element->height,element->minheight);
+// g_print("is now %.2fx%.2f\n",element->width,element->height);
+}
+
+void gst_editor_element_repack(GstEditorElement *element) {
+ GList *pads;
+ GstPad *pad;
+ GstEditorPad *editorpad;
+ gdouble sinkwidth,sinkheight;
+ gint sinks;
+ gdouble srcwidth,srcheight;
+ gint srcs;
+ gdouble x1,y1,x2,y2;
+ gint i;
+
+ if (!element->realized) return;
+
+ gst_editor_element_resize(element);
+
+ // still use x1,y1,x2,y2 so we can change around later
+ x1 = 0.0;y1 = 0.0;
+ x2 = element->width;y2 = element->height;
+
+// g_print("repacking element at %.2fx%.2f + %.2fx%.2f\n",
+// element->x,element->y,x2,y2);
+
+ // move the element group to match
+ gnome_canvas_item_set(GNOME_CANVAS_ITEM(element->group),
+ "x",element->x,"y",element->y,NULL);
+
+ // start by resizing the bordering box
+ g_return_if_fail(element->border != NULL);
+ gtk_object_set(GTK_OBJECT(element->border),
+ "x1",x1,"y1",y1,"x2",x2,"y2",y2,NULL);
+
+ // then move the text to the new top left
+ g_return_if_fail(element->title != NULL);
+ gtk_object_set(GTK_OBJECT(element->title),
+ "x",x1+1.0,"y",y1+1.0,
+ "anchor",GTK_ANCHOR_NORTH_WEST,
+ NULL);
+
+ // and move the resize box
+ g_return_if_fail(element->resizebox != NULL);
+ gtk_object_set(GTK_OBJECT(element->resizebox),
+ "x1",x2-5.0,"y1",y2-5.0,"x2",x2,"y2",y2,NULL);
+
+ // now place the state boxes
+ for (i=0;i<4;i++) {
+ g_return_if_fail(element->statebox[i] != NULL);
+ gtk_object_set(GTK_OBJECT(element->statebox[i]),
+ "x1",x1+(element->statewidth*i),
+ "y1",y2-element->stateheight,
+ "x2",x1+(element->statewidth*(i+1)),"y2",y2,NULL);
+ g_return_if_fail(element->statetext[i] != NULL);
+ gtk_object_set(GTK_OBJECT(element->statetext[i]),
+ "x",x1+(element->statewidth*i)+2.0,
+ "y",y2-element->stateheight+1.0,
+ "anchor",GTK_ANCHOR_NORTH_WEST,NULL);
+ }
+ // and the playstate box
+ g_return_if_fail(element->playbox != NULL);
+ gtk_object_set(GTK_OBJECT(element->playbox),
+ "x1",x1+(element->statewidth*4),
+ "y1",y2-element->stateheight,
+ "x2",x1+(element->statewidth*5),"y2",y2,NULL);
+ g_return_if_fail(element->playtext != NULL);
+ gtk_object_set(GTK_OBJECT(element->playtext),
+ "x",x1+(element->statewidth*4)+2.0,
+ "y",y2-element->stateheight+1.0,
+ "anchor",GTK_ANCHOR_NORTH_WEST,NULL);
+
+ // now we try to place all the pads
+ sinks = element->sinks;
+ pads = element->sinkpads;
+ while (pads) {
+ editorpad = GST_EDITOR_PAD(pads->data);
+ gtk_object_set(GTK_OBJECT(editorpad),
+ "x",x1,
+ "y",y2 - 2.0 - element->stateheight -
+ (element->sinkheight * sinks),
+ NULL);
+ gst_editor_pad_repack(editorpad);
+ sinks--;
+ pads = g_list_next(pads);
+ }
+
+ srcs = element->srcs;
+ pads = element->srcpads;
+ while (pads) {
+ editorpad = GST_EDITOR_PAD(pads->data);
+ gtk_object_set(GTK_OBJECT(editorpad),
+ "x",x2 - element->srcwidth,
+ "y",y2 - 2.0 - element->stateheight -
+ (element->srcheight * srcs),
+ NULL);
+ gst_editor_pad_repack(editorpad);
+ srcs--;
+ pads = g_list_next(pads);
+ }
+
+// g_print("done resizing element\n");
+}
+
+
+GstEditorPad *gst_editor_element_add_pad(GstEditorElement *element,
+ GstPad *pad) {
+ GstEditorPad *editorpad;
+
+ editorpad = gst_editor_pad_new(element,pad,NULL);
+ if (pad->direction == GST_PAD_SINK) {
+ element->sinkpads = g_list_prepend(element->sinkpads,editorpad);
+ element->sinks++;
+// g_print("added 'new' pad to sink list\n");
+ } else if (pad->direction == GST_PAD_SRC) {
+ element->srcpads = g_list_prepend(element->srcpads,editorpad);
+ element->srcs++;
+// g_print("added 'new' pad to src list\n");
+ } else
+ g_print("HUH?!? Don't know which direction this pad is...\n");
+
+ element->padlistchange = TRUE;
+ gst_editor_element_repack(element);
+ return editorpad;
+}
+
+
+static gint gst_editor_element_group_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ GstEditorElement *element) {
+// g_print("in group_event, type %d\n",event->type);
+ if (GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass)->event)
+ return (GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass)->event)(
+ item,event,element);
+ return FALSE;
+}
+
+
+static gint gst_editor_element_event(GnomeCanvasItem *item,GdkEvent *event,
+ GstEditorElement *element) {
+ gdouble item_x,item_y,dx,dy;
+ GdkCursor *fleur;
+
+// g_print("element in event, type %d\n",event->type);
+
+ switch(event->type) {
+ case GDK_ENTER_NOTIFY:
+ break;
+ case GDK_LEAVE_NOTIFY:
+ break;
+ case GDK_BUTTON_PRESS:
+ // dragxy coords are world coords of button press
+ element->dragx = event->button.x;
+ element->dragy = event->button.y;
+ // set some flags
+ element->dragging = TRUE;
+ element->moved = FALSE;
+ fleur = gdk_cursor_new(GDK_FLEUR);
+ gnome_canvas_item_grab(item,
+ GDK_POINTER_MOTION_MASK |
+// GDK_ENTER_NOTIFY_MASK |
+// GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_RELEASE_MASK,
+ fleur,event->button.time);
+ return TRUE;
+ break;
+ case GDK_MOTION_NOTIFY:
+ if (element->dragging) {
+ dx = event->button.x - element->dragx;
+ dy = event->button.y - element->dragy;
+ gst_editor_element_move(element,dx,dy);
+ element->dragx = event->button.x;
+ element->dragy = event->button.y;
+ element->moved = TRUE;
+ }
+ return TRUE;
+ break;
+ case GDK_BUTTON_RELEASE:
+ if (element->dragging) {
+ element->dragging = FALSE;
+ gnome_canvas_item_ungrab(item,event->button.time);
+ }
+ if (!element->moved) {
+ GstEditorElementClass *elementclass;
+ elementclass = GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
+ if (elementclass->button_event)
+ (elementclass->button_event)(item,event,element);
+ }
+//g_print("in element group_event, setting inchild");
+ element->canvas->inchild = TRUE;
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+static gint gst_editor_element_resizebox_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ GstEditorElement *element) {
+ GdkCursor *bottomright;
+ gdouble item_x,item_y;
+
+// g_print("in resizebox_event...\n");
+
+ // calculate coords relative to the group, not the box
+ item_x = event->button.x;
+ item_y = event->button.y;
+ gnome_canvas_item_w2i(item->parent,&item_x,&item_y);
+
+ switch(event->type) {
+ case GDK_ENTER_NOTIFY:
+ break;
+ case GDK_LEAVE_NOTIFY:
+ element->hesitating = FALSE;
+ break;
+ case GDK_BUTTON_PRESS:
+ element->dragx = event->button.x;
+ element->dragy = event->button.y;
+ element->resizing = TRUE;
+ element->hesitating = TRUE;
+ bottomright = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
+ gnome_canvas_item_grab(item,
+ GDK_POINTER_MOTION_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_RELEASE_MASK,
+ bottomright,event->button.time);
+ return TRUE;
+ break;
+ case GDK_MOTION_NOTIFY:
+ if (element->resizing) {
+ // doing a set because the code is in the arg set code
+// g_print("resizing to x2,y2 of %.2f,%.2f\n",item_x,item_y);
+ gtk_object_set(GTK_OBJECT(element),"x2",item_x,"y2",item_y,NULL);
+ element->resize = TRUE;
+ gst_editor_element_repack(element);
+ return TRUE;
+ }
+ break;
+ case GDK_BUTTON_RELEASE:
+ if (element->resizing) {
+ element->resizing = FALSE;
+ gnome_canvas_item_ungrab(item,event->button.time);
+//g_print("in element resizebox_event, setting inchild");
+ element->canvas->inchild = TRUE;
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+static gint gst_editor_element_state_event(GnomeCanvasItem *item,
+ GdkEvent *event,
+ gpointer data) {
+ GstEditorElement *element;
+ gint id = GPOINTER_TO_INT(data);
+ GdkCursor *uparrow;
+
+ element = GST_EDTIOR_GET_OBJECT(item);
+
+ switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ uparrow = gdk_cursor_new(GDK_SB_UP_ARROW);
+ gnome_canvas_item_grab(item,
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_LEAVE_NOTIFY_MASK,
+ uparrow,event->button.time);
+ /* NOTE: when grabbing canvas item, always get pointer_motion,
+ this will allow you to actually get all the other synth events */
+ break;
+ case GDK_LEAVE_NOTIFY:
+ gnome_canvas_item_ungrab(item,event->button.time);
+ break;
+ case GDK_BUTTON_PRESS:
+ return TRUE;
+ break;
+ case GDK_BUTTON_RELEASE:
+ if (id < 5) {
+ element->states[id] = !element->states[id];
+ gst_editor_element_set_state(element,id,TRUE);
+ } else
+ g_warning("Uh, shouldn't have gotten here, unknown state\n");
+//g_print("in element statebox_event, setting inchild");
+ element->canvas->inchild = TRUE;
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+static void gst_editor_element_set_state(GstEditorElement *element,
+ gint id,gboolean set) {
+ gboolean stateset = TRUE; /* if we have no element, set anyway */
+ if (element->states[id]) {
+ /* set the object state */
+ if (set && element->element)
+ stateset = gst_element_set_state(element->element,(1 << id));
+ /* change the display */
+ if (stateset) {
+ if (id < 4) {
+ gtk_object_set(GTK_OBJECT(element->statebox[id]),
+ "fill_color","black",NULL);
+ gtk_object_set(GTK_OBJECT(element->statetext[id]),
+ "fill_color","white",NULL);
+ } else if (id == 4) {
+ gtk_object_set(GTK_OBJECT(element->playbox),
+ "fill_color","black",NULL);
+ gtk_object_set(GTK_OBJECT(element->playtext),
+ "fill_color","white",NULL);
+ }
+ } else {
+ g_print("error setting state %d\n",id);
+ element->states[id] = !element->states[id];
+ }
+ } else {
+ if (set && element->element)
+ stateset = gst_element_set_state(element->element,~(1 << id));
+ if (stateset) {
+ if (id < 4) {
+ gtk_object_set(GTK_OBJECT(element->statebox[id]),
+ "fill_color","white",NULL);
+ gtk_object_set(GTK_OBJECT(element->statetext[id]),
+ "fill_color","black",NULL);
+ } else if (id == 4) {
+ gtk_object_set(GTK_OBJECT(element->playbox),
+ "fill_color","white",NULL);
+ gtk_object_set(GTK_OBJECT(element->playtext),
+ "fill_color","black",NULL);
+ }
+ } else {
+ g_print("error unsetting state %d\n",id);
+ element->states[id] = !element->states[id];
+ }
+ }
+}
+
+
+static void gst_editor_element_state_change(GstElement *element,
+ gint state,
+ GstEditorElement *editorelement) {
+ gint id;
+
+ g_return_if_fail(editorelement != NULL);
+
+// g_print("gst_editor_element_state_change got state 0x%08x\n",state);
+ // if it's an unset
+ if (state & GST_STATE_MAX) {
+ state = ~state;
+ for (id=0;id<(sizeof(state)*8)-1;id++) {
+ if (state & 1) {
+ editorelement->states[id] = FALSE;
+ break;
+ }
+ state /= 2;
+ }
+ } else {
+ for (id=0;id<(sizeof(state)*8)-1;id++) {
+ if (state & 1) {
+ editorelement->states[id] = TRUE;
+ break;
+ }
+ state /= 2;
+ }
+ }
+ gst_editor_element_set_state(editorelement,id,FALSE);
+}
+
+static void gst_editor_element_sync_state(GstEditorElement *element) {
+ gint id;
+
+// g_print("syncronizing state\n");
+ for (id=0;id<5;id++) {
+ element->states[id] = GST_FLAG_IS_SET(element->element,1<<id);
+ gst_editor_element_set_state(element,id,FALSE);
+ }
+}
+
+static void gst_editor_element_move(GstEditorElement *element,
+ gdouble dx,gdouble dy) {
+ GList *pads;
+ GstEditorPad *pad;
+
+ // this is a 'little' trick to keep from repacking the whole thing...
+ element->x += dx;element->y += dy;
+ gnome_canvas_item_move(GNOME_CANVAS_ITEM(element->group),dx,dy);
+
+ pads = element->srcpads;
+ while (pads) {
+ pad = GST_EDITOR_PAD(pads->data);
+ if (pad->connection) {
+// g_print("updating pad's connection\n");
+ pad->connection->resize = TRUE;
+ gst_editor_connection_resize(pad->connection);
+ }
+ pads = g_list_next(pads);
+ }
+ pads = element->sinkpads;
+ while (pads) {
+ pad = GST_EDITOR_PAD(pads->data);
+ if (pad->connection) {
+// g_print("updating pad's connection\n");
+ pad->connection->resize = TRUE;
+ gst_editor_connection_resize(pad->connection);
+ }
+ pads = g_list_next(pads);
+ }
+}