OSDN Git Service

2008-06-28 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / native / jni / gstreamer-peer / gst_classpath_src.c
1 /*gstclasspathsrc.c - Class file for the GstClasspathPlugin
2  Copyright (C) 2007 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #ifdef HAVE_CONFIG_H
39 #  include <config.h>
40 #endif
41
42 /*
43  * We don't really use version numbering here, we give it the same version
44  * number of classpath, so that gstreamer is happy.
45  * TODO: Maybe this should be moved in config.h instead?
46  */
47 #define CLASSPATH_GST_PLUGIN_VERSION PACKAGE_VERSION
48
49 #include <stdio.h>
50 #include <string.h>
51 #include <stdlib.h>
52
53 #include <gst/gst.h>
54 #include <gst/base/gstbasesrc.h>
55 #include <gst/base/gstpushsrc.h>
56
57 #include <glib.h>
58 #include <glib/gprintf.h>
59
60 #include <gdk/gdk.h>
61
62 #include "gst_classpath_src.h"
63 #include "gst_input_stream.h"
64
65 GST_DEBUG_CATEGORY_STATIC (gst_classpath_src_debug);
66 #define GST_CAT_DEFAULT gst_classpath_src_debug
67
68 enum
69 {
70   ARG_0,
71   ARG_INPUTSTREAM
72 };
73
74 struct _GstClasspathSrcPrivate
75 {
76   GstInputStream *istream;
77   GstCaps *caps;
78 };
79
80 static const GstElementDetails gst_classpath_src_details =
81 GST_ELEMENT_DETAILS ("ClasspathSrc",
82   "Source/Network",
83   "Read from a java input stream",
84   "Mario Torre <neugens@limasoftware.net>");
85
86 static GstStaticPadTemplate _template =
87 GST_STATIC_PAD_TEMPLATE ("src",
88   GST_PAD_SRC,
89   GST_PAD_ALWAYS,
90   GST_STATIC_CAPS_ANY);
91
92 /* ***** plugin init ***** */
93
94 static void
95 _do_init (GType filesrc_type __attribute__ ((unused)))
96 {
97   GST_DEBUG_CATEGORY_INIT (gst_classpath_src_debug, "classpathsrc",
98          0, "classpathsrc");
99 }
100
101 GST_BOILERPLATE_FULL (GstClasspathSrc, gst_classpath_src, GstPushSrc,
102                   GST_TYPE_PUSH_SRC, _do_init);
103
104 static gboolean
105 plugin_init (GstPlugin *plugin)
106 {
107   return gst_element_register (plugin, "classpathsrc",
108                                GST_RANK_NONE, GST_TYPE_CLASSPATH_SRC);
109 }
110
111 GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
112   GST_VERSION_MINOR,
113   "classpathsrc",
114   "Java InputStream Reader",
115   plugin_init, CLASSPATH_GST_PLUGIN_VERSION,
116   GST_LICENSE_UNKNOWN, /* GPL + Exception */
117   "Classpath", "http://www.classpath.org/")
118         
119 /* ***** public class methods ***** */
120
121 static void gst_classpath_src_set_property (GObject *object,
122                                             guint prop_id,
123                                             const GValue *value,
124                                             GParamSpec *pspec);
125
126 static void gst_classpath_src_get_property (GObject *object,
127                                             guint prop_id,
128                                             GValue *value,
129                                             GParamSpec *pspec);
130
131 static void gst_classpath_src_finalize (GObject *object);
132
133 static GstCaps *gst_classpath_src_getcaps (GstBaseSrc *basesrc);
134
135 static gboolean gst_classpath_src_start (GstBaseSrc *basesrc);
136
137 static gboolean gst_classpath_src_stop (GstBaseSrc *basesrc);
138
139 static GstFlowReturn gst_classpath_src_create (GstPushSrc *src,
140                                                GstBuffer **buffer);
141
142 static GstFlowReturn
143 gst_classpath_src_create_stream (GstClasspathSrc *src, GstBuffer **buffer);
144
145 static GstFlowReturn
146 check_read (GstClasspathSrc *src, int read, int buffer_size,
147             GstBuffer **buffer);
148
149 /* ***** public class methods: end ***** */
150
151 static void
152 gst_classpath_src_base_init (gpointer gclass)
153 {
154   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (gclass);
155
156   gst_element_class_add_pad_template (gstelement_class,
157                                       gst_static_pad_template_get (&_template));
158
159   gst_element_class_set_details (gstelement_class, &gst_classpath_src_details);
160 }
161
162 static void
163 gst_classpath_src_class_init (GstClasspathSrcClass *klass)
164 {
165   GObjectClass *gobject_class;
166   GstElementClass *gstelement_class;
167   GstBaseSrcClass *gstbasesrc_class;
168   GstPushSrcClass *gstpushsrc_class;
169   
170   GParamSpec *pspec;
171
172   gobject_class = G_OBJECT_CLASS (klass);
173   gstelement_class = GST_ELEMENT_CLASS (klass);
174   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
175   gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
176   
177   g_type_class_add_private (klass, sizeof (GstClasspathSrcPrivate));
178   
179   /* getter and setters */
180
181   gobject_class->set_property = gst_classpath_src_set_property;
182   gobject_class->get_property = gst_classpath_src_get_property;
183
184   /* register properties */    
185   pspec = g_param_spec_pointer (GST_CLASSPATH_SRC_ISTREAM,
186                                 "GstInputStream instance",
187                                 "GstInputStream instance",
188                                 G_PARAM_READWRITE);
189   g_object_class_install_property (gobject_class, ARG_INPUTSTREAM, pspec);
190
191   /* register callbacks */
192   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_classpath_src_finalize);
193
194   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_classpath_src_getcaps);
195   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_classpath_src_start);
196   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_classpath_src_stop);
197
198   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_classpath_src_create);
199 }
200
201 /* ***** */
202
203 static void
204 gst_classpath_src_init (GstClasspathSrc *src,
205                         GstClasspathSrcClass * g_class __attribute__ ((unused)))
206 {
207   src->priv = G_TYPE_INSTANCE_GET_PRIVATE (src, GST_TYPE_CLASSPATH_SRC,
208                                            GstClasspathSrcPrivate);
209   
210   src->priv->istream = NULL;
211   src->priv->caps = NULL;
212 }
213
214 static void
215 gst_classpath_src_finalize (GObject *object)
216 {
217   G_OBJECT_CLASS (parent_class)->finalize (object);
218 }
219
220 /* ************************************************************************** */
221
222 static void
223 gst_classpath_src_set_property (GObject *object,
224                                 guint prop_id,
225                                 const GValue *value,
226                                 GParamSpec *pspec)
227 {
228   GstClasspathSrc *src;
229   
230   g_return_if_fail (GST_IS_CLASSPATH_SRC (object));
231   
232   src = GST_CLASSPATH_SRC (object);
233   
234   GST_OBJECT_LOCK (src);
235   switch (prop_id)
236     {
237       case ARG_INPUTSTREAM:
238         {
239           GST_STATE_LOCK (src);
240             {
241               GstState state;
242               state = GST_STATE (src);
243               
244               if (state != GST_STATE_READY && state != GST_STATE_NULL)
245                 {
246                   GST_DEBUG_OBJECT (src, "setting reader in wrong state");
247                   GST_STATE_UNLOCK (src);
248                   break;
249                 }
250             }
251           GST_STATE_UNLOCK (src);
252           
253           /* FIXME: check if this is a valid instance of GstInputStream */
254           src->priv->istream = g_value_get_pointer (value);
255         }
256         break;
257         
258       default:
259         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);   
260         break;
261     }
262   GST_OBJECT_UNLOCK (src);
263 }
264
265 static void
266 gst_classpath_src_get_property (GObject *object,
267                                 guint prop_id __attribute__ ((unused)),
268                                 GValue *value __attribute__ ((unused)),
269                                 GParamSpec *pspec __attribute__ ((unused)))
270 {
271   /* TODO */
272 }
273
274 /* ************************************************************************** */
275
276 static GstCaps *gst_classpath_src_getcaps (GstBaseSrc *basesrc)
277 {
278   GstClasspathSrc *src;
279   GstCaps *caps = NULL;
280
281   src = GST_CLASSPATH_SRC (basesrc);
282
283   if (src->priv->caps)
284     caps = gst_caps_copy (src->priv->caps);
285   else
286     caps = gst_caps_new_any ();
287   
288   GST_DEBUG_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
289   g_assert (GST_IS_CAPS (caps));
290   
291   return caps;
292 }
293
294 static GstFlowReturn
295 gst_classpath_src_create_stream (GstClasspathSrc *src, GstBuffer **buffer)
296 {
297   int buffer_size = 2048;
298   int read = -1; 
299   
300   buffer_size = gst_input_stream_available (src->priv->istream);
301   if (buffer_size < 0)
302     return GST_FLOW_ERROR;
303   else if (buffer_size == 0)
304     return GST_FLOW_WRONG_STATE;
305   
306   *buffer = gst_buffer_new_and_alloc (buffer_size);
307   if (*buffer == NULL)
308     {
309       return GST_FLOW_ERROR;
310     }
311   
312   read = gst_input_stream_read (src->priv->istream,
313                                 (int *) GST_BUFFER_DATA (*buffer),
314                                 0,
315                                 buffer_size);
316   
317   return check_read (src, read, buffer_size, buffer);
318 }
319
320 GstFlowReturn
321 check_read (GstClasspathSrc *src, int read, int buffer_size, GstBuffer **buffer)
322 {
323   if (G_UNLIKELY (read < 0))
324     {
325       g_warning("GST_FLOW_UNEXPECTED (read < 0)");
326       
327       gst_buffer_unref (*buffer);
328       *buffer = NULL;
329       
330       return GST_FLOW_ERROR;
331     }
332   else if (G_UNLIKELY (read == 0))
333     {
334       g_warning("GST_FLOW_WRONG_STATE (read == 0)");
335       
336       gst_buffer_unref (*buffer);
337       *buffer = NULL;
338       
339       return GST_FLOW_WRONG_STATE;
340     }
341   else if (G_UNLIKELY (read < buffer_size))
342     {
343       g_warning("shorter read");
344       gst_buffer_unref (*buffer);
345       *buffer = NULL;
346       
347       return GST_FLOW_ERROR;
348     }
349
350   GST_BUFFER_SIZE (*buffer) = read;
351   gst_buffer_set_caps (*buffer, src->priv->caps);
352   
353   return GST_FLOW_OK;
354 }
355
356 static GstFlowReturn
357 gst_classpath_src_create (GstPushSrc *basesrc, GstBuffer **buffer)
358 {
359   GstClasspathSrc *src = NULL;
360   GstFlowReturn ret = GST_FLOW_OK;
361   
362   src = GST_CLASSPATH_SRC (basesrc);
363    
364   /* create the buffer */
365   ret = gst_classpath_src_create_stream (src, buffer);
366   
367   return ret;
368 }
369
370 static gboolean
371 gst_classpath_src_start (GstBaseSrc *basesrc)
372 {
373   GstClasspathSrc *src;
374
375   src = GST_CLASSPATH_SRC (basesrc);
376    
377   if (src->priv->istream == NULL)
378     {
379       g_warning("GstInputStream is still null. You need to " \
380                 "pass a valid InputStream object");
381           
382       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
383                          ("GstInputStream is still null. You need to " \
384                           "pass a valid InputStream"));
385       return FALSE;
386     }
387           
388   return TRUE;
389 }
390
391 static gboolean
392 gst_classpath_src_stop (GstBaseSrc *basesrc)
393 {
394   GstClasspathSrc *src;
395
396   src = GST_CLASSPATH_SRC (basesrc);
397   
398   /* clean the stream */
399   if (src->priv->istream != NULL)
400     gst_input_stream_clean (src->priv->istream);
401
402   if (src->priv->caps) {
403     gst_caps_unref (src->priv->caps);
404     src->priv->caps = NULL;
405   }
406
407   return TRUE;
408 }