| /* 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_ELEMENT(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 |
| #ifdef OLD |
| 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; |
| } |
| } |
| #endif |
| 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); |
| } |
| } |