/* Gnome-Streamer * Copyright (C) <1999> Erik Walthinsen * * 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 #include #include #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<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); } }