gstreamer 0.90.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. data/ChangeLog +1157 -0
  2. data/README +33 -0
  3. data/Rakefile +15 -0
  4. data/ext/gstreamer/Makefile +162 -0
  5. data/ext/gstreamer/depend +5 -0
  6. data/ext/gstreamer/extconf.rb +63 -0
  7. data/ext/gstreamer/gst.so +0 -0
  8. data/ext/gstreamer/misc.c +62 -0
  9. data/ext/gstreamer/misc.o +0 -0
  10. data/ext/gstreamer/rbgst-bin.c +466 -0
  11. data/ext/gstreamer/rbgst-bin.o +0 -0
  12. data/ext/gstreamer/rbgst-buffer.c +365 -0
  13. data/ext/gstreamer/rbgst-buffer.o +0 -0
  14. data/ext/gstreamer/rbgst-bus.c +92 -0
  15. data/ext/gstreamer/rbgst-bus.o +0 -0
  16. data/ext/gstreamer/rbgst-caps.c +441 -0
  17. data/ext/gstreamer/rbgst-caps.o +0 -0
  18. data/ext/gstreamer/rbgst-child-proxy.c +33 -0
  19. data/ext/gstreamer/rbgst-child-proxy.o +0 -0
  20. data/ext/gstreamer/rbgst-clock.c +108 -0
  21. data/ext/gstreamer/rbgst-clock.o +0 -0
  22. data/ext/gstreamer/rbgst-element-factory.c +255 -0
  23. data/ext/gstreamer/rbgst-element-factory.o +0 -0
  24. data/ext/gstreamer/rbgst-element.c +1053 -0
  25. data/ext/gstreamer/rbgst-element.o +0 -0
  26. data/ext/gstreamer/rbgst-event.c +351 -0
  27. data/ext/gstreamer/rbgst-event.o +0 -0
  28. data/ext/gstreamer/rbgst-ghost-pad.c +42 -0
  29. data/ext/gstreamer/rbgst-ghost-pad.o +0 -0
  30. data/ext/gstreamer/rbgst-index-factory.c +67 -0
  31. data/ext/gstreamer/rbgst-index-factory.o +0 -0
  32. data/ext/gstreamer/rbgst-message.c +784 -0
  33. data/ext/gstreamer/rbgst-message.o +0 -0
  34. data/ext/gstreamer/rbgst-mini-object.c +220 -0
  35. data/ext/gstreamer/rbgst-mini-object.o +0 -0
  36. data/ext/gstreamer/rbgst-object.c +81 -0
  37. data/ext/gstreamer/rbgst-object.o +0 -0
  38. data/ext/gstreamer/rbgst-pad-template.c +124 -0
  39. data/ext/gstreamer/rbgst-pad-template.o +0 -0
  40. data/ext/gstreamer/rbgst-pad.c +338 -0
  41. data/ext/gstreamer/rbgst-pad.o +0 -0
  42. data/ext/gstreamer/rbgst-pipeline.c +90 -0
  43. data/ext/gstreamer/rbgst-pipeline.o +0 -0
  44. data/ext/gstreamer/rbgst-plugin-feature.c +134 -0
  45. data/ext/gstreamer/rbgst-plugin-feature.o +0 -0
  46. data/ext/gstreamer/rbgst-plugin.c +164 -0
  47. data/ext/gstreamer/rbgst-plugin.o +0 -0
  48. data/ext/gstreamer/rbgst-private.c +89 -0
  49. data/ext/gstreamer/rbgst-private.h +37 -0
  50. data/ext/gstreamer/rbgst-private.o +0 -0
  51. data/ext/gstreamer/rbgst-query.c +289 -0
  52. data/ext/gstreamer/rbgst-query.o +0 -0
  53. data/ext/gstreamer/rbgst-seek.c +36 -0
  54. data/ext/gstreamer/rbgst-seek.o +0 -0
  55. data/ext/gstreamer/rbgst-static-caps.c +49 -0
  56. data/ext/gstreamer/rbgst-static-caps.o +0 -0
  57. data/ext/gstreamer/rbgst-static-pad-template.c +64 -0
  58. data/ext/gstreamer/rbgst-static-pad-template.o +0 -0
  59. data/ext/gstreamer/rbgst-structure.c +300 -0
  60. data/ext/gstreamer/rbgst-structure.o +0 -0
  61. data/ext/gstreamer/rbgst-system-clock.c +45 -0
  62. data/ext/gstreamer/rbgst-system-clock.o +0 -0
  63. data/ext/gstreamer/rbgst-type-find-factory.c +124 -0
  64. data/ext/gstreamer/rbgst-type-find-factory.o +0 -0
  65. data/ext/gstreamer/rbgst-value.c +517 -0
  66. data/ext/gstreamer/rbgst-value.o +0 -0
  67. data/ext/gstreamer/rbgst-x-overlay.c +132 -0
  68. data/ext/gstreamer/rbgst-x-overlay.o +0 -0
  69. data/ext/gstreamer/rbgst.c +279 -0
  70. data/ext/gstreamer/rbgst.h +197 -0
  71. data/ext/gstreamer/rbgst.o +0 -0
  72. data/ext/gstreamer/rbgstclockentry.c +268 -0
  73. data/ext/gstreamer/rbgstclockentry.o +0 -0
  74. data/ext/gstreamer/rbgstformat.c +159 -0
  75. data/ext/gstreamer/rbgstformat.o +0 -0
  76. data/ext/gstreamer/rbgstindex.c +314 -0
  77. data/ext/gstreamer/rbgstindex.o +0 -0
  78. data/ext/gstreamer/rbgstindexentry.c +96 -0
  79. data/ext/gstreamer/rbgstindexentry.o +0 -0
  80. data/ext/gstreamer/rbgstparse.c +66 -0
  81. data/ext/gstreamer/rbgstparse.o +0 -0
  82. data/ext/gstreamer/rbgstquerytype.c +159 -0
  83. data/ext/gstreamer/rbgstquerytype.o +0 -0
  84. data/ext/gstreamer/rbgstregistry.c +278 -0
  85. data/ext/gstreamer/rbgstregistry.o +0 -0
  86. data/ext/gstreamer/rbgsttag.c +111 -0
  87. data/ext/gstreamer/rbgsttag.o +0 -0
  88. data/ext/gstreamer/rbgsttagsetter.c +50 -0
  89. data/ext/gstreamer/rbgsttagsetter.o +0 -0
  90. data/ext/gstreamer/rbgstxml.c +189 -0
  91. data/ext/gstreamer/rbgstxml.o +0 -0
  92. data/ext/gstreamer/ruby-gstreamer.pc +3 -0
  93. data/extconf.rb +49 -0
  94. data/lib/gst.rb +19 -0
  95. data/sample/audio-player.rb +54 -0
  96. data/sample/gst-inspect.rb +417 -0
  97. data/sample/media-type.rb +55 -0
  98. data/sample/media-type2.rb +268 -0
  99. data/sample/ogg-audio-player.rb +54 -0
  100. data/sample/type-find.rb +46 -0
  101. data/sample/video-player.rb +57 -0
  102. data/sample/xml-player.rb +60 -0
  103. data/test/gst-test-utils.rb +18 -0
  104. data/test/run-test.rb +25 -0
  105. data/test/test_bin.rb +167 -0
  106. data/test/test_buffer.rb +174 -0
  107. data/test/test_caps.rb +24 -0
  108. data/test/test_clock.rb +7 -0
  109. data/test/test_element.rb +87 -0
  110. data/test/test_element_factory.rb +28 -0
  111. data/test/test_event.rb +10 -0
  112. data/test/test_index_factory.rb +7 -0
  113. data/test/test_message.rb +191 -0
  114. data/test/test_mini_object.rb +38 -0
  115. data/test/test_object.rb +10 -0
  116. data/test/test_pad.rb +68 -0
  117. data/test/test_plugin.rb +6 -0
  118. data/test/test_plugin_feature.rb +20 -0
  119. data/test/test_seek.rb +17 -0
  120. data/test/test_static_caps.rb +18 -0
  121. data/test/test_static_pad_template.rb +16 -0
  122. data/test/test_structure.rb +159 -0
  123. data/test/test_thread_handling.rb +58 -0
  124. data/test/test_type_find_factory.rb +8 -0
  125. data/test/test_value.rb +69 -0
  126. metadata +208 -0
Binary file
@@ -0,0 +1,108 @@
1
+ /*
2
+ * Copyright (C) 2003, 2004 Laurent Sansonetti <lrz@gnome.org>
3
+ * Copyright (C) 2007 Ruby-GNOME2 Project Team
4
+ *
5
+ * This file is part of Ruby/GStreamer.
6
+ *
7
+ * Ruby/GStreamer is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * Ruby/GStreamer is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with Ruby/GStreamer; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+ #include "rbgst.h"
23
+
24
+ #define SELF(obj) (RVAL2GST_CLOCK(obj))
25
+
26
+ /* Class: Gst::Clock
27
+ * Abstract class for global clocks.
28
+ */
29
+
30
+ /* Method: resolution
31
+ * Returns: the accuracy of the clock.
32
+ */
33
+ static VALUE
34
+ get_resolution(VALUE self)
35
+ {
36
+ return ULL2NUM(gst_clock_get_resolution(SELF(self)));
37
+ }
38
+
39
+ /*
40
+ * Method: set_resolution(resolution)
41
+ * resolution: the accuracy of the clock.
42
+ *
43
+ * Sets the accuracy of the clock.
44
+ *
45
+ * Returns: self.
46
+ */
47
+ static VALUE
48
+ set_resolution(VALUE self, VALUE resolution)
49
+ {
50
+ return ULL2NUM(gst_clock_set_resolution(SELF(self), NUM2ULL(resolution)));
51
+ }
52
+
53
+ /* Method: time
54
+ * Returns: the time of the clock (in nanoseconds).
55
+ */
56
+ static VALUE
57
+ get_time(VALUE self)
58
+ {
59
+ return ULL2NUM(gst_clock_get_time(SELF(self)));
60
+ }
61
+
62
+ /*
63
+ * Method: ==(clock)
64
+ * clock: a Gst::Clock object.
65
+ *
66
+ * Returns: true if two Gst::Clock objects are synchronized on the same time,
67
+ * false otherwise.
68
+ */
69
+ static VALUE
70
+ equal_p(VALUE self, VALUE other_clock)
71
+ {
72
+ if (NIL_P(other_clock))
73
+ return Qfalse;
74
+ else {
75
+ GstClock *c1 = SELF(self);
76
+ GstClock *c2 = SELF(other_clock);
77
+
78
+ return CBOOL2RVAL(GST_CLOCK_DIFF(c1, c2) == 0);
79
+ }
80
+ }
81
+
82
+ void
83
+ Init_gst_clock (void)
84
+ {
85
+ VALUE rb_cGstClock, rb_mGstClockTime;
86
+
87
+ rb_cGstClock = G_DEF_CLASS(GST_TYPE_CLOCK, "Clock", mGst);
88
+
89
+ rb_define_const(mGst, "SECOND", LL2NUM(GST_SECOND));
90
+ rb_define_const(mGst, "MSECOND", LL2NUM(GST_MSECOND));
91
+ rb_define_const(mGst, "USECOND", LL2NUM(GST_USECOND));
92
+ rb_define_const(mGst, "NSECOND", LL2NUM(GST_NSECOND));
93
+
94
+ rb_mGstClockTime = rb_define_module_under(mGst, "ClockTime");
95
+ rb_define_const(rb_mGstClockTime, "NONE", ULL2NUM(GST_CLOCK_TIME_NONE));
96
+
97
+ G_DEF_CLASS(GST_TYPE_CLOCK_FLAGS, "Flags", rb_cGstClock);
98
+ G_DEF_CONSTANTS(rb_cGstClock, GST_TYPE_CLOCK_FLAGS, "GST_CLOCK_");
99
+ G_DEF_CLASS(GST_TYPE_CLOCK_RETURN, "Return", rb_cGstClock);
100
+ G_DEF_CONSTANTS(rb_cGstClock, GST_TYPE_CLOCK_RETURN, "GST_CLOCK_");
101
+
102
+ rb_define_method(rb_cGstClock, "resolution", get_resolution, 0);
103
+ rb_define_method(rb_cGstClock, "set_resolution", set_resolution, 1);
104
+ rb_define_method(rb_cGstClock, "time", get_time, 0);
105
+ rb_define_method(rb_cGstClock, "==", equal_p, 1);
106
+
107
+ G_DEF_SETTERS(rb_cGstClock);
108
+ }
Binary file
@@ -0,0 +1,255 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright (C) 2003, 2004 Laurent Sansonetti <lrz@gnome.org>
4
+ * Copyright (C) 2007 Ruby-GNOME2 Project Team
5
+ *
6
+ * This file is part of Ruby/GStreamer.
7
+ *
8
+ * Ruby/GStreamer is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * Ruby/GStreamer is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with Ruby/GStreamer; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
+ */
22
+
23
+ #include "rbgst.h"
24
+
25
+ #define SELF(self) RVAL2GST_ELEMENT_FACTORY(self)
26
+
27
+ /* Class: Gst::ElementFactory
28
+ * Creates Gst::Element instances.
29
+ */
30
+
31
+ /*
32
+ * Class method: make(factory_name, element_name)
33
+ * factory_name: a name of an existing factory.
34
+ * element_name: a name which will be attributed to the element.
35
+ *
36
+ * Creates a new Gst::Element of the type defined by the given element factory.
37
+ *
38
+ * If element name is ommited (or nil), then the element will receive a guaranteed
39
+ * unique name, consisting of the element factory name and a number.
40
+ * If name is given, it will be given the name supplied.
41
+ *
42
+ * # Creates a 'mad' GStreamer element, named 'foo':
43
+ * elem1 = Gst::ElementFactory.make("mad", "foo")
44
+ *
45
+ * # This line does exactly the same thing:
46
+ * elem2 = Gst::ElementFactory.find("mad").create("foo")
47
+ *
48
+ * Returns: a newly created object based on Gst::Element.
49
+ */
50
+ static VALUE
51
+ rb_gst_elementfactory_make(int argc, VALUE *argv, VALUE self)
52
+ {
53
+ GstElement *element;
54
+ VALUE fname, ename;
55
+ VALUE ret;
56
+
57
+ rb_scan_args(argc, argv, "11", &fname, &ename);
58
+
59
+ element = gst_element_factory_make(RVAL2CSTR(fname),
60
+ RVAL2CSTR_ACCEPT_NIL(ename));
61
+
62
+ if (element == NULL)
63
+ return Qnil;
64
+
65
+ /* This add another ref to the element, but it was already ours so
66
+ * unref it again */
67
+ ret = GOBJ2RVAL(element);
68
+ GOBJ2RVAL_UNREF(element);
69
+ return ret;
70
+ }
71
+
72
+ /*
73
+ * Class method: find(factory_name)
74
+ * factory_name: a name of an existing factory.
75
+ *
76
+ * Searches for an element factory of the given name.
77
+ *
78
+ * Returns: a Gst::ElementFactory object if found, nil otherwise.
79
+ */
80
+ static VALUE
81
+ rb_gst_elementfactory_find (VALUE self, VALUE factory_name)
82
+ {
83
+ GstElementFactory *factory = gst_element_factory_find (RVAL2CSTR (factory_name));
84
+ return factory != NULL
85
+ ? RGST_ELEMENT_FACTORY_NEW (factory)
86
+ : Qnil;
87
+ }
88
+
89
+ /*
90
+ * Method: create(element_name=nil)
91
+ * element_name: a name which will be attributed to the element.
92
+ *
93
+ * Creates a new element of the type defined by the element factory.
94
+ *
95
+ * If element name is ommited (or nil), then the element will receive a guaranteed
96
+ * unique name, consisting of the element factory name and a number.
97
+ * If name is given, it will be given the name supplied.
98
+ *
99
+ * Returns: a newly created object based on Gst::Element.
100
+ */
101
+ static VALUE
102
+ create(int argc, VALUE *argv, VALUE self)
103
+ {
104
+ GstElement *element;
105
+ VALUE name;
106
+
107
+ rb_scan_args(argc, argv, "01", &name);
108
+
109
+ element = gst_element_factory_create(SELF(self), RVAL2CSTR_ACCEPT_NIL(name));
110
+ return GOBJ2RVAL(element);
111
+ }
112
+
113
+ static VALUE
114
+ rb_gst_elementfactory_to_s (VALUE self)
115
+ {
116
+ GstElementFactory *factory = RGST_ELEMENT_FACTORY (self);
117
+ return rb_str_new_with_format ("Element: %s (%s)",
118
+ GST_PLUGIN_FEATURE_NAME(factory),
119
+ factory->details.longname);
120
+ }
121
+
122
+ /*
123
+ * Method: pad_templates
124
+ *
125
+ * Requests all pad templates of factory.
126
+ *
127
+ * Returns: an array of Gst::PadTemplate objects.
128
+ */
129
+ static VALUE
130
+ rb_gst_elementfactory_get_pad_templates (VALUE self)
131
+ {
132
+ GstElementFactory *factory;
133
+ const GList *list;
134
+ VALUE arr;
135
+
136
+ arr = rb_ary_new();
137
+ factory = RGST_ELEMENT_FACTORY(self);
138
+ for (list = gst_element_factory_get_static_pad_templates(factory);
139
+ list != NULL;
140
+ list = g_list_next(list)) {
141
+ GstStaticPadTemplate *pad = list->data;
142
+ rb_ary_push(arr, GST_STATIC_PAD_TEMPLATE2RVAL(pad));
143
+ }
144
+ return arr;
145
+ }
146
+
147
+ /*
148
+ * Method: each_pad_template { |pad_template| ... }
149
+ *
150
+ * Calls the block for each pad template of the factory, passing a
151
+ * reference to the Gst::PadTemplate as parameter.
152
+ *
153
+ * Returns: always nil.
154
+ */
155
+ static VALUE
156
+ rb_gst_elementfactory_each_pad_template (VALUE self)
157
+ {
158
+ return rb_ary_yield (rb_gst_elementfactory_get_pad_templates (self));
159
+ }
160
+
161
+ /*
162
+ * Method: details
163
+ *
164
+ * Gets some public information about the factory,
165
+ * mostly for the benefit of editors.
166
+ *
167
+ * This information is encapsulated in a Hash object,
168
+ * with the following (String) keys:
169
+ *
170
+ * * longname: long (English) element name.
171
+ * * klass: type of element, as hierarchy.
172
+ * * description: a short description about the element.
173
+ * * author: some information about the author(s).
174
+ *
175
+ * Here is an example.
176
+ *
177
+ * # Prints all details related to the 'mad' element:
178
+ * Gst::ElementFactory.find("mad").details do |k, v|
179
+ * p "#{k}: #{v}"
180
+ * end
181
+ *
182
+ * Returns: a Hash.
183
+ */
184
+ static VALUE
185
+ rb_gst_elementfactory_get_details (VALUE self)
186
+ {
187
+ GstElementFactory *factory;
188
+ VALUE hash;
189
+
190
+ factory = RGST_ELEMENT_FACTORY (self);
191
+
192
+ hash = rb_hash_new();
193
+
194
+ rb_hash_aset (hash, CSTR2RVAL ("longname"), CSTR2RVAL (factory->details.longname));
195
+ rb_hash_aset (hash, CSTR2RVAL ("klass"), CSTR2RVAL (factory->details.klass));
196
+ rb_hash_aset (hash, CSTR2RVAL ("description"), CSTR2RVAL (factory->details.description));
197
+ rb_hash_aset (hash, CSTR2RVAL ("author"), CSTR2RVAL (factory->details.author));
198
+
199
+ return hash;
200
+ }
201
+
202
+ static VALUE
203
+ get_long_name(VALUE self)
204
+ {
205
+ return CSTR2RVAL(gst_element_factory_get_longname(SELF(self)));
206
+ }
207
+
208
+ static VALUE
209
+ get_klass(VALUE self)
210
+ {
211
+ return CSTR2RVAL(gst_element_factory_get_klass(SELF(self)));
212
+ }
213
+
214
+ static VALUE
215
+ get_description(VALUE self)
216
+ {
217
+ return CSTR2RVAL(gst_element_factory_get_description(SELF(self)));
218
+ }
219
+
220
+ static VALUE
221
+ get_author(VALUE self)
222
+ {
223
+ return CSTR2RVAL(gst_element_factory_get_author(SELF(self)));
224
+ }
225
+
226
+
227
+ void
228
+ Init_gst_elementfactory (void)
229
+ {
230
+ VALUE rb_cGstElementFactory;
231
+
232
+ rb_cGstElementFactory = G_DEF_CLASS(GST_TYPE_ELEMENT_FACTORY,
233
+ "ElementFactory",
234
+ mGst);
235
+
236
+ rb_define_singleton_method(rb_cGstElementFactory, "make",
237
+ rb_gst_elementfactory_make, -1);
238
+ rb_define_singleton_method(rb_cGstElementFactory, "find",
239
+ rb_gst_elementfactory_find, 1);
240
+
241
+ rb_define_method(rb_cGstElementFactory, "create", create, -1);
242
+ rb_define_method(rb_cGstElementFactory, "details",
243
+ rb_gst_elementfactory_get_details, 0);
244
+ rb_define_method(rb_cGstElementFactory, "to_s",
245
+ rb_gst_elementfactory_to_s, 0);
246
+ rb_define_method(rb_cGstElementFactory, "pad_templates",
247
+ rb_gst_elementfactory_get_pad_templates, 0);
248
+ rb_define_method(rb_cGstElementFactory, "each_pad_template",
249
+ rb_gst_elementfactory_each_pad_template, 0);
250
+
251
+ rb_define_method(rb_cGstElementFactory, "long_name", get_long_name, 0);
252
+ rb_define_method(rb_cGstElementFactory, "klass", get_klass, 0);
253
+ rb_define_method(rb_cGstElementFactory, "description", get_description, 0);
254
+ rb_define_method(rb_cGstElementFactory, "author", get_author, 0);
255
+ }
@@ -0,0 +1,1053 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright (C) 2003, 2004 Laurent Sansonetti <lrz@gnome.org>
4
+ * Copyright (C) 2007, 2008 Ruby-GNOME2 Project Team
5
+ * Copyright (C) 2006, 2008 Sjoerd Simons <sjoerd@luon.net>
6
+ *
7
+ * This file is part of Ruby/GStreamer.
8
+ *
9
+ * Ruby/GStreamer is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU Lesser General Public
11
+ * License as published by the Free Software Foundation; either
12
+ * version 2.1 of the License, or (at your option) any later version.
13
+ *
14
+ * Ruby/GStreamer is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ * Lesser General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU Lesser General Public
20
+ * License along with Ruby/GStreamer; if not, write to the Free Software
21
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
+ */
23
+
24
+ #include "rbgst.h"
25
+ #include "rbgst-private.h"
26
+
27
+ #ifdef HAVE_UNISTD_H
28
+ # include <unistd.h>
29
+ #endif
30
+ #ifdef HAVE_IO_H
31
+ # include <io.h>
32
+ # define pipe(phandles) _pipe(phandles, 128, _O_BINARY)
33
+ #endif
34
+ #include <fcntl.h>
35
+ #include <errno.h>
36
+
37
+ #define SELF(self) RVAL2GST_ELEMENT(self)
38
+
39
+ #define GST_STATE_CHANGE_RETURN2RVAL(object) \
40
+ (GENUM2RVAL(object, GST_TYPE_STATE_CHANGE_RETURN))
41
+
42
+ #define NOTIFY_MESSAGE "R"
43
+ #define NOTIFY_MESSAGE_SIZE 1
44
+
45
+ typedef struct _SetStateData {
46
+ GstStateChangeReturn result;
47
+ GstState state;
48
+ } SetStateData;
49
+
50
+ typedef struct _GetStateData {
51
+ GstStateChangeReturn result;
52
+ GstState state;
53
+ GstState pending;
54
+ GstClockTime timeout;
55
+ } GetStateData;
56
+
57
+ typedef struct _QueryData {
58
+ gboolean result;
59
+ GstQuery *query;
60
+ } QueryData;
61
+
62
+ typedef struct _SendEventData {
63
+ gboolean result;
64
+ GstEvent *event;
65
+ } SendEventData;
66
+
67
+ typedef struct _ThreadData {
68
+ GstElement *element;
69
+ int notify_fd;
70
+ union {
71
+ SetStateData set_state_data;
72
+ GetStateData get_state_data;
73
+ QueryData query_data;
74
+ SendEventData send_event_data;
75
+ } data;
76
+ } ThreadData;
77
+
78
+ static RGConvertTable table = {0};
79
+ static VALUE rb_cGstElement;
80
+ static ID id_gtype;
81
+ static GThreadPool *set_state_thread_pool;
82
+ static GThreadPool *get_state_thread_pool;
83
+ static GThreadPool *query_thread_pool;
84
+ static GThreadPool *send_event_thread_pool;
85
+
86
+ static void
87
+ define_class_if_need(VALUE klass, GType type)
88
+ {
89
+ _rbgst_define_class_if_need(klass, type, "Element");
90
+ }
91
+
92
+ static VALUE
93
+ instance2robj(gpointer instance)
94
+ {
95
+ VALUE klass;
96
+ GType type;
97
+
98
+ type = G_TYPE_FROM_INSTANCE(instance);
99
+ klass = GTYPE2CLASS(type);
100
+ define_class_if_need(klass, type);
101
+ return rbgst_object_instance2robj(instance);
102
+ }
103
+
104
+
105
+ /* Class: Gst::Element
106
+ * Base class for all pipeline elements.
107
+ */
108
+
109
+ static void
110
+ do_in_thread(GThreadPool *pool, ThreadData *data)
111
+ {
112
+ int notify_fds[2];
113
+ char buf[NOTIFY_MESSAGE_SIZE];
114
+ GError *error = NULL;
115
+
116
+ if (pipe(notify_fds) != 0)
117
+ rb_sys_fail("failed to create a pipe to synchronize threaded operation");
118
+
119
+ data->notify_fd = notify_fds[1];
120
+ g_thread_pool_push(pool, data, &error);
121
+ if (error) {
122
+ close(notify_fds[0]);
123
+ close(notify_fds[1]);
124
+ RAISE_GERROR(error);
125
+ }
126
+
127
+ rb_thread_wait_fd(notify_fds[0]);
128
+
129
+ read(notify_fds[0], buf, NOTIFY_MESSAGE_SIZE);
130
+
131
+
132
+ close(notify_fds[0]);
133
+ close(notify_fds[1]);
134
+ }
135
+
136
+ static void
137
+ set_state_in_thread(gpointer data, gpointer user_data)
138
+ {
139
+ ThreadData *thread_data = (ThreadData *)data;
140
+ SetStateData *set_state_data;
141
+
142
+ set_state_data = &(thread_data->data.set_state_data);
143
+ set_state_data->result = gst_element_set_state(thread_data->element,
144
+ set_state_data->state);
145
+ write(thread_data->notify_fd, NOTIFY_MESSAGE, NOTIFY_MESSAGE_SIZE);
146
+ }
147
+
148
+ static VALUE
149
+ rb_gst_element_set_state_internal(VALUE self, GstState state)
150
+ {
151
+ VALUE result;
152
+ ThreadData *thread_data;
153
+ SetStateData *set_state_data;
154
+
155
+ thread_data = g_slice_new(ThreadData);
156
+ thread_data->element = SELF(self);
157
+ set_state_data = &(thread_data->data.set_state_data);
158
+ set_state_data->state = state;
159
+
160
+ do_in_thread(set_state_thread_pool, thread_data);
161
+
162
+ result = GST_STATE_CHANGE_RETURN2RVAL(set_state_data->result);
163
+
164
+ g_slice_free(ThreadData, thread_data);
165
+
166
+ return result;
167
+ }
168
+
169
+ /*
170
+ * Method: set_state(state)
171
+ * state: the state you want to set (see Gst::Element::State).
172
+ *
173
+ * Sets the state of the element.
174
+ *
175
+ * This method will try to set the requested state by going through all
176
+ * the intermediary states and calling the class's state change function
177
+ * for each.
178
+ *
179
+ * Returns: a code (see Gst::Element::StateChangeReturn).
180
+ */
181
+ static VALUE
182
+ rb_gst_element_set_state(VALUE self, VALUE state)
183
+ {
184
+ return rb_gst_element_set_state_internal(self,
185
+ RVAL2GENUM(state, GST_TYPE_STATE));
186
+ }
187
+
188
+ static void
189
+ get_state_in_thread(gpointer data, gpointer user_data)
190
+ {
191
+ ThreadData *thread_data = (ThreadData *)data;
192
+ GetStateData *get_state_data;
193
+
194
+ get_state_data = &(thread_data->data.get_state_data);
195
+ get_state_data->result = gst_element_get_state(thread_data->element,
196
+ &(get_state_data->state),
197
+ &(get_state_data->pending),
198
+ get_state_data->timeout);
199
+ write(thread_data->notify_fd, NOTIFY_MESSAGE, NOTIFY_MESSAGE_SIZE);
200
+ }
201
+
202
+ /* Method: get_state(timeout=nil)
203
+ */
204
+ static VALUE
205
+ rb_gst_element_get_state(int argc, VALUE *argv, VALUE self)
206
+ {
207
+ VALUE result, timeout;
208
+ ThreadData *thread_data;
209
+ GetStateData *get_state_data;
210
+
211
+ rb_scan_args(argc, argv, "01", &timeout);
212
+
213
+ thread_data = g_slice_new(ThreadData);
214
+ thread_data->element = SELF(self);
215
+ get_state_data = &(thread_data->data.get_state_data);
216
+ if (NIL_P(timeout))
217
+ get_state_data->timeout = GST_CLOCK_TIME_NONE;
218
+ else
219
+ get_state_data->timeout = NUM2ULL(timeout);
220
+
221
+ do_in_thread(get_state_thread_pool, thread_data);
222
+
223
+ result = rb_ary_new3(3,
224
+ GST_STATE_CHANGE_RETURN2RVAL(get_state_data->result),
225
+ GST_STATE2RVAL(get_state_data->state),
226
+ GST_STATE2RVAL(get_state_data->pending));
227
+
228
+ g_slice_free(ThreadData, thread_data);
229
+
230
+ return result;
231
+ }
232
+
233
+ /*
234
+ * Method: stop
235
+ *
236
+ * This method calls Gst::Element#set_state with Gst::Element::STATE_NULL.
237
+ *
238
+ * Returns: a code (see Gst::Element::StateChangeReturn).
239
+ */
240
+ static VALUE
241
+ rb_gst_element_stop(VALUE self)
242
+ {
243
+ return rb_gst_element_set_state_internal(self, GST_STATE_NULL);
244
+ }
245
+
246
+ /*
247
+ * Method: ready
248
+ *
249
+ * This method calls Gst::Element#set_state with Gst::Element::STATE_READY.
250
+ *
251
+ * Returns: a code (see Gst::Element::StateChangeReturn).
252
+ */
253
+ static VALUE
254
+ rb_gst_element_ready(VALUE self)
255
+ {
256
+ return rb_gst_element_set_state_internal(self, GST_STATE_READY);
257
+ }
258
+
259
+ /*
260
+ * Method: pause
261
+ *
262
+ * This method calls Gst::Element#set_state with Gst::Element::STATE_PAUSED.
263
+ *
264
+ * Returns: a code (see Gst::Element::StateChangedReturn).
265
+ */
266
+ static VALUE
267
+ rb_gst_element_pause(VALUE self)
268
+ {
269
+ return rb_gst_element_set_state_internal(self, GST_STATE_PAUSED);
270
+ }
271
+
272
+ /*
273
+ * Method: play
274
+ *
275
+ * This method calls Gst::Element#set_state with Gst::Element::STATE_PLAYING.
276
+ *
277
+ * Returns: a code (see Gst::Element::StateChangedReturn).
278
+ */
279
+ static VALUE
280
+ rb_gst_element_play(VALUE self)
281
+ {
282
+ return rb_gst_element_set_state_internal(self, GST_STATE_PLAYING);
283
+ }
284
+
285
+ /*
286
+ * Method: link(element)
287
+ * element: a Gst::Element object.
288
+ *
289
+ * Links this element (source) to the provided element (destination).
290
+ *
291
+ * The method looks for existing pads and request pads that
292
+ * aren't linked yet. If multiple links are possible, only one
293
+ * is established.
294
+ *
295
+ * Returns: the destination element, or nil if the link failed.
296
+ */
297
+ static VALUE
298
+ rb_gst_element_link(VALUE self, VALUE other_element)
299
+ {
300
+ GstElement *element1, *element2;
301
+
302
+ element1 = SELF(self);
303
+ element2 = SELF(other_element);
304
+ return gst_element_link(element1, element2) == TRUE ? other_element : Qnil;
305
+ }
306
+
307
+ /*
308
+ * Method: unlink(element)
309
+ * element: a Gst::Element object.
310
+ *
311
+ * Unlinks this element (source) to the provided element (destination).
312
+ *
313
+ * The method looks for all source pads of the source elemnt that are
314
+ * linked to the destination element and unlinkes them.
315
+ *
316
+ */
317
+ static VALUE
318
+ rb_gst_element_unlink(VALUE self, VALUE other_element)
319
+ {
320
+ GstElement *element1, *element2;
321
+
322
+ element1 = SELF(self);
323
+ element2 = SELF(other_element);
324
+ gst_element_unlink(element1, element2);
325
+ return self;
326
+ }
327
+
328
+ /*
329
+ * Method: link_filtered(element, caps)
330
+ * element: a Gst::Element object.
331
+ * caps: a Gst::Caps object.
332
+ *
333
+ * Links this element (source) to the provided element (destination),
334
+ * filtered by the given caps.
335
+ *
336
+ * The method looks for existing pads and request pads that
337
+ * aren't linked yet. If multiple links are possible, only one
338
+ * is established.
339
+ *
340
+ * Returns: the destination element, or nil if the link failed.
341
+ */
342
+ static VALUE
343
+ rb_gst_element_link_filtered(VALUE self, VALUE other_element, VALUE rcaps)
344
+ {
345
+ GstElement *element1, *element2;
346
+ GstCaps *caps;
347
+
348
+ element1 = SELF(self);
349
+ element2 = SELF(other_element);
350
+ caps = RGST_CAPS(rcaps);
351
+ return gst_element_link_filtered(element1, element2, caps)
352
+ ? other_element
353
+ : Qnil;
354
+ }
355
+
356
+ /* Method: requires_clock?
357
+ * Returns: true if the element requires a clock, false otherwise.
358
+ */
359
+ static VALUE
360
+ rb_gst_element_requires_clock(VALUE self)
361
+ {
362
+ return CBOOL2RVAL(gst_element_requires_clock(SELF(self)));
363
+ }
364
+
365
+ /* Method: provides_clock?
366
+ * Returns: true if the element provides a clock, false otherwise.
367
+ */
368
+ static VALUE
369
+ rb_gst_element_provides_clock(VALUE self)
370
+ {
371
+ return CBOOL2RVAL(gst_element_provides_clock(SELF(self)));
372
+ }
373
+
374
+ /* Method: clock
375
+ * Returns: the clock of the element (as a Gst::Clock object), or nil
376
+ * if this element does not provide a clock.
377
+ */
378
+ static VALUE
379
+ rb_gst_element_get_clock(VALUE self)
380
+ {
381
+ GstClock *clock;
382
+
383
+ clock = gst_element_get_clock(SELF(self));
384
+ return clock != NULL ? RGST_CLOCK_NEW(clock)
385
+ : Qnil;
386
+ }
387
+
388
+ /*
389
+ * Method: set_clock(clock)
390
+ * clock: the Gst::Clock to set for the element.
391
+ *
392
+ * Sets the clock for the element.
393
+ *
394
+ * Returns: self.
395
+ */
396
+ static VALUE
397
+ rb_gst_element_set_clock(VALUE self, VALUE clock)
398
+ {
399
+ gst_element_set_clock(SELF(self), RVAL2GST_CLOCK(clock));
400
+ return self;
401
+ }
402
+
403
+ typedef void (*EachPadCallback)(VALUE pad, VALUE user_data);
404
+ typedef struct _EachPadData {
405
+ VALUE self;
406
+ EachPadCallback callback;
407
+ VALUE user_data;
408
+ GstIterator *iterator;
409
+ } EachPadData;
410
+
411
+ static VALUE
412
+ rb_gst_element_each_pad_body(VALUE user_data)
413
+ {
414
+ GstPad *pad;
415
+ gboolean done = FALSE;
416
+ EachPadData *data;
417
+
418
+ data = (EachPadData *)user_data;
419
+
420
+ while (!done) {
421
+ switch (gst_iterator_next(data->iterator, (gpointer)&pad)) {
422
+ case GST_ITERATOR_OK:
423
+ data->callback(GST_PAD2RVAL(pad), data->user_data);
424
+ gst_object_unref(pad);
425
+ break;
426
+ case GST_ITERATOR_RESYNC:
427
+ gst_iterator_resync(data->iterator);
428
+ break;
429
+ case GST_ITERATOR_ERROR:
430
+ rb_raise(rb_eIndexError, "Pad iteration failed");
431
+ break;
432
+ case GST_ITERATOR_DONE:
433
+ done = TRUE;
434
+ break;
435
+ }
436
+ }
437
+
438
+ return Qnil;
439
+ }
440
+
441
+ static VALUE
442
+ rb_gst_element_each_pad_ensure(VALUE user_data)
443
+ {
444
+ EachPadData *data = (EachPadData *)user_data;
445
+
446
+ gst_iterator_free(data->iterator);
447
+ return Qnil;
448
+ }
449
+
450
+ static VALUE
451
+ rb_gst_element_each_pad_with_callback(VALUE self,
452
+ EachPadCallback callback,
453
+ VALUE user_data)
454
+ {
455
+ EachPadData data;
456
+
457
+ data.self = self;
458
+ data.callback = callback;
459
+ data.user_data = user_data;
460
+ data.iterator = gst_element_iterate_pads(SELF(self));
461
+ return rb_ensure(rb_gst_element_each_pad_body, (VALUE)(&data),
462
+ rb_gst_element_each_pad_ensure, (VALUE)(&data));
463
+ }
464
+
465
+ /*
466
+ * Method: each_pad { |pad| ... }
467
+ *
468
+ * Calls the block for each pad associated with the element, passing a
469
+ * reference to the Gst::Pad as parameter. Throws an IndexError on errors.
470
+ * Note that the elements might be yielded multiple times if the iterator had
471
+ * to resync.
472
+ *
473
+ * Returns: always nil.
474
+ */
475
+ static VALUE
476
+ rb_gst_element_each_pad(VALUE self)
477
+ {
478
+ rb_gst_element_each_pad_with_callback(self, (EachPadCallback)rb_yield, Qnil);
479
+ return Qnil;
480
+ }
481
+
482
+ static void
483
+ collect_pad(VALUE pad, VALUE pads)
484
+ {
485
+ rb_ary_push(pads, pad);
486
+ }
487
+
488
+ static VALUE
489
+ rb_gst_element_get_pads(VALUE self)
490
+ {
491
+ VALUE pads;
492
+
493
+ pads = rb_ary_new();
494
+ rb_gst_element_each_pad_with_callback(self, collect_pad, pads);
495
+ return pads;
496
+ }
497
+
498
+ /*
499
+ * Method: get_pad(name)
500
+ * name: the name of a pad.
501
+ *
502
+ * Retrieves a Gst::Pad object from the element by name.
503
+ *
504
+ * Returns: a Gst::Pad object, or nil if the pad cannot be found.
505
+ */
506
+ static VALUE
507
+ rb_gst_element_get_pad(VALUE self, VALUE pad_name)
508
+ {
509
+ GstPad *pad = gst_element_get_pad(SELF(self),
510
+ RVAL2CSTR(pad_name));
511
+
512
+ return pad != NULL ? RGST_PAD_NEW(pad)
513
+ : Qnil;
514
+ }
515
+
516
+ /*
517
+ * Method: link_pads(source_pad_name, element, destination_pad_name)
518
+ * element: a Gst::Element.
519
+ *
520
+ * Links the source_pad_name pad of the current element to the
521
+ * destination_pad_name pad of the destination element, returning
522
+ * true on success.
523
+ *
524
+ * Returns: true on success, false on failure.
525
+ */
526
+ static VALUE
527
+ rb_gst_element_link_pads(VALUE self, VALUE source_pad_name,
528
+ VALUE other_element, VALUE destination_pad_name)
529
+ {
530
+ return CBOOL2RVAL(gst_element_link_pads(SELF(self),
531
+ RVAL2CSTR(source_pad_name),
532
+ SELF(other_element),
533
+ RVAL2CSTR(destination_pad_name)));
534
+ }
535
+
536
+ /*
537
+ * Method: unlink_pads(source_pad_name, element, destination_pad_name)
538
+ * element: a Gst::Element.
539
+ *
540
+ * Unlinks the source_pad_name named pad of the current element from the
541
+ * destination_pad_name named pad of the destination element.
542
+ *
543
+ * Returns: self.
544
+ */
545
+ static VALUE
546
+ rb_gst_element_unlink_pads(VALUE self, VALUE source_pad_name,
547
+ VALUE other_element, VALUE destination_pad_name)
548
+ {
549
+ gst_element_unlink_pads(SELF(self),
550
+ RVAL2CSTR(source_pad_name),
551
+ SELF(other_element),
552
+ RVAL2CSTR(destination_pad_name));
553
+ return self;
554
+ }
555
+
556
+ /* Method: indexable?
557
+ * Returns: true if the element can be indexed, false otherwise.
558
+ */
559
+ static VALUE
560
+ rb_gst_element_is_indexable(VALUE self)
561
+ {
562
+ return CBOOL2RVAL(gst_element_is_indexable(SELF(self)));
563
+ }
564
+
565
+ static void
566
+ query_in_thread(gpointer data, gpointer user_data)
567
+ {
568
+ ThreadData *thread_data = (ThreadData *)data;
569
+ QueryData *query_data;
570
+
571
+ query_data = &(thread_data->data.query_data);
572
+ query_data->result = gst_element_query(thread_data->element,
573
+ query_data->query);
574
+ write(thread_data->notify_fd, NOTIFY_MESSAGE, NOTIFY_MESSAGE_SIZE);
575
+ }
576
+
577
+ /*
578
+ * Method: query(query)
579
+ * query: a query type (see Gst::Query).
580
+ *
581
+ * Performs a query on the element.
582
+ *
583
+ * Returns: true if the query is performed, false otherwise.
584
+ */
585
+ static VALUE
586
+ rb_gst_element_query(VALUE self, VALUE query)
587
+ {
588
+ VALUE result;
589
+ ThreadData *thread_data;
590
+ QueryData *query_data;
591
+
592
+ thread_data = g_slice_new(ThreadData);
593
+ thread_data->element = SELF(self);
594
+ query_data = &(thread_data->data.query_data);
595
+ query_data->query = RVAL2GST_QUERY(query);
596
+
597
+ do_in_thread(query_thread_pool, thread_data);
598
+
599
+ result = CBOOL2RVAL(query_data->result);
600
+
601
+ g_slice_free(ThreadData, thread_data);
602
+
603
+ return result;
604
+ }
605
+
606
+ static void
607
+ send_event_in_thread(gpointer data, gpointer user_data)
608
+ {
609
+ ThreadData *thread_data = (ThreadData *)data;
610
+ SendEventData *send_event_data;
611
+
612
+ send_event_data = &(thread_data->data.send_event_data);
613
+ send_event_data->result = gst_element_send_event(thread_data->element,
614
+ send_event_data->event);
615
+ write(thread_data->notify_fd, NOTIFY_MESSAGE, NOTIFY_MESSAGE_SIZE);
616
+ }
617
+ /*
618
+ * Method: send_event(event)
619
+ * event: a Gst::Event object.
620
+ *
621
+ * Sends an event to an element, through a Gst::Event object.
622
+ * If the element doesn't implement an event handler, the event will be
623
+ * forwarded to a random sink pad.
624
+ *
625
+ * Returns: true if the request event was successfully handled, false
626
+ * otherwise.
627
+ */
628
+ static VALUE
629
+ rb_gst_element_send_event(VALUE self, VALUE event)
630
+ {
631
+ VALUE result;
632
+ ThreadData *thread_data;
633
+ SendEventData *send_event_data;
634
+
635
+ thread_data = g_slice_new(ThreadData);
636
+ thread_data->element = SELF(self);
637
+ send_event_data = &(thread_data->data.send_event_data);
638
+ send_event_data->event = RVAL2GST_EVENT(event);
639
+
640
+ gst_event_ref(send_event_data->event);
641
+ do_in_thread(send_event_thread_pool, thread_data);
642
+
643
+ result = CBOOL2RVAL(send_event_data->result);
644
+
645
+ g_slice_free(ThreadData, thread_data);
646
+
647
+ return result;
648
+ }
649
+
650
+ /*
651
+ * Method: base_time
652
+ *
653
+ * Queries the element's time.
654
+ *
655
+ * Returns: the current stream time (in nanoseconds) in Gst::Element::STATE_PLAYING, the
656
+ * element base time in Gst::Element::STATE_PAUSED, or -1 otherwise.
657
+ */
658
+ static VALUE
659
+ rb_gst_element_get_base_time(VALUE self)
660
+ {
661
+ return ULL2NUM(gst_element_get_base_time(SELF(self)));
662
+ }
663
+
664
+ /*
665
+ * Method: set_base_time(time)
666
+ * time: time to set (in nanoseconds).
667
+ *
668
+ * Sets the current time of the element. This method can be used when handling discont events.
669
+ * You can only call this method on an element with a clock in Gst::Element::STATE_PAUSED or
670
+ * Gst::Element::STATE_PLAYING. You might want to have a look at Gst::Element#adjust_time, if
671
+ * you want to adjust by a difference as that is more accurate.
672
+ *
673
+ * Returns: self.
674
+ */
675
+ static VALUE
676
+ rb_gst_element_set_base_time(VALUE self, VALUE time)
677
+ {
678
+ gst_element_set_base_time(SELF(self), NUM2ULL(time));
679
+ return Qnil;
680
+ }
681
+
682
+ /*
683
+ * Method: index
684
+ *
685
+ * Gets the index from the element.
686
+ *
687
+ * Returns: a Gst::Index or nil when no index was set on the element.
688
+ */
689
+ static VALUE
690
+ rb_gst_element_get_index(VALUE self)
691
+ {
692
+ GstIndex *index = gst_element_get_index(SELF(self));
693
+
694
+ return index != NULL ? RGST_INDEX_NEW(index)
695
+ : Qnil;
696
+ }
697
+
698
+ /*
699
+ * Method: set_index(index)
700
+ * index: the index to set, as a Gst::Index.
701
+ *
702
+ * Sets the specified index on the element.
703
+ *
704
+ * Returns: self.
705
+ */
706
+ static VALUE
707
+ rb_gst_element_set_index(VALUE self, VALUE index)
708
+ {
709
+ gst_element_set_index(SELF(self), RGST_INDEX(index));
710
+ return self;
711
+ }
712
+
713
+ /*
714
+ * Method: get_static_pad(name)
715
+ * name: the name of the static Gst::Pad to retrieve.
716
+ *
717
+ * Retrieves a pad from the element by name. This version only retrieves
718
+ * already existing (i.e. 'static') pads.
719
+ *
720
+ * Returns: the requested Gst::Pad if found, otherwise nil.
721
+ */
722
+ static VALUE
723
+ rb_gst_element_get_static_pad(VALUE self, VALUE name)
724
+ {
725
+ GstPad *pad =
726
+ gst_element_get_static_pad(SELF(self), RVAL2CSTR(name));
727
+ return pad != NULL ? RGST_PAD_NEW(pad) : Qnil;
728
+ }
729
+
730
+ /*
731
+ * Method: get_request_pad(name)
732
+ * name: the name of the request Gst::Pad to retrieve.
733
+ *
734
+ * Retrieves a pad from the element by name. This version only retrieves
735
+ * request pads.
736
+ *
737
+ * Returns: the requested Gst::Pad if found, otherwise nil.
738
+ */
739
+ static VALUE
740
+ rb_gst_element_get_request_pad(VALUE self, VALUE name)
741
+ {
742
+ GstPad *pad =
743
+ gst_element_get_request_pad(SELF(self), RVAL2CSTR(name));
744
+ return pad != NULL ? GST_PAD2RVAL_UNREF(pad) : Qnil;
745
+ }
746
+
747
+ /*
748
+ * Method: release_request_pad(pad)
749
+ * pad: the Gst::Pad to release.
750
+ *
751
+ * Makes the element free the previously requested pad ass obtained with
752
+ * Gst::Element#get_requested_pad.
753
+ *
754
+ * Returns: self.
755
+ */
756
+ static VALUE
757
+ rb_gst_element_release_request_pad(VALUE self, VALUE pad)
758
+ {
759
+ gst_element_release_request_pad(SELF(self), RGST_PAD(pad));
760
+ return self;
761
+ }
762
+
763
+ /*
764
+ * Method: add_pad(pad)
765
+ * pad: the Gst::Pad to add to the element.
766
+ *
767
+ * Adds a pad (link point) to the element. Pads are automatically activated
768
+ * when the element is in state Gst::Element::PLAYING.
769
+ *
770
+ * Returns: self.
771
+ */
772
+ static VALUE
773
+ rb_gst_element_add_pad(VALUE self, VALUE pad)
774
+ {
775
+ gst_element_add_pad(SELF(self), RGST_PAD(pad));
776
+ G_CHILD_ADD(self, pad);
777
+ return self;
778
+ }
779
+
780
+ /*
781
+ * Method: remove_pad(pad)
782
+ * pad: the Gst::Pad to remove from the element.
783
+ *
784
+ * Removes the given pad from the element.
785
+ *
786
+ * Returns: self.
787
+ */
788
+ static VALUE
789
+ rb_gst_element_remove_pad(VALUE self, VALUE pad)
790
+ {
791
+ gst_element_remove_pad(SELF(self), RGST_PAD(pad));
792
+ return self;
793
+ }
794
+
795
+ /*
796
+ * Class Method: get_pad_template(name)
797
+ * name: the name of the Gst::PadTemplate to get.
798
+ *
799
+ * Retrieves a Gst::PadTemplate from this element with the given name.
800
+ *
801
+ * Returns: the Gst::PadTemplate with the given name, or nil if none was found.
802
+ */
803
+ static VALUE
804
+ rb_gst_element_get_pad_template(VALUE self, VALUE name)
805
+ {
806
+ GstElementClass *element_class;
807
+ GstPadTemplate *template;
808
+
809
+ element_class = g_type_class_peek(CLASS2GTYPE(self));
810
+ template = gst_element_class_get_pad_template(element_class,
811
+ RVAL2CSTR(name));
812
+ return template == NULL ? Qnil : RGST_PAD_TEMPLATE_NEW(template);
813
+ }
814
+
815
+ /*
816
+ * Class Method: pad_templates
817
+ *
818
+ * Retrieves a list of pad templates associated with the element.
819
+ *
820
+ * Returns: an Array of Gst::PadTemplate objects.
821
+ */
822
+ static VALUE
823
+ rb_gst_element_get_pad_templates(VALUE self)
824
+ {
825
+ GstElementClass *element_class;
826
+ GList *list, *node;
827
+ VALUE ary;
828
+
829
+ ary = rb_ary_new();
830
+
831
+ element_class = g_type_class_peek(CLASS2GTYPE(self));
832
+ list = gst_element_class_get_pad_template_list(element_class);
833
+ for (node = list; node != NULL; node = g_list_next(node)) {
834
+ rb_ary_push(ary, RGST_PAD_TEMPLATE_NEW(node->data));
835
+ }
836
+ g_list_free(list);
837
+ return ary;
838
+ }
839
+
840
+ /*
841
+ * Class Method: each_pad_template { |pad_template| ... }
842
+ *
843
+ * Calls the block for each pad template associated with the element,
844
+ * passing a reference to a Gst::PadTemplate object as parameter.
845
+ *
846
+ * Returns: always nil.
847
+ */
848
+ static VALUE
849
+ rb_gst_element_each_pad_template(VALUE self)
850
+ {
851
+ return rb_ary_yield(rb_gst_element_get_pad_templates(self));
852
+ }
853
+
854
+ /*
855
+ * Method: seek(seek_type, offset)
856
+ * seek_type: the method to use for seeking (see Gst::EventSeek::Type).
857
+ * offset: the offset to seek to.
858
+ *
859
+ * Sends a seek event (Gst::EventSseek) to the element.
860
+ *
861
+ * Returns: true if the event was handled.
862
+ */
863
+ static VALUE
864
+ rb_gst_element_seek(VALUE self, VALUE rate, VALUE format, VALUE flags,
865
+ VALUE cur_type, VALUE cur, VALUE stop_type, VALUE stop)
866
+ {
867
+ return CBOOL2RVAL(gst_element_seek(SELF(self),
868
+ NUM2DBL(rate),
869
+ RVAL2GENUM(format, GST_TYPE_FORMAT),
870
+ RVAL2GFLAGS(flags, GST_TYPE_SEEK_FLAGS),
871
+ RVAL2GENUM(cur_type, GST_TYPE_SEEK_TYPE),
872
+ NUM2LL(cur),
873
+ RVAL2GENUM(stop_type, GST_TYPE_SEEK_TYPE),
874
+ NUM2LL(stop)));
875
+ }
876
+
877
+ /*
878
+ * Method: locked_state?
879
+ *
880
+ * Checks if the state of an element is locked. If the state of an element is
881
+ * locked, state changes of the parent don't affect the element. This way you
882
+ * can leave currently unused elements inside bins. Just lock their state
883
+ * before changing the state from Gst::Element::STATE_NULL.
884
+ *
885
+ * Returns: true if the element's state is locked.
886
+ */
887
+ static VALUE
888
+ rb_gst_element_is_locked_state(VALUE self)
889
+ {
890
+ return CBOOL2RVAL(gst_element_is_locked_state(SELF(self)));
891
+ }
892
+
893
+ /*
894
+ * Method: set_locked_state(state)
895
+ * state: whether to lock the element's state.
896
+ *
897
+ * Locks the state of an element, so state changes of the parent don't affect
898
+ * this element anymore.
899
+ *
900
+ * Returns: self.
901
+ */
902
+ static VALUE
903
+ rb_gst_element_set_locked_state(VALUE self, VALUE state)
904
+ {
905
+ gst_element_set_locked_state(SELF(self), RVAL2CBOOL(state));
906
+ return self;
907
+ }
908
+
909
+ /*
910
+ * Method: sync_state_with_parent
911
+ *
912
+ * Tries to change the state of the element to the same as its parent. If this
913
+ * method returns false, the state of element is undefined.
914
+ *
915
+ * Returns: true if the element's state could be synced to the parent's state.
916
+ */
917
+ static VALUE
918
+ rb_gst_element_sync_state_with_parent(VALUE self)
919
+ {
920
+ return
921
+ CBOOL2RVAL(gst_element_sync_state_with_parent(SELF(self)));
922
+ }
923
+
924
+ /*
925
+ * Method: no_more_pads
926
+ *
927
+ * Uses this method to signal that the element does not expect any more pads
928
+ * to show up in the current pipeline. This method should be called whenever
929
+ * pads have been added by the element itself.
930
+ * Elements with Gst::Pad::SOMETIMES pad templates use this in combination
931
+ * with autopluggers to figure out that the element is done initializing its
932
+ * pads.
933
+ *
934
+ * Returns: self.
935
+ */
936
+ static VALUE
937
+ rb_gst_element_no_more_pads(VALUE self)
938
+ {
939
+ gst_element_no_more_pads(SELF(self));
940
+ return self;
941
+ }
942
+
943
+ static VALUE
944
+ rb_gst_element_found_tag_sig(guint num, const GValue *values)
945
+ {
946
+ GstElement *element, *source;
947
+ GstTagList *tag_list;
948
+
949
+ element = g_value_get_object(&values[0]);
950
+ source = g_value_get_object(&values[1]);
951
+ tag_list = g_value_get_boxed(&values[2]);
952
+
953
+ return rb_ary_new3(3,
954
+ GST_ELEMENT2RVAL(element),
955
+ GST_ELEMENT2RVAL(source),
956
+ GST_STRUCT2RVAL(tag_list));
957
+ }
958
+
959
+ static void
960
+ initialize_thread_pool(GThreadPool **pool, GFunc function)
961
+ {
962
+ GError *error = NULL;
963
+
964
+ *pool = g_thread_pool_new(function, NULL, -1, FALSE, &error);
965
+ if (error)
966
+ RAISE_GERROR(error);
967
+ }
968
+
969
+ void
970
+ Init_gst_element(void)
971
+ {
972
+ table.type = GST_TYPE_ELEMENT;
973
+ table.instance2robj = instance2robj;
974
+ RG_DEF_CONVERSION(&table);
975
+
976
+ id_gtype = rb_intern("gtype");
977
+
978
+ initialize_thread_pool(&set_state_thread_pool, set_state_in_thread);
979
+ initialize_thread_pool(&get_state_thread_pool, get_state_in_thread);
980
+ initialize_thread_pool(&query_thread_pool, query_in_thread);
981
+ initialize_thread_pool(&send_event_thread_pool, send_event_in_thread);
982
+
983
+ rb_cGstElement = G_DEF_CLASS(GST_TYPE_ELEMENT, "Element", mGst);
984
+
985
+ rb_define_singleton_method(rb_cGstElement, "get_pad_template",
986
+ rb_gst_element_get_pad_template, 1);
987
+ rb_define_singleton_method(rb_cGstElement, "pad_templates",
988
+ rb_gst_element_get_pad_templates, 0);
989
+ rb_define_singleton_method(rb_cGstElement, "each_pad_template",
990
+ rb_gst_element_each_pad_template, 0);
991
+
992
+ rb_define_method(rb_cGstElement, "set_state", rb_gst_element_set_state, 1);
993
+ rb_define_method(rb_cGstElement, "get_state", rb_gst_element_get_state, -1);
994
+ rb_define_method(rb_cGstElement, "stop", rb_gst_element_stop, 0);
995
+ rb_define_method(rb_cGstElement, "ready", rb_gst_element_ready, 0);
996
+ rb_define_method(rb_cGstElement, "pause", rb_gst_element_pause, 0);
997
+ rb_define_method(rb_cGstElement, "play", rb_gst_element_play, 0);
998
+ rb_define_method(rb_cGstElement, "link", rb_gst_element_link, 1);
999
+ rb_define_alias(rb_cGstElement, ">>", "link");
1000
+ rb_define_method(rb_cGstElement, "unlink", rb_gst_element_unlink, 1);
1001
+ rb_define_method(rb_cGstElement, "link_filtered", rb_gst_element_link_filtered, 2);
1002
+ rb_define_method(rb_cGstElement, "provides_clock?", rb_gst_element_provides_clock, 0);
1003
+ rb_define_alias(rb_cGstElement, "provide_clock?", "provides_clock?");
1004
+ rb_define_method(rb_cGstElement, "requires_clock?", rb_gst_element_requires_clock, 0);
1005
+ rb_define_alias(rb_cGstElement, "require_clock?", "requires_clock?");
1006
+ rb_define_method(rb_cGstElement, "clock", rb_gst_element_get_clock, 0);
1007
+ rb_define_method(rb_cGstElement, "set_clock", rb_gst_element_set_clock, 1);
1008
+ rb_define_method(rb_cGstElement, "base_time", rb_gst_element_get_base_time, 0);
1009
+ rb_define_method(rb_cGstElement, "set_base_time", rb_gst_element_set_base_time, 1);
1010
+ rb_define_method(rb_cGstElement, "each_pad", rb_gst_element_each_pad, 0);
1011
+ rb_define_method(rb_cGstElement, "pads", rb_gst_element_get_pads, 0);
1012
+ rb_define_method(rb_cGstElement, "get_pad", rb_gst_element_get_pad, 1);
1013
+ rb_define_alias(rb_cGstElement, "[]", "get_pad");
1014
+ rb_define_method(rb_cGstElement, "get_static_pad", rb_gst_element_get_static_pad, 1);
1015
+ rb_define_method(rb_cGstElement, "get_request_pad", rb_gst_element_get_request_pad, 1);
1016
+ rb_define_method(rb_cGstElement, "release_request_pad",
1017
+ rb_gst_element_release_request_pad, 1);
1018
+ rb_define_method(rb_cGstElement, "link_pads", rb_gst_element_link_pads, 3);
1019
+ rb_define_method(rb_cGstElement, "unlink_pads", rb_gst_element_unlink_pads, 3);
1020
+ rb_define_method(rb_cGstElement, "add_pad", rb_gst_element_add_pad, 1);
1021
+ rb_define_method(rb_cGstElement, "remove_pad", rb_gst_element_remove_pad, 1);
1022
+ rb_define_method(rb_cGstElement, "indexable?", rb_gst_element_is_indexable, 0);
1023
+ rb_define_method(rb_cGstElement, "query", rb_gst_element_query, 1);
1024
+ rb_define_method(rb_cGstElement, "send_event", rb_gst_element_send_event, 1);
1025
+ rb_define_method(rb_cGstElement, "seek", rb_gst_element_seek, 7);
1026
+ rb_define_method(rb_cGstElement, "index", rb_gst_element_get_index, 0);
1027
+ rb_define_method(rb_cGstElement, "set_index", rb_gst_element_set_index, 1);
1028
+ rb_define_method(rb_cGstElement, "locked_state?", rb_gst_element_is_locked_state, 0);
1029
+ rb_define_method(rb_cGstElement, "set_locked_state", rb_gst_element_set_locked_state,
1030
+ 1);
1031
+ rb_define_method(rb_cGstElement, "sync_state_with_parent",
1032
+ rb_gst_element_sync_state_with_parent, 0);
1033
+ rb_define_method(rb_cGstElement, "no_more_pads", rb_gst_element_no_more_pads, 0);
1034
+
1035
+ G_DEF_SETTERS(rb_cGstElement);
1036
+
1037
+ G_DEF_CLASS(GST_TYPE_STATE, "State", mGst);
1038
+ G_DEF_CONSTANTS(mGst, GST_TYPE_STATE, "GST_");
1039
+ G_DEF_CLASS(GST_TYPE_STATE_CHANGE_RETURN, "StateChangeReturn", mGst);
1040
+ G_DEF_CONSTANTS(mGst, GST_TYPE_STATE_CHANGE_RETURN, "GST_");
1041
+ G_DEF_CLASS(GST_TYPE_STATE_CHANGE, "StateChange", mGst);
1042
+ G_DEF_CONSTANTS(mGst, GST_TYPE_STATE_CHANGE, "GST_");
1043
+ G_DEF_CLASS(GST_TYPE_ELEMENT_FLAGS, "Flags", rb_cGstElement);
1044
+ G_DEF_CONSTANTS(rb_cGstElement, GST_TYPE_ELEMENT_FLAGS, "GST_ELEMENT_");
1045
+
1046
+ /*
1047
+ * TODO:
1048
+ * gst_element_clock_wait()
1049
+ */
1050
+
1051
+ G_DEF_SIGNAL_FUNC(rb_cGstElement, "found-tag",
1052
+ (GValToRValSignalFunc)rb_gst_element_found_tag_sig);
1053
+ }