gstreamer 0.90.6

Sign up to get free protection for your applications and to get access to all the features.
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
+ }