/* * Copyright (C) 2003, 2004 Laurent Sansonetti * 2004 Erwan Loisant * * This file is part of Ruby/GStreamer. * * Ruby/GStreamer is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Ruby/GStreamer 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with Ruby/GStreamer; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "rbgst.h" #include "rbgst-private.h" #define SELF(self) RVAL2GST_BIN(self) /* Class: Gst::Bin * Base container element. */ /* * Class method: new(name=nil) * name: a name for the bin. * * Constructs a new Gst::Bin object. * * If element name is ommited (or nil), then the bin will receive a guaranteed * unique name, consisting of the "bin" string and a number. * If name is given, it will be given the name supplied. * * Returns: a newly allocated Gst::Bin object. */ static VALUE rb_gst_bin_initialize(int argc, VALUE *argv, VALUE self) { GstElement *bin; VALUE name; rb_scan_args(argc, argv, "01", &name); bin = gst_bin_new(RVAL2CSTR_ACCEPT_NIL(name)); if (bin) RBGST_INITIALIZE(self, bin); return Qnil; } /* * Method: size * * Returns: the number of elements in the container. */ static VALUE rb_gst_bin_size(VALUE self) { return INT2NUM(GST_BIN_NUMCHILDREN(SELF(self))); } /* * Method: children(interface=nil) * interface: an interface (Ruby class). * * Returns: If interface is nil, an array of all * Gst::Element objects in the container. Otherwise, an * array of Gst::Element objects in the container that * implements the interface. */ static VALUE rb_gst_bin_get_children(int argc, VALUE *argv, VALUE self) { VALUE children, iface; rb_scan_args(argc, argv, "01", &iface); if (NIL_P(iface)) { const GList *node; children = rb_ary_new(); for (node = GST_BIN_CHILDREN(SELF(self)); node; node = g_list_next(node)) { rb_ary_push(children, GST_ELEMENT2RVAL(node->data)); } } else { GstIterator *iter; iter = gst_bin_iterate_all_by_interface(SELF(self), CLASS2GTYPE(iface)); children = _rbgst_collect_elements(iter); } return children; } /* * Method: children_recurse() * * Returns: an array of all Gst::Element objects in the container and child * bins. */ static VALUE rb_gst_bin_get_children_recurse(VALUE self) { GstIterator *iter; VALUE children; iter = gst_bin_iterate_recurse(SELF(self)); children = _rbgst_collect_elements(iter); return children; } static VALUE rb_gst_bin_get_children_cookie(VALUE self) { return UINT2NUM(GST_BIN_CHILDREN_COOKIE(SELF(self))); } static VALUE rb_gst_bin_get_child_bus(VALUE self) { return GST_BUS2RVAL(SELF(self)->child_bus); } static VALUE rb_gst_bin_get_messages(VALUE self) { GList *node; VALUE messages; messages = rb_ary_new(); for (node = SELF(self)->messages; node; node = g_list_next(node)) { rb_ary_push(messages, GST_MSG2RVAL(node->data)); } return messages; } static VALUE rb_gst_bin_polling_p(VALUE self) { return CBOOL2RVAL(SELF(self)->polling); } static VALUE rb_gst_bin_clock_dirty_p(VALUE self) { return CBOOL2RVAL(SELF(self)->clock_dirty); } /* * Method: provided_clock * * Gets the current clock of the (scheduler of the) bin, * as a Gst::Clock object. * * Returns: a Gst::Clock object, or nil. */ static VALUE rb_gst_bin_get_provided_clock(VALUE self) { return GST_CLOCK2RVAL(SELF(self)->provided_clock); } /* * Method: provided_clock=(clock) * clock: a Gst::Clock. * * Forces the bin to use the given clock. Use nil to force it * to use no clock at all. * * Returns: self. */ static VALUE rb_gst_bin_set_provided_clock(VALUE self, VALUE clock) { GstBin *bin; bin = SELF(self); if (bin->provided_clock) g_object_unref(bin->provided_clock); bin->provided_clock = RVAL2GST_CLOCK(clock); if (bin->provided_clock) g_object_ref(bin->provided_clock); return self; } static VALUE rb_gst_bin_get_clock_provider(VALUE self) { return GST_ELEMENT2RVAL(SELF(self)->clock_provider); } /* * Method: <<(element) * element: a Gst::Element object. * * Adds a Gst::Element object to the bin. * * Returns: self. */ static VALUE rb_gst_bin_add(VALUE self, VALUE element) { VALUE klass = GTYPE2CLASS(GST_TYPE_ELEMENT); if (!RVAL2CBOOL(rb_obj_is_kind_of(element, klass))) { rb_raise(rb_eTypeError, "Gst::Element expected"); } gst_bin_add(SELF(self), RVAL2GST_ELEMENT(element)); G_CHILD_ADD(self, element); return self; } /* * Method: add(*elements) * elements: a list of Gst::Element objects. * * Adds one or more Gst::Element objects to the bin. * * Returns: nil. */ static VALUE rb_gst_bin_add_multi(int argc, VALUE *argv, VALUE self) { int i; for (i = 0; i < argc; i++) { rb_gst_bin_add(self, argv[i]); } return Qnil; } /* * Method: remove(*elements) * elements: a list of Gst::Element objects. * * Removes one or more Gst::Element objects from the bin, unparenting * as well. * * Returns: nil. */ static VALUE rb_gst_bin_remove(int argc, VALUE *argv, VALUE self) { int i; GstBin *bin; bin = SELF(self); for (i = 0; i < argc; i++) { G_CHILD_REMOVE(self, argv[i]); gst_bin_remove(bin, RVAL2GST_ELEMENT(argv[i])); } return Qnil; } /* * Method: clear * * Removes all Gst::Element objects in the bin. * * Returns: nil. */ static VALUE rb_gst_bin_clear(VALUE self) { GstBin *bin; GList *node, *children; bin = SELF(self); children = g_list_copy(GST_BIN_CHILDREN(bin)); for (node = children; node; node = g_list_next(node)) { gst_bin_remove(bin, node->data); } g_list_free(children); return Qnil; } /* * Method: each(interface=nil) {|element| ...} * * Calls the block for each element in the bin, passing a reference to * the Gst::Element as parameter. If the interface isn't nil, * iterated elements should implement the interface. * * Returns: always nil. */ static VALUE rb_gst_bin_each_element(int argc, VALUE *argv, VALUE self) { return rb_ary_yield(rb_gst_bin_get_children(argc, argv, self)); } /* * Method: each_recurse() {|element| ...} * * Calls the block for each element in the bin and its child bins, passing a * reference to the Gst::Element as parameter. * * Returns: always nil. */ static VALUE rb_gst_bin_each_recurse_element(VALUE self) { return rb_ary_yield(rb_gst_bin_get_children_recurse(self)); } /* * Method: get_child(index) * Method: get_child(name, recurse=false) * Method: get_child(interface) * index: an index. * name: a name. * recurse: search recursively. * interface: an interface (Ruby class). * * 1st: Gets the index-th element. * * 2nd: Gets the element with the given name from the * bin, as a reference to a Gst::Element object. If the * element is not found and recurse is true, a recursion is * performed on the parent bin. * * 3nd: Looks for the first element inside the bin that implements the * given interface. If such an element is found, it returns the element. * If you want all elements that implement the interface, use * Gst::Bin#get_all_by_interface. The method recurses bins inside bins. * * Returns: a Gst::Element reference, or nil if the bin does not contain * an element with the given name nor implementing the interface. */ static VALUE rb_gst_bin_get(int argc, VALUE *argv, VALUE self) { VALUE index_or_name_or_interface, recurse; GstElement *element = NULL; rb_scan_args(argc, argv, "11", &index_or_name_or_interface, &recurse); if (RVAL2CBOOL(rb_obj_is_kind_of(index_or_name_or_interface, rb_cInteger))) { int index; GList *node; index = NUM2INT(index_or_name_or_interface); node = g_list_nth(GST_BIN_CHILDREN(SELF(self)), index); if (node) element = node->data; } else if (RVAL2CBOOL(rb_obj_is_kind_of(index_or_name_or_interface, rb_cString))) { char *name; name = RVAL2CSTR(index_or_name_or_interface); if (RVAL2CBOOL(recurse)) { element = gst_bin_get_by_name_recurse_up(SELF(self), name); } else { element = gst_bin_get_by_name(SELF(self), name); } } else { GType iface; iface = CLASS2GTYPE(index_or_name_or_interface); element = gst_bin_get_by_interface(SELF(self), iface); } return GST_ELEMENT2RVAL(element); } static VALUE rb_gst_bin_get_sinks(VALUE self) { return _rbgst_collect_elements(gst_bin_iterate_sinks(SELF(self))); } static VALUE rb_gst_bin_get_sources(VALUE self) { return _rbgst_collect_elements(gst_bin_iterate_sources(SELF(self))); } #ifdef GST_DEBUG_BIN_TO_DOT_FILE static VALUE rb_gst_bin_to_dot_file(VALUE self, VALUE details, VALUE filename) { GST_DEBUG_BIN_TO_DOT_FILE(SELF(self), NUM2INT(details), RVAL2CSTR(filename)); return Qnil; } static VALUE rb_gst_bin_to_dot_file_with_ts(VALUE self, VALUE details, VALUE filename) { GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(SELF(self), NUM2INT(details), RVAL2CSTR(filename)); return Qnil; } #endif void Init_gst_bin (void) { VALUE rb_cGstBin; rb_cGstBin = G_DEF_CLASS(GST_TYPE_BIN, "Bin", mGst); rb_include_module(rb_cGstBin, rb_mEnumerable); rb_define_method(rb_cGstBin, "initialize", rb_gst_bin_initialize, -1); rb_define_method(rb_cGstBin, "size", rb_gst_bin_size, 0); rb_define_alias(rb_cGstBin, "length", "size"); rb_define_method(rb_cGstBin, "children", rb_gst_bin_get_children, -1); rb_define_method(rb_cGstBin, "each", rb_gst_bin_each_element, -1); rb_define_method(rb_cGstBin, "children_recurse", rb_gst_bin_get_children_recurse, 0); rb_define_method(rb_cGstBin, "each_recurse", rb_gst_bin_each_recurse_element, 0); rb_define_method(rb_cGstBin, "children_cookie", rb_gst_bin_get_children_cookie, 0); rb_define_method(rb_cGstBin, "child_bus", rb_gst_bin_get_child_bus, 0); rb_define_method(rb_cGstBin, "messages", rb_gst_bin_get_messages, 0); rb_define_method(rb_cGstBin, "polling?", rb_gst_bin_polling_p, 0); rb_define_method(rb_cGstBin, "clock_dirty?", rb_gst_bin_clock_dirty_p, 0); rb_define_method(rb_cGstBin, "provided_clock", rb_gst_bin_get_provided_clock, 0); rb_define_method(rb_cGstBin, "set_provided_clock", rb_gst_bin_set_provided_clock, 1); rb_define_method(rb_cGstBin, "clock_provider", rb_gst_bin_get_clock_provider, 0); rb_define_method(rb_cGstBin, "<<", rb_gst_bin_add, 1); rb_define_method(rb_cGstBin, "add", rb_gst_bin_add_multi, -1); rb_define_method(rb_cGstBin, "remove", rb_gst_bin_remove, -1); rb_define_method(rb_cGstBin, "clear", rb_gst_bin_clear, 0); rb_define_method(rb_cGstBin, "get_child", rb_gst_bin_get, -1); rb_define_method(rb_cGstBin, "sinks", rb_gst_bin_get_sinks, 0); rb_define_method(rb_cGstBin, "sources", rb_gst_bin_get_sources, 0); #ifdef GST_DEBUG_BIN_TO_DOT_FILE rb_define_method(rb_cGstBin, "to_dot_file", rb_gst_bin_to_dot_file, 2); rb_define_method(rb_cGstBin, "to_dot_file_with_ts", rb_gst_bin_to_dot_file_with_ts, 2); #endif G_DEF_SETTERS(rb_cGstBin); G_DEF_CLASS(GST_TYPE_BIN_FLAGS, "Flags", rb_cGstBin); G_DEF_CONSTANTS(rb_cGstBin, GST_TYPE_BIN_FLAGS, "GST_BIN_"); #ifdef GST_DEBUG_BIN_TO_DOT_FILE G_DEF_CONSTANTS(rb_cGstBin, GST_TYPE_DEBUG_GRAPH_DETAILS, "GST_DEBUG_GRAPH_"); #endif }