mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			407 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			407 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
/*gstclasspathsrc.c - Class file for the GstClasspathPlugin
 | 
						|
 Copyright (C) 2007 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#  include <config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * We don't really use version numbering here, we give it the same version
 | 
						|
 * number of classpath, so that gstreamer is happy.
 | 
						|
 * TODO: Maybe this should be moved in config.h instead?
 | 
						|
 */
 | 
						|
#define CLASSPATH_GST_PLUGIN_VERSION PACKAGE_VERSION
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#include <gst/gst.h>
 | 
						|
#include <gst/base/gstbasesrc.h>
 | 
						|
#include <gst/base/gstpushsrc.h>
 | 
						|
 | 
						|
#include <glib.h>
 | 
						|
#include <glib/gprintf.h>
 | 
						|
 | 
						|
#include <gdk/gdk.h>
 | 
						|
 | 
						|
#include "gst_classpath_src.h"
 | 
						|
#include "gst_input_stream.h"
 | 
						|
 | 
						|
GST_DEBUG_CATEGORY_STATIC (gst_classpath_src_debug);
 | 
						|
#define GST_CAT_DEFAULT gst_classpath_src_debug
 | 
						|
 | 
						|
enum
 | 
						|
{
 | 
						|
  ARG_0,
 | 
						|
  ARG_INPUTSTREAM
 | 
						|
};
 | 
						|
 | 
						|
struct _GstClasspathSrcPrivate
 | 
						|
{
 | 
						|
  GstInputStream *istream;
 | 
						|
  GstCaps *caps;
 | 
						|
};
 | 
						|
 | 
						|
static const GstElementDetails gst_classpath_src_details =
 | 
						|
GST_ELEMENT_DETAILS ("ClasspathSrc",
 | 
						|
  "Source/Network",
 | 
						|
  "Read from a java input stream",
 | 
						|
  "Mario Torre <neugens@limasoftware.net>");
 | 
						|
 | 
						|
static GstStaticPadTemplate _template =
 | 
						|
GST_STATIC_PAD_TEMPLATE ("src",
 | 
						|
  GST_PAD_SRC,
 | 
						|
  GST_PAD_ALWAYS,
 | 
						|
  GST_STATIC_CAPS_ANY);
 | 
						|
 | 
						|
/* ***** plugin init ***** */
 | 
						|
 | 
						|
static void
 | 
						|
_do_init (GType filesrc_type __attribute__ ((unused)))
 | 
						|
{
 | 
						|
  GST_DEBUG_CATEGORY_INIT (gst_classpath_src_debug, "classpathsrc",
 | 
						|
         0, "classpathsrc");
 | 
						|
}
 | 
						|
 | 
						|
GST_BOILERPLATE_FULL (GstClasspathSrc, gst_classpath_src, GstPushSrc,
 | 
						|
                  GST_TYPE_PUSH_SRC, _do_init);
 | 
						|
 | 
						|
static gboolean
 | 
						|
plugin_init (GstPlugin *plugin)
 | 
						|
{
 | 
						|
  return gst_element_register (plugin, "classpathsrc",
 | 
						|
                               GST_RANK_NONE, GST_TYPE_CLASSPATH_SRC);
 | 
						|
}
 | 
						|
 | 
						|
GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
 | 
						|
  GST_VERSION_MINOR,
 | 
						|
  "classpathsrc",
 | 
						|
  "Java InputStream Reader",
 | 
						|
  plugin_init, CLASSPATH_GST_PLUGIN_VERSION,
 | 
						|
  GST_LICENSE_UNKNOWN, /* GPL + Exception */
 | 
						|
  "Classpath", "http://www.classpath.org/")
 | 
						|
        
 | 
						|
/* ***** public class methods ***** */
 | 
						|
 | 
						|
static void gst_classpath_src_set_property (GObject *object,
 | 
						|
                                            guint prop_id,
 | 
						|
                                            const GValue *value,
 | 
						|
                                            GParamSpec *pspec);
 | 
						|
 | 
						|
static void gst_classpath_src_get_property (GObject *object,
 | 
						|
                                            guint prop_id,
 | 
						|
                                            GValue *value,
 | 
						|
                                            GParamSpec *pspec);
 | 
						|
 | 
						|
static void gst_classpath_src_finalize (GObject *object);
 | 
						|
 | 
						|
static GstCaps *gst_classpath_src_getcaps (GstBaseSrc *basesrc);
 | 
						|
 | 
						|
static gboolean gst_classpath_src_start (GstBaseSrc *basesrc);
 | 
						|
 | 
						|
static gboolean gst_classpath_src_stop (GstBaseSrc *basesrc);
 | 
						|
 | 
						|
static GstFlowReturn gst_classpath_src_create (GstPushSrc *src,
 | 
						|
                                               GstBuffer **buffer);
 | 
						|
 | 
						|
static GstFlowReturn
 | 
						|
gst_classpath_src_create_stream (GstClasspathSrc *src, GstBuffer **buffer);
 | 
						|
 | 
						|
static GstFlowReturn
 | 
						|
check_read (GstClasspathSrc *src, int read, int buffer_size,
 | 
						|
            GstBuffer **buffer);
 | 
						|
 | 
						|
/* ***** public class methods: end ***** */
 | 
						|
 | 
						|
static void
 | 
						|
gst_classpath_src_base_init (gpointer gclass)
 | 
						|
{
 | 
						|
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (gclass);
 | 
						|
 | 
						|
  gst_element_class_add_pad_template (gstelement_class,
 | 
						|
                                      gst_static_pad_template_get (&_template));
 | 
						|
 | 
						|
  gst_element_class_set_details (gstelement_class, &gst_classpath_src_details);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gst_classpath_src_class_init (GstClasspathSrcClass *klass)
 | 
						|
{
 | 
						|
  GObjectClass *gobject_class;
 | 
						|
  GstBaseSrcClass *gstbasesrc_class;
 | 
						|
  GstPushSrcClass *gstpushsrc_class;
 | 
						|
  
 | 
						|
  GParamSpec *pspec;
 | 
						|
 | 
						|
  gobject_class = G_OBJECT_CLASS (klass);
 | 
						|
  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
 | 
						|
  gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
 | 
						|
  
 | 
						|
  g_type_class_add_private (klass, sizeof (GstClasspathSrcPrivate));
 | 
						|
  
 | 
						|
  /* getter and setters */
 | 
						|
 | 
						|
  gobject_class->set_property = gst_classpath_src_set_property;
 | 
						|
  gobject_class->get_property = gst_classpath_src_get_property;
 | 
						|
 | 
						|
  /* register properties */    
 | 
						|
  pspec = g_param_spec_pointer (GST_CLASSPATH_SRC_ISTREAM,
 | 
						|
                                "GstInputStream instance",
 | 
						|
                                "GstInputStream instance",
 | 
						|
                                G_PARAM_READWRITE);
 | 
						|
  g_object_class_install_property (gobject_class, ARG_INPUTSTREAM, pspec);
 | 
						|
 | 
						|
  /* register callbacks */
 | 
						|
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_classpath_src_finalize);
 | 
						|
 | 
						|
  gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_classpath_src_getcaps);
 | 
						|
  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_classpath_src_start);
 | 
						|
  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_classpath_src_stop);
 | 
						|
 | 
						|
  gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_classpath_src_create);
 | 
						|
}
 | 
						|
 | 
						|
/* ***** */
 | 
						|
 | 
						|
static void
 | 
						|
gst_classpath_src_init (GstClasspathSrc *src,
 | 
						|
                        GstClasspathSrcClass * g_class __attribute__ ((unused)))
 | 
						|
{
 | 
						|
  src->priv = G_TYPE_INSTANCE_GET_PRIVATE (src, GST_TYPE_CLASSPATH_SRC,
 | 
						|
                                           GstClasspathSrcPrivate);
 | 
						|
  
 | 
						|
  src->priv->istream = NULL;
 | 
						|
  src->priv->caps = NULL;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gst_classpath_src_finalize (GObject *object)
 | 
						|
{
 | 
						|
  G_OBJECT_CLASS (parent_class)->finalize (object);
 | 
						|
}
 | 
						|
 | 
						|
/* ************************************************************************** */
 | 
						|
 | 
						|
static void
 | 
						|
gst_classpath_src_set_property (GObject *object,
 | 
						|
                                guint prop_id,
 | 
						|
                                const GValue *value,
 | 
						|
                                GParamSpec *pspec)
 | 
						|
{
 | 
						|
  GstClasspathSrc *src;
 | 
						|
  
 | 
						|
  g_return_if_fail (GST_IS_CLASSPATH_SRC (object));
 | 
						|
  
 | 
						|
  src = GST_CLASSPATH_SRC (object);
 | 
						|
  
 | 
						|
  GST_OBJECT_LOCK (src);
 | 
						|
  switch (prop_id)
 | 
						|
    {
 | 
						|
      case ARG_INPUTSTREAM:
 | 
						|
        {
 | 
						|
          GST_STATE_LOCK (src);
 | 
						|
            {
 | 
						|
              GstState state;
 | 
						|
              state = GST_STATE (src);
 | 
						|
              
 | 
						|
              if (state != GST_STATE_READY && state != GST_STATE_NULL)
 | 
						|
                {
 | 
						|
                  GST_DEBUG_OBJECT (src, "setting reader in wrong state");
 | 
						|
                  GST_STATE_UNLOCK (src);
 | 
						|
                  break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
          GST_STATE_UNLOCK (src);
 | 
						|
          
 | 
						|
          /* FIXME: check if this is a valid instance of GstInputStream */
 | 
						|
          src->priv->istream = g_value_get_pointer (value);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
        
 | 
						|
      default:
 | 
						|
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);   
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  GST_OBJECT_UNLOCK (src);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gst_classpath_src_get_property (GObject *object,
 | 
						|
                                guint prop_id __attribute__ ((unused)),
 | 
						|
                                GValue *value __attribute__ ((unused)),
 | 
						|
                                GParamSpec *pspec __attribute__ ((unused)))
 | 
						|
{
 | 
						|
  /* TODO */
 | 
						|
}
 | 
						|
 | 
						|
/* ************************************************************************** */
 | 
						|
 | 
						|
static GstCaps *gst_classpath_src_getcaps (GstBaseSrc *basesrc)
 | 
						|
{
 | 
						|
  GstClasspathSrc *src;
 | 
						|
  GstCaps *caps = NULL;
 | 
						|
 | 
						|
  src = GST_CLASSPATH_SRC (basesrc);
 | 
						|
 | 
						|
  if (src->priv->caps)
 | 
						|
    caps = gst_caps_copy (src->priv->caps);
 | 
						|
  else
 | 
						|
    caps = gst_caps_new_any ();
 | 
						|
  
 | 
						|
  GST_DEBUG_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
 | 
						|
  g_assert (GST_IS_CAPS (caps));
 | 
						|
  
 | 
						|
  return caps;
 | 
						|
}
 | 
						|
 | 
						|
static GstFlowReturn
 | 
						|
gst_classpath_src_create_stream (GstClasspathSrc *src, GstBuffer **buffer)
 | 
						|
{
 | 
						|
  int buffer_size = 2048;
 | 
						|
  int read = -1; 
 | 
						|
  
 | 
						|
  buffer_size = gst_input_stream_available (src->priv->istream);
 | 
						|
  if (buffer_size < 0)
 | 
						|
    return GST_FLOW_ERROR;
 | 
						|
  else if (buffer_size == 0)
 | 
						|
    return GST_FLOW_WRONG_STATE;
 | 
						|
  
 | 
						|
  *buffer = gst_buffer_new_and_alloc (buffer_size);
 | 
						|
  if (*buffer == NULL)
 | 
						|
    {
 | 
						|
      return GST_FLOW_ERROR;
 | 
						|
    }
 | 
						|
  
 | 
						|
  read = gst_input_stream_read (src->priv->istream,
 | 
						|
                                (int *) GST_BUFFER_DATA (*buffer),
 | 
						|
                                0,
 | 
						|
                                buffer_size);
 | 
						|
  
 | 
						|
  return check_read (src, read, buffer_size, buffer);
 | 
						|
}
 | 
						|
 | 
						|
GstFlowReturn
 | 
						|
check_read (GstClasspathSrc *src, int read, int buffer_size, GstBuffer **buffer)
 | 
						|
{
 | 
						|
  if (G_UNLIKELY (read < 0))
 | 
						|
    {
 | 
						|
      g_warning("GST_FLOW_UNEXPECTED (read < 0)");
 | 
						|
      
 | 
						|
      gst_buffer_unref (*buffer);
 | 
						|
      *buffer = NULL;
 | 
						|
      
 | 
						|
      return GST_FLOW_ERROR;
 | 
						|
    }
 | 
						|
  else if (G_UNLIKELY (read == 0))
 | 
						|
    {
 | 
						|
      g_warning("GST_FLOW_WRONG_STATE (read == 0)");
 | 
						|
      
 | 
						|
      gst_buffer_unref (*buffer);
 | 
						|
      *buffer = NULL;
 | 
						|
      
 | 
						|
      return GST_FLOW_WRONG_STATE;
 | 
						|
    }
 | 
						|
  else if (G_UNLIKELY (read < buffer_size))
 | 
						|
    {
 | 
						|
      g_warning("shorter read");
 | 
						|
      gst_buffer_unref (*buffer);
 | 
						|
      *buffer = NULL;
 | 
						|
      
 | 
						|
      return GST_FLOW_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
  GST_BUFFER_SIZE (*buffer) = read;
 | 
						|
  gst_buffer_set_caps (*buffer, src->priv->caps);
 | 
						|
  
 | 
						|
  return GST_FLOW_OK;
 | 
						|
}
 | 
						|
 | 
						|
static GstFlowReturn
 | 
						|
gst_classpath_src_create (GstPushSrc *basesrc, GstBuffer **buffer)
 | 
						|
{
 | 
						|
  GstClasspathSrc *src = NULL;
 | 
						|
  GstFlowReturn ret = GST_FLOW_OK;
 | 
						|
  
 | 
						|
  src = GST_CLASSPATH_SRC (basesrc);
 | 
						|
   
 | 
						|
  /* create the buffer */
 | 
						|
  ret = gst_classpath_src_create_stream (src, buffer);
 | 
						|
  
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
gst_classpath_src_start (GstBaseSrc *basesrc)
 | 
						|
{
 | 
						|
  GstClasspathSrc *src;
 | 
						|
 | 
						|
  src = GST_CLASSPATH_SRC (basesrc);
 | 
						|
   
 | 
						|
  if (src->priv->istream == NULL)
 | 
						|
    {
 | 
						|
      g_warning("GstInputStream is still null. You need to " \
 | 
						|
                "pass a valid InputStream object");
 | 
						|
          
 | 
						|
      GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
 | 
						|
                         ("GstInputStream is still null. You need to " \
 | 
						|
                          "pass a valid InputStream"));
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
          
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
gst_classpath_src_stop (GstBaseSrc *basesrc)
 | 
						|
{
 | 
						|
  GstClasspathSrc *src;
 | 
						|
 | 
						|
  src = GST_CLASSPATH_SRC (basesrc);
 | 
						|
  
 | 
						|
  /* clean the stream */
 | 
						|
  if (src->priv->istream != NULL)
 | 
						|
    gst_input_stream_clean (src->priv->istream);
 | 
						|
 | 
						|
  if (src->priv->caps) {
 | 
						|
    gst_caps_unref (src->priv->caps);
 | 
						|
    src->priv->caps = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 |