]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blob - editor/gsteditorelement.c
initial checkin
[glsdk/gstreamer0-10.git] / editor / gsteditorelement.c
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 <gnome.h>
23 #include <gst/gst.h>
24 #include <gst/gstutils.h>
26 #include "gsteditor.h"
28 /* class functions */
29 static void gst_editor_element_class_init(GstEditorElementClass *klass);
30 static void gst_editor_element_init(GstEditorElement *element);
31 static void gst_editor_element_set_arg(GtkObject *object,GtkArg *arg,guint id);
32 static void gst_editor_element_get_arg(GtkObject *object,GtkArg *arg,guint id);
33 static void gst_editor_element_realize(GstEditorElement *element);
34 static gint gst_editor_element_event(GnomeCanvasItem *item,
35                                      GdkEvent *event,
36                                      GstEditorElement *element);
38 /* events fired by items within self */
39 static gint gst_editor_element_resizebox_event(GnomeCanvasItem *item,
40                                                GdkEvent *event,
41                                                GstEditorElement *element);
42 static gint gst_editor_element_group_event(GnomeCanvasItem *item,
43                                            GdkEvent *event,
44                                            GstEditorElement *element);
45 static gint gst_editor_element_state_event(GnomeCanvasItem *item,
46                                            GdkEvent *event,
47                                            gpointer data);
49 /* external events (from GstElement) */
50 static void gst_editor_element_state_change(GstElement *element,
51                                             gint state,
52                                             GstEditorElement *editorelement);
54 /* utility functions */
55 static void gst_editor_element_resize(GstEditorElement *element);
56 static void gst_editor_element_set_state(GstEditorElement *element,
57                                          gint id,gboolean set);
58 static void gst_editor_element_sync_state(GstEditorElement *element);
59 static void gst_editor_element_move(GstEditorElement *element,
60                                     gdouble dx,gdouble dy);
63 static gchar *_gst_editor_element_states[] = { "C","R","D","P" };
66 enum {
67   ARG_0,
68   ARG_X,
69   ARG_Y,
70   ARG_WIDTH,  
71   ARG_HEIGHT,
72   ARG_X1,
73   ARG_Y1,
74   ARG_X2,
75   ARG_Y2,
76   ARG_ELEMENT,
77 };
79 enum {
80   LAST_SIGNAL
81 };
83 static GtkObjectClass *parent_class;
84 static guint gst_editor_element_signals[LAST_SIGNAL] = { 0 };
86 GtkType gst_editor_element_get_type() {
87   static GtkType element_type = 0;
89   if (!element_type) {
90     static const GtkTypeInfo element_info = {
91       "GstEditorElement",
92       sizeof(GstEditorElement),
93       sizeof(GstEditorElementClass),
94       (GtkClassInitFunc)gst_editor_element_class_init,
95       (GtkObjectInitFunc)gst_editor_element_init,
96       NULL,
97       NULL,
98       (GtkClassInitFunc)NULL,
99     };
100     element_type = gtk_type_unique(gtk_object_get_type(),&element_info);
101   }
102   return element_type;
105 static void gst_editor_element_class_init(GstEditorElementClass *klass) {
106   GtkObjectClass *object_class;
108   object_class = (GtkObjectClass*)klass;
110   parent_class = gtk_type_class(gtk_object_get_type());
112   gtk_object_add_arg_type("GstEditorElement::x",GTK_TYPE_DOUBLE,
113                           GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
114                           ARG_X);
115   gtk_object_add_arg_type("GstEditorElement::y",GTK_TYPE_DOUBLE,
116                           GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
117                           ARG_Y);
118   gtk_object_add_arg_type("GstEditorElement::width",GTK_TYPE_DOUBLE,
119                           GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
120                           ARG_WIDTH);
121   gtk_object_add_arg_type("GstEditorElement::height",GTK_TYPE_DOUBLE,
122                           GTK_ARG_READWRITE|GTK_ARG_CONSTRUCT_ONLY,
123                           ARG_HEIGHT);
124   gtk_object_add_arg_type("GstEditorElement::x1",GTK_TYPE_DOUBLE,
125                           GTK_ARG_READWRITE,ARG_X1);
126   gtk_object_add_arg_type("GstEditorElement::y1",GTK_TYPE_DOUBLE,
127                           GTK_ARG_READWRITE,ARG_Y1);
128   gtk_object_add_arg_type("GstEditorElement::x2",GTK_TYPE_DOUBLE,
129                           GTK_ARG_READWRITE,ARG_X2);
130   gtk_object_add_arg_type("GstEditorElement::y2",GTK_TYPE_DOUBLE,
131                           GTK_ARG_READWRITE,ARG_Y2);
132   gtk_object_add_arg_type("GstEditorElement::element",GTK_TYPE_POINTER,
133                           GTK_ARG_READABLE,ARG_ELEMENT);
135   klass->realize = gst_editor_element_realize;
136   klass->event = gst_editor_element_event;
138   object_class->set_arg = gst_editor_element_set_arg;
139   object_class->get_arg = gst_editor_element_get_arg;
142 static void gst_editor_element_init(GstEditorElement *element) {
145 GstEditorElement *gst_editor_element_new(GstEditorBin *parent,
146                                          GstElement *element,
147                                          const gchar *first_arg_name, ...) {
148   GstEditorElement *editorelement;
149   va_list args;
151   g_return_if_fail(parent != NULL);
152   g_return_if_fail(GST_IS_EDITOR_BIN(parent));
153   g_return_if_fail(element != NULL);
154   g_return_if_fail(GST_IS_ELEMENT(element));
156   editorelement = GST_EDITOR_ELEMENT(gtk_type_new(GST_TYPE_EDITOR_ELEMENT));
157   editorelement->element = element;
159   va_start(args,first_arg_name);
160   gst_editor_element_construct(editorelement,parent,first_arg_name,args);
161   va_end(args);
163   return editorelement;
166 void gst_editor_element_construct(GstEditorElement *element,
167                                   GstEditorBin *parent,
168                                   const gchar *first_arg_name,
169                                   va_list args) {
170   GtkObject *obj = GTK_OBJECT(element);
171   GSList *arg_list = NULL, *info_list = NULL;
172   gchar *error;
173   GstEditorElementClass *elementclass;
175 //  g_print("in gst_editor_element_construct()\n");
177   error = gtk_object_args_collect(GTK_OBJECT_TYPE(obj),&arg_list,
178                                   &info_list,first_arg_name,args);
179   if (error) {
180     g_warning("gst_editor_element_construct(): %s",error);
181     g_free(error);
182   } else {
183     GSList *arg,*info;
184 //    g_print("setting all the arguments on the element\n");
185     for (arg=arg_list,info=info_list;arg;arg=arg->next,info=info->next)
186       gtk_object_arg_set(obj,arg->data,info->data);
187     gtk_args_collect_cleanup(arg_list,info_list);
188   }
190   if (parent)
191     gst_editor_bin_add(parent,element);
192   else if (!GST_IS_EDITOR_BIN(element))
193     g_warning("floating element...\n");
195   elementclass = GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
196   if (elementclass->realize)
197     (elementclass->realize)(element);
200 static void gst_editor_element_set_arg(GtkObject *object,GtkArg *arg,guint id) {
201   GstEditorElement *element;
202   gdouble dx,dy,newwidth,newheight;
204   /* get the major types of this object */
205   element = GST_EDITOR_ELEMENT(object);
207   switch (id) {
208     case ARG_X:
209       element->x = GTK_VALUE_DOUBLE(*arg);
210       break;
211     case ARG_Y:
212       element->y = GTK_VALUE_DOUBLE(*arg);
213       break;
214     case ARG_WIDTH:
215       element->width = GTK_VALUE_DOUBLE(*arg);
216       element->resize = TRUE;
217       break;
218     case ARG_HEIGHT:
219       element->height = GTK_VALUE_DOUBLE(*arg);
220       element->resize = TRUE;
221       break;
222     case ARG_X1:
223       element->x = GTK_VALUE_DOUBLE(*arg);
224       element->resize = TRUE;
225       break;
226     case ARG_Y1:
227       element->y = GTK_VALUE_DOUBLE(*arg);
228       element->resize = TRUE;
229       break;
230     case ARG_X2:
231       // make sure it's big enough, grow if not
232       element->width = MAX(GTK_VALUE_DOUBLE(*arg),element->minwidth);
233       element->resize = TRUE;
234       break;
235     case ARG_Y2:
236       // make sure it's big enough, grow if not
237       element->height = MAX(GTK_VALUE_DOUBLE(*arg),element->minheight);
238       element->resize = TRUE;
239       break;
240     default:
241       g_warning("gsteditorelement: unknown arg!");
242       break;
243   }
246 static void gst_editor_element_get_arg(GtkObject *object,GtkArg *arg,guint id) {
247   GstEditorElement *element;
249   /* get the major types of this object */
250   element = GST_EDITOR_ELEMENT(object);
252   switch (id) {
253     case ARG_X:
254       GTK_VALUE_INT(*arg) = element->x + (element->width / 2.0);
255       break;
256     case ARG_Y:
257       GTK_VALUE_INT(*arg) = element->y + (element->height / 2.0);
258       break;
259     case ARG_WIDTH:
260       GTK_VALUE_INT(*arg) = element->width;
261       break;
262     case ARG_HEIGHT:
263       GTK_VALUE_INT(*arg) = element->height;
264       break;
265     case ARG_X1:
266       GTK_VALUE_INT(*arg) = element->x;
267       break;
268     case ARG_Y1:
269       GTK_VALUE_INT(*arg) = element->y;
270       break;
271     case ARG_X2:
272       GTK_VALUE_INT(*arg) = element->x + element->width;
273       break;
274     case ARG_Y2:
275       GTK_VALUE_INT(*arg) = element->y + element->height;
276       break;
277     case ARG_ELEMENT:
278       GTK_VALUE_POINTER(*arg) = element->element;
279       break;
280     default:
281       arg->type = GTK_TYPE_INVALID;
282       break;
283   }
286 static void gst_editor_element_realize(GstEditorElement *element) {
287   GnomeCanvasGroup *parentgroup;
288   gint i;
289   gdouble x1,y1,x2,y2;
290   GList *pads;
291   GstPad *pad;
293 //  g_print("realizing editor element %p\n",element);
295   /* we have to have a parent by this point */
296   g_return_if_fail(element->parent != NULL);
298   // set the state signal of the actual element
299   gtk_signal_connect(GTK_OBJECT(element->element),"state_change",
300                      GTK_SIGNAL_FUNC(gst_editor_element_state_change),
301                      element);
303   // create the bounds if we haven't had them set
304 //  g_print("centering element at %.2fx%.2f (%.2fx%.2f)\n",
305 //          element->x,element->y,element->width,element->height);
307   /* create the group holding all the stuff for this element */
308   parentgroup = GST_EDITOR_ELEMENT(element->parent)->group;
309   element->group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(parentgroup,
310     gnome_canvas_group_get_type(),
311     "x",element->x - (element->width / 2.0),
312     "y",element->y - (element->height / 2.0),NULL));
313 //  g_print("origin of group is %.2fx%.2f\n",
314 //          element->x - (element->width / 2.0),
315 //          element->y - (element->height / 2.0));
316   g_return_if_fail(element->group != NULL);
317   GST_EDITOR_SET_OBJECT(element->group,element);
318   gtk_signal_connect(GTK_OBJECT(element->group),"event",
319     GTK_SIGNAL_FUNC(gst_editor_element_group_event),element);
321   // calculate the inter-group coords (x1,y1,x2,y2 are convenience vars)
322   x1 = 0.0;y1 = 0.0;
323   x2 = element->width;y2 = element->height;
325   /* create bordering box */
326   element->border = gnome_canvas_item_new(element->group,
327     gnome_canvas_rect_get_type(),
328     "width_units",2.0,"fill_color","white","outline_color","black", 
329     "x1",x1,"y1",y1,"x2",x2,"y2",y2,NULL);
330   g_return_if_fail(element->border != NULL);
331   GST_EDITOR_SET_OBJECT(element->border,element);
333   /* create resizing box */
334   element->resizebox = gnome_canvas_item_new(element->group,
335     gnome_canvas_rect_get_type(),
336     "width_units",1.0,"fill_color","white","outline_color","black",
337     "x1",x2-4.0,"y1",y2-4.0,"x2",x2,"y2",y2,NULL);
338   g_return_if_fail(element->resizebox != NULL);
339   GST_EDITOR_SET_OBJECT(element->resizebox,element);
340   gtk_signal_connect(GTK_OBJECT(element->resizebox),"event",
341     GTK_SIGNAL_FUNC(gst_editor_element_resizebox_event),element);
343   /* create the title */
344   element->title = gnome_canvas_item_new(element->group,
345     gnome_canvas_text_get_type(),
346     "text",gst_element_get_name(GST_OBJECT(element->element)),
347     "x",x1+1.0,"y",y1+1.0,"anchor",GTK_ANCHOR_NORTH_WEST,
348     "font_gdk",gtk_widget_get_default_style()->font,
349     NULL);
350   g_return_if_fail(element->title != NULL);
351   GST_EDITOR_SET_OBJECT(element->title,element);
353   /* create the state boxen */
354   for (i=0;i<4;i++) {
355     element->statebox[i] = gnome_canvas_item_new(element->group,
356       gnome_canvas_rect_get_type(),
357       "width_units",1.0,"fill_color","white","outline_color","black",
358       "x1",0.0,"y1",0.0,"x2",0.0,"y2",0.0,
359       NULL);
360     g_return_if_fail(element->statebox[i] != NULL);
361     GST_EDITOR_SET_OBJECT(element->statebox[i],element);
362     gtk_signal_connect(GTK_OBJECT(element->statebox[i]),"event",
363                        GTK_SIGNAL_FUNC(gst_editor_element_state_event),
364                        GINT_TO_POINTER(i));
365     element->statetext[i] = gnome_canvas_item_new(element->group,
366       gnome_canvas_text_get_type(),
367       "text",_gst_editor_element_states[i],
368       "x",0.0,"y",0.0,"anchor",GTK_ANCHOR_NORTH_WEST,
369       "font","-*-*-*-*-*-*-6-*-*-*-*-*-*-*",
370       NULL);
371     g_return_if_fail(element->statetext[i] != NULL);
372     GST_EDITOR_SET_OBJECT(element->statetext[i],element);
373     gtk_signal_connect(GTK_OBJECT(element->statetext[i]),"event",
374                        GTK_SIGNAL_FUNC(gst_editor_element_state_event),
375                        GINT_TO_POINTER(i));
376   }
377   /* and the play box (FIXME: should be icons, not text */
378   element->playbox = gnome_canvas_item_new(element->group,
379     gnome_canvas_rect_get_type(),
380     "width_units",1.0,"fill_color","white","outline_color","black",
381     "x1",0.0,"y1",0.0,"x2",0.0,"y2",0.0,
382     NULL);
383   g_return_if_fail(element->playbox != NULL);
384   GST_EDITOR_SET_OBJECT(element->playbox,element);
385   gtk_signal_connect(GTK_OBJECT(element->playbox),"event",
386                      GTK_SIGNAL_FUNC(gst_editor_element_state_event),
387                      GINT_TO_POINTER(4));
388   element->playtext = gnome_canvas_item_new(element->group,
389     gnome_canvas_text_get_type(),
390     "text","P",
391     "x",0.0,"y",0.0,"anchor",GTK_ANCHOR_NORTH_WEST,
392     "font","-*-*-*-*-*-*-6-*-*-*-*-*-*-*",
393     NULL);
394   g_return_if_fail(element->playtext != NULL);
395   GST_EDITOR_SET_OBJECT(element->playtext,element);
396   gtk_signal_connect(GTK_OBJECT(element->playtext),"event",
397                      GTK_SIGNAL_FUNC(gst_editor_element_state_event),
398                      GINT_TO_POINTER(4));
400   // get all the pads
401   pads = gst_element_get_pad_list(element->element);
402   while (pads) {
403     pad = GST_PAD(pads->data);
404     gst_editor_element_add_pad(element,pad);
405     pads = g_list_next(pads);
406   }
408   element->realized = TRUE;
410   // force a resize
411   element->resize = TRUE;
412   gst_editor_element_resize(element);
414   // recenter things on the supposed center
415 //  g_print("recentering element at %.2fx%.2f (%.2fx%.2f)\n",
416 //          element->x,element->y,element->width,element->height);
417   element->x -= (element->width / 2.0);
418   element->y -= (element->height / 2.0);
419   gnome_canvas_item_set(GNOME_CANVAS_ITEM(element->group),
420     "x",element->x,"y",element->y,NULL);
421 //  g_print("origin of group is %.2fx%.2f\n",element->x,element->y);
423   gst_editor_element_repack(element);
427 static void gst_editor_element_resize(GstEditorElement *element) {
428   gdouble itemwidth,itemheight;
429   gdouble groupwidth,groupheight;
430   GList *pads;
431   GstEditorPad *editorpad;
432   gint i;
434   if (element->resize != TRUE) return;
435   element->resize = FALSE;
437 //  g_print("resizing element\n");
439   element->minwidth = element->insidewidth;
440   element->minheight = element->insideheight;
442   // get the text size and add it into minsize
443   g_return_if_fail(element->title != NULL);
444   itemwidth = gst_util_get_double_arg(GTK_OBJECT(element->title),
445                                       "text_width") + 2.0;
446   itemheight = gst_util_get_double_arg(GTK_OBJECT(element->title),
447                                        "text_height") + 2.0;
448   element->titlewidth = itemwidth;
449   element->titleheight = itemheight;
450   element->minwidth = MAX(element->minwidth,itemwidth);
451   element->minheight += itemheight;
453   // now do the bottom bar
454   // find the biggest of the state chars
455   element->statewidth = 0.0;element->stateheight = 0.0;
456   for (i=0;i<4;i++) {
457     g_return_if_fail(element->statetext[i] != NULL);
458     itemwidth = gst_util_get_double_arg(GTK_OBJECT(element->statetext[i]),
459                                         "text_width") - 2.0;
460     itemwidth = gst_util_get_double_arg(GTK_OBJECT(element->statetext[i]),
461                                         "text_height");
462     element->statewidth = MAX(element->statewidth,itemwidth);
463     element->stateheight = MAX(element->stateheight,itemheight);
464   }
465   // calculate the size of the primary group
466   groupwidth = element->statewidth * 5; // 4 states plus playstate
467   groupheight = element->stateheight;
468   // add in the resize box
469   groupwidth += 7.0;            // 2.0 for buffer, 5.0 for actual size
470   groupheight = MAX(groupheight,5.0);
471   // update the minsize
472   element->minwidth = MAX(element->minwidth,groupwidth);
473   element->minheight += groupheight;
475   // now go and try to calculate necessary space for the pads
476   element->sinkwidth = 10.0;element->sinkheight = 0.0;element->sinks = 0;
477   pads = element->sinkpads;
478   while (pads) {
479     editorpad = GST_EDITOR_PAD(pads->data);
480     element->sinkwidth = MAX(element->sinkwidth,editorpad->width);
481     element->sinkheight = MAX(element->sinkheight,editorpad->height);
482     element->sinks++;
483     pads = g_list_next(pads);
484   }
485   element->srcwidth = 10.0;element->srcheight = 0.0;element->srcs = 0;
486   pads = element->srcpads;
487   while (pads) {
488     editorpad = GST_EDITOR_PAD(pads->data);
489     element->srcwidth = MAX(element->srcwidth,editorpad->width);
490     element->srcheight = MAX(element->srcheight,editorpad->height);
491     element->srcs++;
492     pads = g_list_next(pads);
493   }
494   // add in the needed space
495   element->minheight += MAX((element->sinkheight*element->sinks),
496                             (element->srcheight*element->srcs)) + 4.0;
497   element->minwidth = MAX(element->minwidth,
498                           ((element->sinkwidth*element->sinks) +
499                            (element->srcwidth*element->srcs) + 4.0));
500 //  g_print("have %d sinks (%.2fx%.2f) and %d srcs (%.2fx%.2f)\n",
501 //          element->sinks,element->sinkwidth,element->sinkheight,
502 //          element->srcs,element->srcwidth,element->srcheight);
504   // grow the element to hold all the stuff
505 //  g_print("minsize is %.2fx%.2f,
506 //",element->minwidth,element->minheight);
507 //  g_print("size was %.2fx%.2f, ",element->width,element->height);
508   element->width = MAX(element->width,element->minwidth);
509   element->height = MAX(element->height,element->minheight);
510 //  g_print("is now %.2fx%.2f\n",element->width,element->height);
513 void gst_editor_element_repack(GstEditorElement *element) {
514   GList *pads;
515   GstPad *pad;
516   GstEditorPad *editorpad;
517   gdouble sinkwidth,sinkheight;
518   gint sinks;
519   gdouble srcwidth,srcheight;
520   gint srcs;
521   gdouble x1,y1,x2,y2;
522   gint i;
524   if (!element->realized) return;
526   gst_editor_element_resize(element);
528   // still use x1,y1,x2,y2 so we can change around later
529   x1 = 0.0;y1 = 0.0;
530   x2 = element->width;y2 = element->height;
532 //  g_print("repacking element at %.2fx%.2f + %.2fx%.2f\n",
533 //          element->x,element->y,x2,y2);
535   // move the element group to match
536   gnome_canvas_item_set(GNOME_CANVAS_ITEM(element->group),
537                         "x",element->x,"y",element->y,NULL);
539   // start by resizing the bordering box
540   g_return_if_fail(element->border != NULL);
541   gtk_object_set(GTK_OBJECT(element->border),
542                  "x1",x1,"y1",y1,"x2",x2,"y2",y2,NULL);
544   // then move the text to the new top left
545   g_return_if_fail(element->title != NULL);
546   gtk_object_set(GTK_OBJECT(element->title),
547                  "x",x1+1.0,"y",y1+1.0,
548                  "anchor",GTK_ANCHOR_NORTH_WEST,
549                  NULL);
551   // and move the resize box
552   g_return_if_fail(element->resizebox != NULL);
553   gtk_object_set(GTK_OBJECT(element->resizebox),
554                  "x1",x2-5.0,"y1",y2-5.0,"x2",x2,"y2",y2,NULL);
556   // now place the state boxes
557   for (i=0;i<4;i++) {
558     g_return_if_fail(element->statebox[i] != NULL);
559     gtk_object_set(GTK_OBJECT(element->statebox[i]),
560                    "x1",x1+(element->statewidth*i),
561                    "y1",y2-element->stateheight,
562                    "x2",x1+(element->statewidth*(i+1)),"y2",y2,NULL);
563   g_return_if_fail(element->statetext[i] != NULL);
564     gtk_object_set(GTK_OBJECT(element->statetext[i]),
565                    "x",x1+(element->statewidth*i)+2.0,
566                    "y",y2-element->stateheight+1.0,
567                    "anchor",GTK_ANCHOR_NORTH_WEST,NULL);
568   }
569   // and the playstate box
570   g_return_if_fail(element->playbox != NULL);
571   gtk_object_set(GTK_OBJECT(element->playbox),
572                  "x1",x1+(element->statewidth*4),
573                  "y1",y2-element->stateheight,
574                  "x2",x1+(element->statewidth*5),"y2",y2,NULL);
575   g_return_if_fail(element->playtext != NULL);
576   gtk_object_set(GTK_OBJECT(element->playtext),
577                  "x",x1+(element->statewidth*4)+2.0,
578                  "y",y2-element->stateheight+1.0,
579                  "anchor",GTK_ANCHOR_NORTH_WEST,NULL);
581   // now we try to place all the pads
582   sinks = element->sinks;
583   pads = element->sinkpads;
584   while (pads) {
585     editorpad = GST_EDITOR_PAD(pads->data);
586     gtk_object_set(GTK_OBJECT(editorpad),
587                    "x",x1,
588                    "y",y2 - 2.0 - element->stateheight - 
589                        (element->sinkheight * sinks),
590                    NULL);
591     gst_editor_pad_repack(editorpad);
592     sinks--;
593     pads = g_list_next(pads);
594   }
596   srcs = element->srcs;
597   pads = element->srcpads;
598   while (pads) {
599     editorpad = GST_EDITOR_PAD(pads->data);
600     gtk_object_set(GTK_OBJECT(editorpad),
601                    "x",x2 - element->srcwidth,
602                    "y",y2 - 2.0 - element->stateheight -
603                        (element->srcheight * srcs),
604                    NULL);
605     gst_editor_pad_repack(editorpad);
606     srcs--;
607     pads = g_list_next(pads);
608   }
610 //  g_print("done resizing element\n");
614 GstEditorPad *gst_editor_element_add_pad(GstEditorElement *element,
615                                          GstPad *pad) {
616   GstEditorPad *editorpad;
618   editorpad = gst_editor_pad_new(element,pad,NULL);
619   if (pad->direction == GST_PAD_SINK) {
620     element->sinkpads = g_list_prepend(element->sinkpads,editorpad);
621     element->sinks++;
622 //    g_print("added 'new' pad to sink list\n");
623   } else if (pad->direction == GST_PAD_SRC) {
624     element->srcpads = g_list_prepend(element->srcpads,editorpad);
625     element->srcs++;
626 //    g_print("added 'new' pad to src list\n");
627   } else
628     g_print("HUH?!?  Don't know which direction this pad is...\n");
630   element->padlistchange = TRUE;
631   gst_editor_element_repack(element);
632   return editorpad;
636 static gint gst_editor_element_group_event(GnomeCanvasItem *item,
637                                            GdkEvent *event,
638                                            GstEditorElement *element) {
639 //  g_print("in group_event, type %d\n",event->type);
640   if (GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass)->event)
641     return (GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass)->event)(
642       item,event,element);
643   return FALSE;
647 static gint gst_editor_element_event(GnomeCanvasItem *item,GdkEvent *event,
648                                      GstEditorElement *element) {
649   gdouble item_x,item_y,dx,dy;
650   GdkCursor *fleur;
652 //  g_print("element in event, type %d\n",event->type);
654   switch(event->type) {
655     case GDK_ENTER_NOTIFY:
656       break;
657     case GDK_LEAVE_NOTIFY:
658       break;
659     case GDK_BUTTON_PRESS:
660       // dragxy coords are world coords of button press
661       element->dragx = event->button.x;
662       element->dragy = event->button.y;
663       // set some flags
664       element->dragging = TRUE;
665       element->moved = FALSE;
666       fleur = gdk_cursor_new(GDK_FLEUR);
667       gnome_canvas_item_grab(item,
668                              GDK_POINTER_MOTION_MASK |
669 //                             GDK_ENTER_NOTIFY_MASK |
670 //                             GDK_LEAVE_NOTIFY_MASK |
671                              GDK_BUTTON_RELEASE_MASK,
672                              fleur,event->button.time);
673       return TRUE;
674       break;
675     case GDK_MOTION_NOTIFY:
676       if (element->dragging) {
677         dx = event->button.x - element->dragx;
678         dy = event->button.y - element->dragy;
679         gst_editor_element_move(element,dx,dy);
680         element->dragx = event->button.x;
681         element->dragy = event->button.y;
682         element->moved = TRUE;
683       }
684       return TRUE;
685       break;
686     case GDK_BUTTON_RELEASE:
687       if (element->dragging) {
688         element->dragging = FALSE;
689         gnome_canvas_item_ungrab(item,event->button.time);
690       }
691       if (!element->moved) {
692         GstEditorElementClass *elementclass;
693         elementclass = GST_EDITOR_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
694         if (elementclass->button_event)
695           (elementclass->button_event)(item,event,element);
696       }
697 //g_print("in element group_event, setting inchild");
698       element->canvas->inchild = TRUE;
699       return TRUE;
700       break;
702     default:
703       break;
704   }
705   return FALSE;
709 static gint gst_editor_element_resizebox_event(GnomeCanvasItem *item,
710                                                GdkEvent *event,
711                                                GstEditorElement *element) {
712   GdkCursor *bottomright;
713   gdouble item_x,item_y;
715 //  g_print("in resizebox_event...\n");
717   // calculate coords relative to the group, not the box
718   item_x = event->button.x;
719   item_y = event->button.y;
720   gnome_canvas_item_w2i(item->parent,&item_x,&item_y);
722   switch(event->type) {
723     case GDK_ENTER_NOTIFY:
724       break;
725     case GDK_LEAVE_NOTIFY:
726       element->hesitating = FALSE;
727       break;
728     case GDK_BUTTON_PRESS:
729       element->dragx = event->button.x;
730       element->dragy = event->button.y;
731       element->resizing = TRUE;
732       element->hesitating = TRUE;
733       bottomright = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
734       gnome_canvas_item_grab(item,
735                              GDK_POINTER_MOTION_MASK |
736                              GDK_ENTER_NOTIFY_MASK |
737                              GDK_LEAVE_NOTIFY_MASK |
738                              GDK_BUTTON_RELEASE_MASK,
739                              bottomright,event->button.time);
740       return TRUE;
741       break;
742     case GDK_MOTION_NOTIFY:
743       if (element->resizing) {
744         // doing a set because the code is in the arg set code
745 //        g_print("resizing to x2,y2 of %.2f,%.2f\n",item_x,item_y);
746         gtk_object_set(GTK_OBJECT(element),"x2",item_x,"y2",item_y,NULL);
747         element->resize = TRUE;
748         gst_editor_element_repack(element);
749         return TRUE;
750       }
751       break;
752     case GDK_BUTTON_RELEASE:
753       if (element->resizing) {
754         element->resizing = FALSE;
755         gnome_canvas_item_ungrab(item,event->button.time);
756 //g_print("in element resizebox_event, setting inchild");
757         element->canvas->inchild = TRUE;
758         return TRUE;
759       }
760       break;
761     default:
762       break;
763   }
764   return FALSE;
768 static gint gst_editor_element_state_event(GnomeCanvasItem *item,
769                                            GdkEvent *event,
770                                            gpointer data) {
771   GstEditorElement *element;
772   gint id = GPOINTER_TO_INT(data);
773   GdkCursor *uparrow;
775   element = GST_EDTIOR_GET_OBJECT(item);
777   switch (event->type) {
778     case GDK_ENTER_NOTIFY:
779       uparrow = gdk_cursor_new(GDK_SB_UP_ARROW);
780       gnome_canvas_item_grab(item,
781                              GDK_POINTER_MOTION_MASK |
782                              GDK_BUTTON_RELEASE_MASK |
783                              GDK_LEAVE_NOTIFY_MASK,
784                              uparrow,event->button.time);
785       /* NOTE: when grabbing canvas item, always get pointer_motion,
786          this will allow you to actually get all the other synth events */
787       break;
788     case GDK_LEAVE_NOTIFY:
789       gnome_canvas_item_ungrab(item,event->button.time);
790       break;
791     case GDK_BUTTON_PRESS:
792       return TRUE;
793       break;
794     case GDK_BUTTON_RELEASE:
795       if (id < 5) {
796         element->states[id] = !element->states[id];
797         gst_editor_element_set_state(element,id,TRUE);
798       } else
799         g_warning("Uh, shouldn't have gotten here, unknown state\n");
800 //g_print("in element statebox_event, setting inchild");
801       element->canvas->inchild = TRUE;
802       return TRUE;
803       break;
804     default:
805       break;
806   }
807   return FALSE;
811 static void gst_editor_element_set_state(GstEditorElement *element,
812                                          gint id,gboolean set) {
813   gboolean stateset = TRUE;     /* if we have no element, set anyway */
814   if (element->states[id]) {
815     /* set the object state */
816     if (set && element->element)
817       stateset = gst_element_set_state(element->element,(1 << id));
818     /* change the display */
819     if (stateset) {
820       if (id < 4) {
821         gtk_object_set(GTK_OBJECT(element->statebox[id]),
822                        "fill_color","black",NULL);
823         gtk_object_set(GTK_OBJECT(element->statetext[id]),
824                        "fill_color","white",NULL);
825       } else if (id == 4) {
826         gtk_object_set(GTK_OBJECT(element->playbox),
827                        "fill_color","black",NULL);
828         gtk_object_set(GTK_OBJECT(element->playtext),
829                        "fill_color","white",NULL);
830       }
831     } else {
832       g_print("error setting state %d\n",id);
833       element->states[id] = !element->states[id];
834     }
835   } else {
836     if (set && element->element)
837       stateset = gst_element_set_state(element->element,~(1 << id));
838     if (stateset) {
839       if (id < 4) {
840         gtk_object_set(GTK_OBJECT(element->statebox[id]),
841                        "fill_color","white",NULL);
842         gtk_object_set(GTK_OBJECT(element->statetext[id]),
843                        "fill_color","black",NULL);
844       } else if (id == 4) {
845         gtk_object_set(GTK_OBJECT(element->playbox),
846                        "fill_color","white",NULL);
847         gtk_object_set(GTK_OBJECT(element->playtext),
848                        "fill_color","black",NULL);
849       }
850     } else {
851       g_print("error unsetting state %d\n",id);
852       element->states[id] = !element->states[id];
853     }
854   }
858 static void gst_editor_element_state_change(GstElement *element,
859                                             gint state,
860                                             GstEditorElement *editorelement) {
861   gint id;
863   g_return_if_fail(editorelement != NULL);
865 //  g_print("gst_editor_element_state_change got state 0x%08x\n",state);
866   // if it's an unset
867   if (state & GST_STATE_MAX) {
868     state = ~state;
869     for (id=0;id<(sizeof(state)*8)-1;id++) {
870       if (state & 1) {
871         editorelement->states[id] = FALSE;
872         break;
873       }
874       state /= 2;
875     }
876   } else {
877     for (id=0;id<(sizeof(state)*8)-1;id++) {
878       if (state & 1) {
879         editorelement->states[id] = TRUE;
880         break;
881       }
882       state /= 2;
883     }
884   }
885   gst_editor_element_set_state(editorelement,id,FALSE);
888 static void gst_editor_element_sync_state(GstEditorElement *element) {
889   gint id;
891 //  g_print("syncronizing state\n");
892   for (id=0;id<5;id++) {
893     element->states[id] = GST_FLAG_IS_SET(element->element,1<<id);
894     gst_editor_element_set_state(element,id,FALSE);
895   }
898 static void gst_editor_element_move(GstEditorElement *element,
899                                     gdouble dx,gdouble dy) {
900   GList *pads;
901   GstEditorPad *pad;
903   // this is a 'little' trick to keep from repacking the whole thing...
904   element->x += dx;element->y += dy;
905   gnome_canvas_item_move(GNOME_CANVAS_ITEM(element->group),dx,dy);
907   pads = element->srcpads;
908   while (pads) {
909     pad = GST_EDITOR_PAD(pads->data);
910     if (pad->connection) {
911 //      g_print("updating pad's connection\n");
912       pad->connection->resize = TRUE;
913       gst_editor_connection_resize(pad->connection);
914     }
915     pads = g_list_next(pads);
916   }
917   pads = element->sinkpads;
918   while (pads) {
919     pad = GST_EDITOR_PAD(pads->data);
920     if (pad->connection) {
921 //      g_print("updating pad's connection\n");
922       pad->connection->resize = TRUE;
923       gst_editor_connection_resize(pad->connection);
924     }
925     pads = g_list_next(pads);
926   }