diff options
Diffstat (limited to 'libjava/classpath/native/jni/gstreamer-peer')
13 files changed, 1733 insertions, 854 deletions
diff --git a/libjava/classpath/native/jni/gstreamer-peer/Makefile.am b/libjava/classpath/native/jni/gstreamer-peer/Makefile.am index 45c91d1..d15f0a2 100644 --- a/libjava/classpath/native/jni/gstreamer-peer/Makefile.am +++ b/libjava/classpath/native/jni/gstreamer-peer/Makefile.am @@ -1,10 +1,15 @@ nativeexeclib_LTLIBRARIES = libgstreamerpeer.la -libgstreamerpeer_la_SOURCES = GStreamerIOPeer.c \ - gstinputstream.c \ - gstclasspathsrc.c \ - gstclasspathsrc.h \ - gstinputstream.h +libgstreamerpeer_la_SOURCES = gst_peer.c \ + gstreamer_io_peer.c \ + gst_native_data_line.c \ + gst_input_stream.c \ + gst_native_pipeline.c \ + gst_classpath_src.c \ + gst_peer.h \ + gst_classpath_src.h \ + gst_input_stream.h \ + gst_native_pipeline.h libgstreamerpeer_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo @@ -17,7 +22,8 @@ AM_CPPFLAGS = @CLASSPATH_INCLUDES@ # We cannot use -Wwrite-strings and the strict flags since # gstreamer contain broken prototypes (by design). -AM_CFLAGS = @WARNING_CFLAGS@ -Wno-write-strings -Wno-missing-field-initializers \ +AM_CFLAGS = @WARNING_CFLAGS@ -Wno-write-strings \ + -Wno-missing-field-initializers \ @ERROR_CFLAGS@ -Wno-unused-parameter @GSTREAMER_BASE_CFLAGS@ \ @GDK_CFLAGS@ @GSTREAMER_CFLAGS@ @GSTREAMER_PLUGINS_BASE_CFLAGS@ \ @EXTRA_CFLAGS@ diff --git a/libjava/classpath/native/jni/gstreamer-peer/Makefile.in b/libjava/classpath/native/jni/gstreamer-peer/Makefile.in index 4942b2d..be6f336 100644 --- a/libjava/classpath/native/jni/gstreamer-peer/Makefile.in +++ b/libjava/classpath/native/jni/gstreamer-peer/Makefile.in @@ -50,6 +50,8 @@ am__aclocal_m4_deps = $(top_srcdir)/../../config/depstand.m4 \ $(top_srcdir)/../../ltoptions.m4 \ $(top_srcdir)/../../ltsugar.m4 \ $(top_srcdir)/../../ltversion.m4 \ + $(top_srcdir)/m4/ac_prog_javac.m4 \ + $(top_srcdir)/m4/ac_prog_javac_works.m4 \ $(top_srcdir)/m4/acattribute.m4 $(top_srcdir)/m4/accross.m4 \ $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_create_stdint_h.m4 \ @@ -74,8 +76,9 @@ nativeexeclibLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(nativeexeclib_LTLIBRARIES) libgstreamerpeer_la_DEPENDENCIES = \ $(top_builddir)/native/jni/classpath/jcl.lo -am_libgstreamerpeer_la_OBJECTS = GStreamerIOPeer.lo gstinputstream.lo \ - gstclasspathsrc.lo +am_libgstreamerpeer_la_OBJECTS = gst_peer.lo gstreamer_io_peer.lo \ + gst_native_data_line.lo gst_input_stream.lo \ + gst_native_pipeline.lo gst_classpath_src.lo libgstreamerpeer_la_OBJECTS = $(am_libgstreamerpeer_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/../../depcomp @@ -157,7 +160,6 @@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ -ECJ = @ECJ@ ECJ_JAR = @ECJ_JAR@ EGREP = @EGREP@ ENABLE_LOCAL_SOCKETS_FALSE = @ENABLE_LOCAL_SOCKETS_FALSE@ @@ -169,19 +171,8 @@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ FASTJAR = @FASTJAR@ FGREP = @FGREP@ FIND = @FIND@ -FOUND_ECJ_FALSE = @FOUND_ECJ_FALSE@ -FOUND_ECJ_TRUE = @FOUND_ECJ_TRUE@ -FOUND_GCJ_FALSE = @FOUND_GCJ_FALSE@ -FOUND_GCJ_TRUE = @FOUND_GCJ_TRUE@ -FOUND_JAVAC_FALSE = @FOUND_JAVAC_FALSE@ -FOUND_JAVAC_TRUE = @FOUND_JAVAC_TRUE@ -FOUND_JIKES_FALSE = @FOUND_JIKES_FALSE@ -FOUND_JIKES_TRUE = @FOUND_JIKES_TRUE@ -FOUND_KJC_FALSE = @FOUND_KJC_FALSE@ -FOUND_KJC_TRUE = @FOUND_KJC_TRUE@ FREETYPE2_CFLAGS = @FREETYPE2_CFLAGS@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ -GCJ = @GCJ@ GCONF_CFLAGS = @GCONF_CFLAGS@ GCONF_LIBS = @GCONF_LIBS@ GDK_CFLAGS = @GDK_CFLAGS@ @@ -213,15 +204,12 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVAC = @JAVAC@ +JAVAC_MEM_OPT = @JAVAC_MEM_OPT@ JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION = @JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION@ JAVA_MAINTAINER_MODE_FALSE = @JAVA_MAINTAINER_MODE_FALSE@ JAVA_MAINTAINER_MODE_TRUE = @JAVA_MAINTAINER_MODE_TRUE@ JAY = @JAY@ JAY_SKELETON = @JAY_SKELETON@ -JIKES = @JIKES@ -JIKESENCODING = @JIKESENCODING@ -JIKESWARNINGS = @JIKESWARNINGS@ -KJC = @KJC@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDEBUG = @LIBDEBUG@ @@ -269,10 +257,8 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRICT_WARNING_CFLAGS = @STRICT_WARNING_CFLAGS@ STRIP = @STRIP@ -USER_CLASSLIB = @USER_CLASSLIB@ +TOOLSDIR = @TOOLSDIR@ USER_JAVAH = @USER_JAVAH@ -USER_SPECIFIED_CLASSLIB_FALSE = @USER_SPECIFIED_CLASSLIB_FALSE@ -USER_SPECIFIED_CLASSLIB_TRUE = @USER_SPECIFIED_CLASSLIB_TRUE@ USE_ESCHER_FALSE = @USE_ESCHER_FALSE@ USE_ESCHER_TRUE = @USE_ESCHER_TRUE@ USE_PREBUILT_GLIBJ_ZIP_FALSE = @USE_PREBUILT_GLIBJ_ZIP_FALSE@ @@ -345,11 +331,16 @@ target_vendor = @target_vendor@ toolexeclibdir = @toolexeclibdir@ vm_classes = @vm_classes@ nativeexeclib_LTLIBRARIES = libgstreamerpeer.la -libgstreamerpeer_la_SOURCES = GStreamerIOPeer.c \ - gstinputstream.c \ - gstclasspathsrc.c \ - gstclasspathsrc.h \ - gstinputstream.h +libgstreamerpeer_la_SOURCES = gst_peer.c \ + gstreamer_io_peer.c \ + gst_native_data_line.c \ + gst_input_stream.c \ + gst_native_pipeline.c \ + gst_classpath_src.c \ + gst_peer.h \ + gst_classpath_src.h \ + gst_input_stream.h \ + gst_native_pipeline.h libgstreamerpeer_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo libgstreamerpeer_la_LDFLAGS = $(AM_LDFLAGS) @GST_PLUGIN_LDFLAGS@ -avoid-version @@ -360,7 +351,8 @@ AM_CPPFLAGS = @CLASSPATH_INCLUDES@ # We cannot use -Wwrite-strings and the strict flags since # gstreamer contain broken prototypes (by design). -AM_CFLAGS = @WARNING_CFLAGS@ -Wno-write-strings -Wno-missing-field-initializers \ +AM_CFLAGS = @WARNING_CFLAGS@ -Wno-write-strings \ + -Wno-missing-field-initializers \ @ERROR_CFLAGS@ -Wno-unused-parameter @GSTREAMER_BASE_CFLAGS@ \ @GDK_CFLAGS@ @GSTREAMER_CFLAGS@ @GSTREAMER_PLUGINS_BASE_CFLAGS@ \ @EXTRA_CFLAGS@ @@ -434,9 +426,12 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GStreamerIOPeer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstclasspathsrc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstinputstream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_classpath_src.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_input_stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_native_data_line.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_native_pipeline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_peer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstreamer_io_peer.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ diff --git a/libjava/classpath/native/jni/gstreamer-peer/gstclasspathsrc.c b/libjava/classpath/native/jni/gstreamer-peer/gst_classpath_src.c index afce1f1..80c6795 100644 --- a/libjava/classpath/native/jni/gstreamer-peer/gstclasspathsrc.c +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_classpath_src.c @@ -59,8 +59,8 @@ exception statement from your version. */ #include <gdk/gdk.h> -#include "gstclasspathsrc.h" -#include "gstinputstream.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 @@ -71,6 +71,12 @@ enum ARG_INPUTSTREAM }; +struct _GstClasspathSrcPrivate +{ + GstInputStream *istream; + GstCaps *caps; +}; + static const GstElementDetails gst_classpath_src_details = GST_ELEMENT_DETAILS ("ClasspathSrc", "Source/Network", @@ -107,7 +113,7 @@ GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, "classpathsrc", "Java InputStream Reader", plugin_init, CLASSPATH_GST_PLUGIN_VERSION, - GST_LICENSE_UNKNOWN, + GST_LICENSE_UNKNOWN, /* GPL + Exception */ "Classpath", "http://www.classpath.org/") /* ***** public class methods ***** */ @@ -124,6 +130,8 @@ static void gst_classpath_src_get_property (GObject *object, 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); @@ -131,6 +139,13 @@ 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 @@ -159,6 +174,8 @@ gst_classpath_src_class_init (GstClasspathSrcClass *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; @@ -174,6 +191,7 @@ gst_classpath_src_class_init (GstClasspathSrcClass *klass) /* 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); @@ -186,8 +204,11 @@ static void gst_classpath_src_init (GstClasspathSrc *src, GstClasspathSrcClass * g_class __attribute__ ((unused))) { - src->istream = NULL; - src->read_position = 0; + src->priv = G_TYPE_INSTANCE_GET_PRIVATE (src, GST_TYPE_CLASSPATH_SRC, + GstClasspathSrcPrivate); + + src->priv->istream = NULL; + src->priv->caps = NULL; } static void @@ -222,21 +243,15 @@ gst_classpath_src_set_property (GObject *object, if (state != GST_STATE_READY && state != GST_STATE_NULL) { - GST_DEBUG_OBJECT (src, "setting location in wrong state"); + GST_DEBUG_OBJECT (src, "setting reader in wrong state"); GST_STATE_UNLOCK (src); break; } } GST_STATE_UNLOCK (src); - if (GST_IS_INPUT_STREAM (g_value_get_pointer (value))) - { - src->istream = g_value_get_pointer (value); - } - else - { - GST_INFO_OBJECT (src, "invalid instance of GstInputStream"); - } + /* FIXME: check if this is a valid instance of GstInputStream */ + src->priv->istream = g_value_get_pointer (value); } break; @@ -254,53 +269,102 @@ gst_classpath_src_get_property (GObject *object, GParamSpec *pspec __attribute__ ((unused))) { /* TODO */ - G_OBJECT_CLASS (parent_class)->finalize (object); } /* ************************************************************************** */ -static GstFlowReturn -gst_classpath_src_create (GstPushSrc *basesrc, - GstBuffer **buffer) +static GstCaps *gst_classpath_src_getcaps (GstBaseSrc *basesrc) { GstClasspathSrc *src; - int read = -1; - + 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 (); - /* create the buffer */ - *buffer = gst_buffer_new_and_alloc (2048); + 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; } - GST_BUFFER_SIZE (*buffer) = 0; - - GST_OBJECT_LOCK (src); - read = gst_input_stream_read (src->istream, (int *) GST_BUFFER_DATA (*buffer), 0, - 2048); - GST_OBJECT_UNLOCK (src); + 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); - return GST_FLOW_UNEXPECTED; + *buffer = NULL; + + return GST_FLOW_WRONG_STATE; } - - GST_OBJECT_LOCK (src); - + 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_OFFSET (*buffer) = src->read_position; - GST_BUFFER_OFFSET_END (*buffer) = src->read_position + read; - - src->read_position += read; + gst_buffer_set_caps (*buffer, src->priv->caps); - GST_OBJECT_UNLOCK (src); + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_classpath_src_create (GstPushSrc *basesrc, GstBuffer **buffer) +{ + GstClasspathSrc *src = NULL; + GstFlowReturn ret = GST_FLOW_OK; - gst_buffer_set_caps (*buffer, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); + src = GST_CLASSPATH_SRC (basesrc); + + /* create the buffer */ + ret = gst_classpath_src_create_stream (src, buffer); - return GST_FLOW_OK; + return ret; } static gboolean @@ -310,23 +374,35 @@ gst_classpath_src_start (GstBaseSrc *basesrc) src = GST_CLASSPATH_SRC (basesrc); - if (src->istream == NULL) + 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")); - + ("GstInputStream is still null. You need to " \ + "pass a valid InputStream")); return FALSE; } - GST_OBJECT_LOCK (src); - src->read_position = 0; - GST_OBJECT_UNLOCK (src); - + return TRUE; } static gboolean -gst_classpath_src_stop (GstBaseSrc *basesrc __attribute__ ((unused))) +gst_classpath_src_stop (GstBaseSrc *basesrc) { - /* nothing to do */ + 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; } diff --git a/libjava/classpath/native/jni/gstreamer-peer/gstclasspathsrc.h b/libjava/classpath/native/jni/gstreamer-peer/gst_classpath_src.h index f5fa6c8..9e2acb0 100644 --- a/libjava/classpath/native/jni/gstreamer-peer/gstclasspathsrc.h +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_classpath_src.h @@ -41,7 +41,7 @@ exception statement from your version. */ #include <gst/gst.h> #include <gst/base/gstpushsrc.h> -#include "gstinputstream.h" +#include "gst_input_stream.h" G_BEGIN_DECLS @@ -59,7 +59,8 @@ G_BEGIN_DECLS #define GST_IS_CLASSPATH_SRC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CLASSPATH_SRC)) - + +typedef struct _GstClasspathSrcPrivate GstClasspathSrcPrivate; typedef struct _GstClasspathSrc GstClasspathSrc; typedef struct _GstClasspathSrcClass GstClasspathSrcClass; @@ -67,9 +68,8 @@ struct _GstClasspathSrc { GstPushSrc element; - /* TODO: move in a private structure */ - GstInputStream *istream; - int read_position; + /* instance members */ + GstClasspathSrcPrivate *priv; }; struct _GstClasspathSrcClass diff --git a/libjava/classpath/native/jni/gstreamer-peer/gst_input_stream.c b/libjava/classpath/native/jni/gstreamer-peer/gst_input_stream.c new file mode 100644 index 0000000..c5e5129 --- /dev/null +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_input_stream.c @@ -0,0 +1,290 @@ +/*GstInputStream.c - Header 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. */ + +#include <jni.h> +#include <jcl.h> + +#include <string.h> +#include <stdlib.h> + +#include <gdk/gdk.h> + +#include <glib.h> + +#include "gst_peer.h" + +#include "gnu_javax_sound_sampled_gstreamer_io_GstInputStream.h" +#include "gst_input_stream.h" + +/* for caching */ +static jmethodID readID = NULL; +static jmethodID pointerConstructorID = NULL; +static jmethodID availableID = NULL; + +static jfieldID streamID = NULL; +static jfieldID pointerDataID = NULL; + +struct _GstInputStreamPrivate +{ + JavaVM *vm; + jclass readerClass; + jclass pointerClass; + + jobject reader; +}; + +/* ************************************************************************** */ + +static void init_pointer_IDs (JNIEnv* env); + +/* ************************************************************************** */ + +/* JNI Methods */ + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_io_GstInputStream_init_1id_1cache + (JNIEnv *env, jclass clazz) +{ + readID = (*env)->GetMethodID(env, clazz, "read", "([BII)I"); + availableID = (*env)->GetMethodID(env, clazz, "available", "()I"); + + streamID = (*env)->GetFieldID(env, clazz, "gstInputStream", + "Lgnu/classpath/Pointer;"); + init_pointer_IDs(env); +} + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_io_GstInputStream_init_1instance + (JNIEnv *env, jobject reader) +{ + GstInputStream *istream = NULL; + + jclass localReader = NULL; + jclass localPointer = NULL; + jobject _pointer = NULL; + + istream = (GstInputStream *) JCL_malloc (env, sizeof (GstInputStream)); + if (istream == NULL) + return; + + istream->priv = (GstInputStreamPrivate *) + JCL_malloc (env, sizeof (GstInputStreamPrivate)); + if (istream->priv == NULL) + { + JCL_free (env, istream); + return; + } + + /* get a local references first */ + localReader = (*env)->GetObjectClass(env, reader); + if (localReader == NULL) + { + JCL_free (env, istream->priv); + JCL_free (env, istream); + JCL_ThrowException (env, "java/lang/InternalError", + "Class Initialization failed."); + + return; + } + +#if SIZEOF_VOID_P == 8 + localPointer = JCL_FindClass (env, "gnu/classpath/Pointer64"); +#else +# if SIZEOF_VOID_P == 4 + localPointer = JCL_FindClass (env, "gnu/classpath/Pointer32"); +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ + + if (localReader == NULL || localPointer == NULL) + { + JCL_free (env, istream->priv); + JCL_free (env, istream); + JCL_ThrowException (env, "java/lang/InternalError", + "Class Initialization failed."); + return; + } + + /* fill out our structure */ + istream->priv->readerClass = (*env)->NewGlobalRef(env, localReader); + istream->priv->pointerClass = (*env)->NewGlobalRef(env, localPointer); + (*env)->GetJavaVM(env, &istream->priv->vm); + istream->priv->reader = (*env)->NewGlobalRef(env, reader); + + _pointer = (*env)->GetObjectField(env, reader, streamID); + + /* this should be always null */ + if (_pointer == NULL) + { +#if SIZEOF_VOID_P == 8 + _pointer = (*env)->NewObject(env, istream->priv->pointerClass, + pointerConstructorID, (jlong) istream); +#else + _pointer = (*env)->NewObject(env, istream->priv->pointerClass, + pointerConstructorID, (jint) istream); +#endif + } + else + { +#if SIZEOF_VOID_P == 8 + (*env)->SetLongField(env, reader, streamID, (jlong) istream); +#else + (*env)->SetIntField(env, reader, streamID, (jint) istream); +#endif + } + + /* store back our pointer into the calling class */ + (*env)->SetObjectField(env, reader, streamID, _pointer); +} + +/* exported library functions */ + +void +gst_input_stream_clean (GstInputStream *self) +{ + JNIEnv *env = NULL; + + env = gst_get_jenv (self->priv->vm); + + (*env)->DeleteGlobalRef (env, self->priv->reader); + (*env)->DeleteGlobalRef (env, self->priv->readerClass); + (*env)->DeleteGlobalRef (env, self->priv->pointerClass); + + JCL_free (env, self->priv); + JCL_free (env, self); +} + +int +gst_input_stream_available (GstInputStream *self) +{ + JNIEnv *env = NULL; + + if (self == NULL || self->priv == NULL || + self->priv->vm == NULL || self->priv->reader == NULL) + { + return -1; + } + + env = gst_get_jenv (self->priv->vm); + if (env == NULL) + { + g_warning("GstInputStream::gst_input_stream_available " \ + "failed to get java env"); + return -1; + } + + return (*env)->CallIntMethod (env, self->priv->reader, availableID); +} + +int +gst_input_stream_read (GstInputStream *self, int *data, int offset, + int length) +{ + JNIEnv *env = NULL; + + int ret = -1; + jbyteArray buffer; + jbyte *bytes = NULL; + + if (self == NULL || self->priv == NULL || + self->priv->vm == NULL || self->priv->reader == NULL) + { + return -1; + } + + env = gst_get_jenv (self->priv->vm); + if (env == NULL) + { + g_warning("GstInputStream::gst_input_stream_read failed to get java env"); + return -1; + } + + buffer = (*env)->NewByteArray (env, length); + if (buffer == NULL) + { + g_warning ("GstInputStream::gst_input_stream_read called, failed"); + return -1; + } + + ret = (*env)->CallIntMethod (env, self->priv->reader, readID, buffer, 0, + length); + if (ret < 0) + { + (*env)->DeleteLocalRef(env, buffer); + return ret; + } + + bytes = (*env)->GetByteArrayElements (env, buffer, NULL); + + /* copy bytes and release */ + memcpy (data + offset, bytes, ret); + + (*env)->ReleaseByteArrayElements (env, buffer, bytes, 0); + (*env)->DeleteLocalRef (env, buffer); + + return ret; +} + +/* private functions */ + +static void init_pointer_IDs (JNIEnv* env) +{ + jclass pointerClass = NULL; + +#if SIZEOF_VOID_P == 8 + pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer64"); + if (pointerClass != NULL) + { + pointerDataID = (*env)->GetFieldID (env, pointerClass, "data", "J"); + pointerConstructorID = (*env)->GetMethodID (env, pointerClass, "<init>", + "(J)V"); + } +#else +# if SIZEOF_VOID_P == 4 + pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer32"); + if (pointerClass != NULL) + { + pointerDataID = (*env)->GetFieldID(env, pointerClass, "data", "I"); + pointerConstructorID = (*env)->GetMethodID(env, pointerClass, + "<init>", "(I)V"); + } +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ +} diff --git a/libjava/classpath/native/jni/gstreamer-peer/gstinputstream.h b/libjava/classpath/native/jni/gstreamer-peer/gst_input_stream.h index 1930412..8e9d3cf 100644 --- a/libjava/classpath/native/jni/gstreamer-peer/gstinputstream.h +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_input_stream.h @@ -38,62 +38,34 @@ exception statement from your version. */ #ifndef __GST_INPUT_STREAM_H__ #define __GST_INPUT_STREAM_H__ -#include <glib-object.h> - -/* TODO: is a gobject overkill for that? */ - -G_BEGIN_DECLS - -/* #defines don't like whitespacey bits */ -#define GST_TYPE_INPUT_STREAM (gst_input_stream_get_type()) - -#define GST_INPUT_STREAM(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INPUT_STREAM,GstInputStream)) - -#define GST_INPUT_STREAM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INPUT_STREAM,GstInputStreamClass)) - -#define GST_IS_INPUT_STREAM(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INPUT_STREAM)) - -#define GST_IS_INPUT_STREAM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INPUT_STREAM)) - typedef struct _GstInputStream GstInputStream; -typedef struct _GstInputStreamClass GstInputStreamClass; typedef struct _GstInputStreamPrivate GstInputStreamPrivate; struct _GstInputStream { - GObject parent; - /* instance members */ GstInputStreamPrivate *priv; }; -struct _GstInputStreamClass -{ - GObjectClass parent_class; -}; - -GType gst_input_stream_get_type (void); - +/** + * Clean the given instance of GstInputStream so that the garbage + * collector can collect the cached Java classes. + * Call this fuction when you don't need anymore to use this instance of + * GstInputStream. Note that failure to call this routine will result in + * memroy leaks. + */ +void gst_input_stream_clean (GstInputStream *self); + +/** + * Perform the "read" operation on this GstInputStream. + */ int gst_input_stream_read (GstInputStream *self, int *data, int offset, int length); - -gboolean gst_input_stream_available (GstInputStream *self, guint64 *size); - -gboolean gst_input_stream_can_seek (GstInputStream *self); - -long gst_input_stream_skip (GstInputStream *self, long size); - -void gst_input_stream_reset (GstInputStream *self); - -/* exported properties */ - -#define GST_ISTREAM_JVM "vm" -#define GST_ISTREAM_READER "reader" -G_END_DECLS +/** + * Returns the number of byte currently available for read in this + * GstInputStream. + */ +int gst_input_stream_available (GstInputStream *self); #endif /* __GST_INPUT_STREAM_H__ */ diff --git a/libjava/classpath/native/jni/gstreamer-peer/gst_native_data_line.c b/libjava/classpath/native/jni/gstreamer-peer/gst_native_data_line.c new file mode 100644 index 0000000..84e76a1 --- /dev/null +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_native_data_line.c @@ -0,0 +1,251 @@ +/*gst_native_data_line.c - Implements the native methods of GstNativeDataLine + 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. */ + +#include <jni.h> + +#include <gst/gst.h> + +#include "jcl.h" +#include "gnu_javax_sound_sampled_gstreamer_lines_GstNativeDataLine.h" + +#include "gst_peer.h" +#include "gst_classpath_src.h" +#include "gst_native_pipeline.h" + +static jfieldID pointerDataFID = NULL; + +/* ************************************************************************** */ + +static GstElement *setup_pipeline (GstNativePipeline *jpipeline, int fd); +static void +gst_newpad (GstElement *decodebin, GstPad *pad, gboolean last, gpointer data); + +/* ************************************************************************** */ + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstNativeDataLine_init_1id_1cache + (JNIEnv *env __attribute__ ((unused)), jclass clazz __attribute__ ((unused))) +{ + jclass pointerClass = NULL; + +#if SIZEOF_VOID_P == 8 + pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer64"); + if (pointerClass != NULL) + { + pointerDataFID = (*env)->GetFieldID (env, pointerClass, "data", "J"); + } +#else +# if SIZEOF_VOID_P == 4 + pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer32"); + if (pointerClass != NULL) + { + pointerDataFID = (*env)->GetFieldID(env, pointerClass, "data", "I"); + } +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ +} + +JNIEXPORT jboolean JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstNativeDataLine_setup_1sink_1pipeline + (JNIEnv *env, jclass clazz __attribute__ ((unused)), + jobject pointer) +{ + GstNativePipeline *jpipeline = NULL; + + GstElement *pipeline = NULL; + GstElement *sink = NULL; + GstElement *audioconv= NULL; + GstElement *resample = NULL; + GstElement *audio = NULL; + GstElement *decodebin = NULL; + + GstPad *audiopad = NULL; + + gst_init (NULL, NULL); + + /* get the pipeline from the pointer, then create it if needed */ + jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer, + pointerDataFID); + if (jpipeline == NULL) + return JNI_FALSE; + + pipeline = setup_pipeline (jpipeline, + gst_native_pipeline_get_pipeline_fd (jpipeline)); + if (pipeline == NULL) + return JNI_FALSE; + + /* add the audio sink to the pipeline */ + /* TODO: hardcoded values */ + sink = gst_element_factory_make ("autoaudiosink", "alsa-output"); + if (sink == NULL) + { + gst_object_unref(GST_OBJECT(pipeline)); + gst_object_unref(GST_OBJECT(sink)); + + g_warning ("unable to create sink\n"); + return JNI_FALSE; + } + + audioconv = gst_element_factory_make ("audioconvert", "aconv"); + if (audioconv == NULL) + { + gst_object_unref(GST_OBJECT(pipeline)); + gst_object_unref(GST_OBJECT(sink)); + gst_object_unref(GST_OBJECT(decodebin)); + + g_warning ("unable to create audioconv\n"); + return JNI_FALSE; + } + + audio = gst_bin_new ("audiobin"); + if (audio == NULL) + { + gst_object_unref(GST_OBJECT(pipeline)); + gst_object_unref(GST_OBJECT(sink)); + gst_object_unref(GST_OBJECT(decodebin)); + + g_warning ("unable to create audioconv\n"); + return JNI_FALSE; + } + + resample = gst_element_factory_make ("audioresample", "audioresample"); + if (audioconv == NULL) + { + gst_object_unref(GST_OBJECT(pipeline)); + gst_object_unref(GST_OBJECT(sink)); + gst_object_unref(GST_OBJECT(decodebin)); + gst_object_unref(GST_OBJECT(audio)); + + g_warning ("unable to create resample\n"); + return JNI_FALSE; + } + + audiopad = gst_element_get_pad (audioconv, "sink"); + gst_bin_add_many (GST_BIN (audio), audioconv, resample, sink, NULL); + gst_element_link (audioconv, sink); + + gst_element_add_pad (audio, gst_ghost_pad_new ("sink", audiopad)); + + gst_object_unref (audiopad); + gst_bin_add (GST_BIN (pipeline), audio); + + decodebin = gst_bin_get_by_name (GST_BIN (pipeline), "decodebin"); + g_signal_connect (decodebin, "new-decoded-pad", G_CALLBACK (gst_newpad), + audio); + + gst_native_pipeline_set_pipeline (jpipeline, pipeline); + + return JNI_TRUE; +} + +/* ************************************************************************** */ + +static GstElement *setup_pipeline (GstNativePipeline *jpipeline, int fd) +{ + GstElement *decodebin = NULL; + GstElement *source = NULL; + + GstElement *pipeline = NULL; + + if (fd < 0) + return NULL; + + pipeline = gst_pipeline_new ("java sound pipeline"); + if (pipeline == NULL) + return NULL; + + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + if (decodebin == NULL) + { + gst_object_unref(GST_OBJECT(pipeline)); + gst_object_unref(GST_OBJECT(source)); + + g_warning ("unable to create decodebin\n"); + return NULL; + } + + source = gst_element_factory_make ("fdsrc", "source"); + if (source == NULL) + { + gst_object_unref(GST_OBJECT(pipeline)); + gst_object_unref(GST_OBJECT(source)); + gst_object_unref(GST_OBJECT(decodebin)); + + g_warning ("unable to create a source"); + return JNI_FALSE; + } + g_object_set (G_OBJECT (source), "fd", fd, NULL); + + gst_bin_add_many (GST_BIN (pipeline), source, decodebin, NULL); + gst_element_link (source, decodebin); + + return pipeline; +} + +static void +gst_newpad (GstElement *decodebin, GstPad *pad, gboolean last, gpointer data) +{ + GstCaps *caps; + GstStructure *str; + GstPad *audiopad; + + GstElement *audio = (GstElement *) data; + + /* only link once */ + audiopad = gst_element_get_pad (audio, "sink"); + if (GST_PAD_IS_LINKED (audiopad)) + { + g_object_unref (audiopad); + return; + } + + /* check media type */ + caps = gst_pad_get_caps (pad); + str = gst_caps_get_structure (caps, 0); + if (!g_strrstr (gst_structure_get_name (str), "audio")) + { + gst_caps_unref (caps); + gst_object_unref (audiopad); + return; + } + gst_caps_unref (caps); + + /* link'n'play */ + gst_pad_link (pad, audiopad); +} diff --git a/libjava/classpath/native/jni/gstreamer-peer/gst_native_pipeline.c b/libjava/classpath/native/jni/gstreamer-peer/gst_native_pipeline.c new file mode 100644 index 0000000..3e32568 --- /dev/null +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_native_pipeline.c @@ -0,0 +1,611 @@ +/*gst_native_pipeline.c - Header 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. */ + +#include <jni.h> +#include <jcl.h> + +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <unistd.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif /* HAVE_FCNTL_H */ + +#if defined(HAVE_SYS_IOCTL_H) +#define BSD_COMP /* Get FIONREAD on Solaris2 */ +#include <sys/ioctl.h> +#endif +#if defined(HAVE_SYS_FILIO_H) /* Get FIONREAD on Solaris 2.5 */ +#include <sys/filio.h> +#endif + +#include <gdk/gdk.h> +#include <glib.h> + +#include <gst/gst.h> + +#include "cpio.h" +#include "gst_peer.h" + +#include "gnu_javax_sound_sampled_gstreamer_lines_GstPipeline.h" +#include "gst_native_pipeline.h" + +static jmethodID pointerConstructorMID = NULL; + +static jfieldID pipelineFID = NULL; +static jfieldID pointerDataFID = NULL; +static jfieldID nameFID = NULL; +static jfieldID capacityFID = NULL; + +/* + * Needed to compute the size of the data still available for processing in the + * pipeline. We give a default here but this will be overwritten by the + * detection routines. + */ +static long GST_DETECTED_PIPE_CAPACITY = 65536; + +/* + * Note: the Java code uses enum classes, these are not mapped into constants + * by the javah tool, changes to these values should be reflected in the Java + * side. + */ +enum +{ + PLAY, + PAUSE, + STOP +}; + +/* + * Defined as constants in the Java code, hence mapped by javah. + */ +enum +{ + READ = gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_READ, + WRITE = gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_WRITE +}; + +struct _GstNativePipelinePrivate +{ + JavaVM *vm; + jclass GstPipelineClass; + jclass PointerClass; + + jobject jni_pipeline; + + char *name; + int fd; + + GstElement *pipeline; +}; + +/* ************************************************************************** */ +/* +static void gst_native_pipeline_clean (GstNativePipeline *self);*/ +static char *create_name (void); +static void init_pointer_IDs (JNIEnv* env); +static jint get_free_space (int fd); +static void detect_pipe_max (void); + +/* ************************************************************************** */ + +/* JNI Methods */ + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_init_1id_1cache + (JNIEnv *env, jclass clazz) +{ + pipelineFID = (*env)->GetFieldID (env, clazz, "pipeline", + "Lgnu/classpath/Pointer;"); + nameFID = (*env)->GetFieldID (env, clazz, "name", "Ljava/lang/String;"); + capacityFID = (*env)->GetFieldID (env, clazz, "capacity", "J"); + + init_pointer_IDs (env); +} + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_init_1instance + (JNIEnv *env, jobject pipeline) +{ + GstNativePipeline *_pipeline = NULL; + + jclass localGstPipelineClass = NULL; + jclass localPointerClass = NULL; + jobject _pointer = NULL; + + _pipeline = + (GstNativePipeline *) JCL_malloc (env, sizeof (GstNativePipeline)); + if (_pipeline == NULL) + return; + + _pipeline->priv = (GstNativePipelinePrivate *) + JCL_malloc (env, sizeof (GstNativePipelinePrivate)); + if (_pipeline->priv == NULL) + { + JCL_free (env, _pipeline); + return; + } + +#if SIZEOF_VOID_P == 8 + localPointerClass = JCL_FindClass (env, "gnu/classpath/Pointer64"); +#else +# if SIZEOF_VOID_P == 4 + localPointerClass = JCL_FindClass (env, "gnu/classpath/Pointer32"); +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ + + localGstPipelineClass = (*env)->GetObjectClass(env, pipeline); + if (localGstPipelineClass == NULL || localGstPipelineClass == NULL) + { + JCL_free (env, _pipeline->priv); + JCL_free (env, _pipeline); + JCL_ThrowException (env, "java/lang/InternalError", + "Class Initialization failed."); + return; + } + + GST_DETECTED_PIPE_CAPACITY = (long) (*env)->GetLongField(env, pipeline, + capacityFID); + + /* fill the object */ + (*env)->GetJavaVM(env, &_pipeline->priv->vm); + _pipeline->priv->jni_pipeline = (*env)->NewGlobalRef(env, pipeline); + _pipeline->priv->GstPipelineClass = + (*env)->NewGlobalRef(env, localGstPipelineClass); + _pipeline->priv->PointerClass = (*env)->NewGlobalRef(env, localPointerClass); + _pipeline->priv->pipeline = NULL; + + _pointer = (*env)->GetObjectField(env, pipeline, pipelineFID); + + if (_pointer == NULL) + { +#if SIZEOF_VOID_P == 8 + _pointer = (*env)->NewObject(env, _pipeline->priv->PointerClass, + pointerConstructorMID, (jlong) _pipeline); +#else + _pointer = (*env)->NewObject(env, _pipeline->priv->PointerClass, + pointerConstructorMID, (jint) _pipeline); +#endif + } + else + { +#if SIZEOF_VOID_P == 8 + (*env)->SetLongField(env, pipeline, pipelineFID, (jlong) _pipeline); +#else + (*env)->SetIntField(env, pipeline, pipelineFID, (jint) _pipeline); +#endif + } + + /* store back our pointer into the calling class */ + (*env)->SetObjectField(env, pipeline, pipelineFID, _pointer); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_set_1state + (JNIEnv *env, jclass clazz, jobject pointer, jint state) +{ + GstNativePipeline *jpipeline = NULL; + jboolean result = JNI_FALSE; + + if (pointer == NULL) + { + JCL_ThrowException (env, "javax/sound/sampled/LineUnavailableException", + "Can't change pipeline state: " \ + "pipeline not initialized"); + return result; + } + + jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer, + pointerDataFID); + if (jpipeline == NULL) + return JNI_FALSE; + + switch (state) + { + case (PLAY): + gst_element_set_state(GST_ELEMENT(jpipeline->priv->pipeline), + GST_STATE_PLAYING); + result = JNI_TRUE; + break; + + case (PAUSE): + gst_element_set_state(GST_ELEMENT(jpipeline->priv->pipeline), + GST_STATE_PAUSED); + result = JNI_TRUE; + break; + + case (STOP): +#ifndef WITHOUT_FILESYSTEM + /* clean the pipeline and kill named pipe */ + if (jpipeline->priv->name) + { + cpio_removeFile (jpipeline->priv->name); + g_free (jpipeline->priv->name); + jpipeline->priv->name = NULL; + } +#endif /* WITHOUT_FILESYSTEM */ + + if (jpipeline->priv->pipeline != NULL) + gst_object_unref (GST_OBJECT(jpipeline->priv->pipeline)); + result = JNI_TRUE; + break; + + default: + /* nothing */ + result = JNI_FALSE; + break; + } + + return result; +} + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_open_1native_1pipe + (JNIEnv *env, jclass clazz, jobject pointer, jint mode) +{ + GstNativePipeline *jpipeline = NULL; + + jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer, + pointerDataFID); + switch (mode) + { + case (READ): + jpipeline->priv->fd = + open (jpipeline->priv->name, O_RDONLY | O_NONBLOCK); + break; + + case (WRITE): + /* TODO: no-op currently */ + break; + } +} + +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_close_1native_1pipe + (JNIEnv *env, jclass clazz, jobject pointer) +{ +#ifndef WITHOUT_FILESYSTEM + GstNativePipeline *jpipeline = NULL; + jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer, + pointerDataFID); + /* kill the named pipe */ + if (jpipeline->priv->name) + { + cpio_removeFile (jpipeline->priv->name); + g_free (jpipeline->priv->name); + jpipeline->priv->name = NULL; + } +#endif /* WITHOUT_FILESYSTEM */ +} + +JNIEXPORT jboolean JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_create_1named_1pipe + (JNIEnv *env, jobject GstPipeline, jobject pointer) +{ +#ifndef WITHOUT_FILESYSTEM + /* + * We get a temp name for the named pipe, create the named pipe and then + * set the relative field in the java class. + */ + GstNativePipeline *jpipeline = NULL; + jstring *name = NULL; + + jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer, + pointerDataFID); + if (jpipeline == NULL) + return JNI_FALSE; + + jpipeline->priv->name = create_name (); + if (jpipeline->priv->name == NULL) + return JNI_FALSE; + + if (mkfifo (jpipeline->priv->name, 0600) < 0) + { + if (jpipeline->priv->name != NULL) + free (jpipeline->priv->name); + return JNI_FALSE; + } + + /* now set the String field */ + name = (*env)->NewStringUTF(env, jpipeline->priv->name); + if (name == NULL) + { + cpio_removeFile (jpipeline->priv->name); + if (jpipeline->priv->name != NULL) + free (jpipeline->priv->name); + + return JNI_FALSE; + } + + (*env)->SetObjectField(env, GstPipeline, nameFID, name); + + return JNI_TRUE; + +#else /* not WITHOUT_FILESYSTEM */ + return JNI_FALSE; +#endif /* not WITHOUT_FILESYSTEM */ +} + +JNIEXPORT jint JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_available + (JNIEnv *env, jclass clazz, jobject pointer, jint mode) +{ + jint result = -1; + +#ifndef WITHOUT_FILESYSTEM + + GstNativePipeline *jpipeline = NULL; + jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer, + pointerDataFID); + + if (mode == READ) + { + result = get_free_space (jpipeline->priv->fd); + } + else + { +# if defined (FIONREAD) + if (ioctl (jpipeline->priv->fd, FIONREAD, &result) == -1) + g_warning("IMPLEMENT ME: ioctl failed"); + +# else /* not defined (FIONREAD) */ + g_warning("IMPLEMENT ME: !defined (FIONREAD"); +# endif /* defined (FIONREAD) */ + + } /* if (mode == READ) */ + +#endif /* not WITHOUT_FILESYSTEM */ + + return result; +} + +JNIEXPORT jlong JNICALL +Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_detect_1pipe_1size + (JNIEnv *env, jobject GstPipeline) +{ + detect_pipe_max (); + + return GST_DETECTED_PIPE_CAPACITY; +} + +/* exported library functions */ +/* +static void gst_native_pipeline_clean (GstNativePipeline *self) +{ + JNIEnv *env = NULL; + + env = gst_get_jenv (self->priv->vm); + + (*env)->DeleteGlobalRef (env, self->priv->jni_pipeline); + (*env)->DeleteGlobalRef (env, self->priv->GstPipelineClass); + (*env)->DeleteGlobalRef (env, self->priv->PointerClass); + + if (self->priv->pipeline != NULL) + gst_object_unref (GST_OBJECT (self->priv->pipeline)); + + if (self->priv->name) + { + cpio_removeFile (self->priv->name); + g_free (self->priv->name); + self->priv->name = NULL; + } + + JCL_free (env, self->priv); + JCL_free (env, self); +} +*/ +void gst_native_pipeline_set_pipeline (GstNativePipeline *self, + GstElement *pipeline) +{ + if (self->priv->pipeline != NULL) + gst_object_unref (GST_OBJECT (self->priv->pipeline)); + + self->priv->pipeline = pipeline; +} + +GstElement *gst_native_pipeline_get_pipeline (GstNativePipeline *self) +{ + return self->priv->pipeline; +} + +char *gst_native_pipeline_get_pipeline_name (GstNativePipeline *self) +{ + return self->priv->name; +} + +int gst_native_pipeline_get_pipeline_fd (GstNativePipeline *self) +{ + return self->priv->fd; +} + +/* private functions */ + +static void init_pointer_IDs (JNIEnv* env) +{ + jclass PointerClass = NULL; + +#if SIZEOF_VOID_P == 8 + PointerClass = JCL_FindClass (env, "gnu/classpath/Pointer64"); + if (PointerClass != NULL) + { + pointerDataFID = (*env)->GetFieldID (env, PointerClass, "data", "J"); + pointerConstructorMID = (*env)->GetMethodID (env, PointerClass, "<init>", + "(J)V"); + } +#else +# if SIZEOF_VOID_P == 4 + PointerClass = JCL_FindClass (env, "gnu/classpath/Pointer32"); + if (PointerClass != NULL) + { + pointerDataFID = (*env)->GetFieldID(env, PointerClass, "data", "I"); + pointerConstructorMID = (*env)->GetMethodID(env, PointerClass, + "<init>", "(I)V"); + } +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ +} + +static jint get_free_space (int fd) +{ + jint result = -1; + +#if defined (FIONSPACE) + + if (ioctl (fd, FIONSPACE, &result) == -1) + { + g_warning("IMPLEMENT ME: ioctl failed"); + } + +#elif defined (FIONREAD) + + if (ioctl (fd, FIONREAD, &result) == -1) + { + g_warning("IMPLEMENT ME: ioctl failed"); + } + + result = GST_DETECTED_PIPE_CAPACITY - result; + +#elif + g_warning("IMPLEMENT ME!!! - !defined (FIONSPACE), !defined (FIONREAD"); + +#endif + + return result; +} + +static char *create_name (void) +{ + char *buffer = NULL; + char *tmp = NULL; + + buffer = (char *) g_malloc0 (_GST_MALLOC_SIZE_); + if (buffer == NULL) + { + /* huston, we have a problem... */ + return NULL; + } + + tmp = tempnam (NULL, _GST_PIPELINE_PREFIX_); + if (tmp == NULL) + { + g_free (buffer); + return NULL; + } + + g_snprintf (buffer, _GST_MALLOC_SIZE_, "%s%s", tmp, _GST_PIPELINE_SUFFIX_); + g_free (tmp); + + return buffer; +} + +static void detect_pipe_max (void) +{ + int read_fd; + int write_fd; + + /* can be anything! */ + char *character = "a"; + char *pipe = NULL; + + gboolean available = TRUE; + int w = 0; + long wrote = 0; + + pipe = create_name (); + if (pipe == NULL) + { + g_warning ("can't create test pipe name"); + return; + } + + if (mkfifo (pipe, 0600) < 0) + { + g_warning ("unable to create test pipe..."); + g_free (pipe); + + return; + } + + /* open both end of the pipe */ + read_fd = open (pipe, O_RDONLY | O_NONBLOCK); + if (read_fd < 0) + { + cpio_removeFile (pipe); + g_free (pipe); + + return; + } + + write_fd = open (pipe, O_WRONLY | O_NONBLOCK); + if (write_fd < 0) + { + cpio_closeFile (write_fd); + cpio_removeFile (pipe); + g_free (pipe); + + return; + } + + while (available) + { + w = 0; + + cpio_write (write_fd, character, 1, &w); + if (w < 0) + available = FALSE; + else + wrote += w; + } + + GST_DETECTED_PIPE_CAPACITY = wrote; + + cpio_closeFile (write_fd); + cpio_closeFile (read_fd); + cpio_removeFile (pipe); + + g_free (pipe); +} diff --git a/libjava/classpath/native/jni/gstreamer-peer/gst_native_pipeline.h b/libjava/classpath/native/jni/gstreamer-peer/gst_native_pipeline.h new file mode 100644 index 0000000..b5a45b4 --- /dev/null +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_native_pipeline.h @@ -0,0 +1,63 @@ +/*gst_native_pipeline.h - Header 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. */ + +#ifndef __GST_NATIVE_PIPELINE_H__ +#define __GST_NATIVE_PIPELINE_H__ + +#include <glib.h> + +#include <gst/gst.h> + +typedef struct _GstNativePipeline GstNativePipeline; +typedef struct _GstNativePipelinePrivate GstNativePipelinePrivate; + +struct _GstNativePipeline +{ + /* instance members */ + GstNativePipelinePrivate *priv; +}; + +void gst_native_pipeline_set_pipeline (GstNativePipeline *self, + GstElement *pipeline); + +GstElement *gst_native_pipeline_get_pipeline (GstNativePipeline *self); + +char *gst_native_pipeline_get_pipeline_name (GstNativePipeline *self); + +int gst_native_pipeline_get_pipeline_fd (GstNativePipeline *self); + +#endif /* __GST_NATIVE_PIPELINE_H__ */ diff --git a/libjava/classpath/native/jni/gstreamer-peer/gst_peer.c b/libjava/classpath/native/jni/gstreamer-peer/gst_peer.c new file mode 100644 index 0000000..da83b00 --- /dev/null +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_peer.c @@ -0,0 +1,83 @@ +/*gst_peer.c - Common utility functions for the native peer. + 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. */ + +#include <glib.h> + +#include <jni.h> +#include "jcl.h" + +#include "gst_peer.h" + +JNIEnv *gst_get_jenv (JavaVM *vm) +{ + void *env = NULL; + + if ((*vm)->GetEnv(vm, &env, JNI_VERSION_1_2) != JNI_OK) + { + if ((*vm)->AttachCurrentThreadAsDaemon(vm, &env, NULL) < 0) + { + g_warning ("GstNativePipeline:- env not attached"); + return NULL; + } + } + + return (JNIEnv *) env; +} + +void * +get_object_from_pointer (JNIEnv *env, jobject pointer, jfieldID pointerDataFID) +{ + void *_object = NULL; + + if (env == NULL) + return NULL; + + if ((*env)->IsSameObject(env, pointer, NULL) == JNI_TRUE) + return NULL; + +#if SIZEOF_VOID_P == 8 + _object = (void *) (*env)->GetLongField(env, pointer, pointerDataFID); +#else +# if SIZEOF_VOID_P == 4 + _object = (void *) (*env)->GetIntField(env, pointer, pointerDataFID); +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ + + return _object; +} diff --git a/libjava/classpath/native/jni/gstreamer-peer/gst_peer.h b/libjava/classpath/native/jni/gstreamer-peer/gst_peer.h new file mode 100644 index 0000000..4500001 --- /dev/null +++ b/libjava/classpath/native/jni/gstreamer-peer/gst_peer.h @@ -0,0 +1,59 @@ +/*gst_peer.h - Common utility functions for the native peer. + 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. */ + +#include <jni.h> +#include "jcl.h" + +#ifdef MAXPATHLEN +# define _GST_MALLOC_SIZE_ MAXPATHLEN +#else +# define _GST_MALLOC_SIZE_ 1024 +#endif + +#define _GST_PIPELINE_PREFIX_ "cp-" +#define _GST_PIPELINE_SUFFIX_ "-classpath-gst-audio" + +/** + * Return a reference to the object stored in this Pointer. + */ +void * +get_object_from_pointer (JNIEnv *env, jobject pointer, jfieldID pointerDataFID); + +/** + * Return the JNIEnv valid under the current thread context. + */ +JNIEnv *gst_get_jenv (JavaVM *vm); diff --git a/libjava/classpath/native/jni/gstreamer-peer/gstinputstream.c b/libjava/classpath/native/jni/gstreamer-peer/gstinputstream.c deleted file mode 100644 index eb49696..0000000 --- a/libjava/classpath/native/jni/gstreamer-peer/gstinputstream.c +++ /dev/null @@ -1,494 +0,0 @@ -/*gstinputstream.c - Header 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. */ - -#include <jni.h> -#include <jcl.h> - -#include <string.h> -#include <stdlib.h> - -#include <gdk/gdk.h> - -#include <glib.h> -#include <glib/gprintf.h> - -#include "gstinputstream.h" - -struct _GstInputStreamPrivate -{ - JavaVM *vm; - jobject *reader; - - gboolean eof; - guint8 *buffer; - long size; - long length; - - gboolean disposed; -}; - -#define INPUT_STREAM_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_INPUT_STREAM, GstInputStreamPrivate)) - -/* properties */ - -enum -{ - ARG_0, - ARG_JVM, - ARG_READER -}; - -/* ***** */ - -static JNIEnv *gst_input_stream_get_jenv(GstInputStream *self); - -static void gst_input_stream_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - -static void gst_input_stream_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static void gst_input_stream_instance_init (GTypeInstance *instance, - gpointer g_class); - -static void gst_input_stream_class_init (gpointer g_class, - gpointer g_class_data); - -static GObject * -gst_input_stream_constructor (GType type, guint n_construct_properties, - GObjectConstructParam *construct_properties); - -static void -gst_input_stream_dispose (GObject *obj); - -static void -gst_input_stream_finalize (GObject *obj); - -/* ************************************************************************** */ - -/* class methods */ - -int -gst_input_stream_read (GstInputStream *self, int *data, int offset, - int length) -{ - /* TODO: cache */ - jmethodID _readID = NULL; - jclass InputStream = NULL; - - JNIEnv *env = NULL; - - int ret = -1; - jbyteArray buffer; - jbyte *bytes = NULL; - - if (self->priv->disposed || self->priv->vm == NULL || - self->priv->reader == NULL) - { - return -1; - } - - env = gst_input_stream_get_jenv (self); - if (env == NULL) - { - g_warning("GstInputStream::gst_input_stream_read failed to get java env"); - return -1; - } - - buffer = (*env)->NewByteArray (env, length); - if (buffer == NULL) - { - g_warning ("GstInputStream::gst_input_stream_read called, failed"); - return -1; - } - - InputStream = (*env)->GetObjectClass(env, self->priv->reader); - _readID = (*env)->GetMethodID(env, InputStream, "read", "([BII)I"); - if (_readID == NULL) - { - (*env)->DeleteLocalRef(env, buffer); - return -1; - } - - ret = (*env)->CallIntMethod (env, self->priv->reader, _readID, buffer, 0, - length); - if (ret == -1) - { - (*env)->DeleteLocalRef(env, buffer); - return ret; - } - - bytes = (*env)->GetByteArrayElements (env, buffer, NULL); - - /* copy bytes and release */ - memcpy (data + offset, bytes, ret); - - (*env)->ReleaseByteArrayElements (env, buffer, bytes, 0); - (*env)->DeleteLocalRef (env, buffer); - - return ret; -} - -gboolean -gst_input_stream_available (GstInputStream *self, guint64 *size) -{ - /* TODO: caching */ - - jmethodID _availableID = NULL; - jclass InputStream = NULL; - JNIEnv *env = NULL; - - if (self->priv->disposed || self->priv->vm == NULL || - self->priv->reader == NULL) - { - return FALSE; - } - - env = gst_input_stream_get_jenv(self); - if (env == NULL) - { - g_warning("GstInputStream::gst_input_stream_available failed to get java env"); - return FALSE; - } - - InputStream = (*env)->GetObjectClass(env, self->priv->reader); - _availableID = (*env)->GetMethodID(env, InputStream, "available", "()I"); - if (_availableID == NULL) - { - return FALSE; - } - - *size = (*env)->CallIntMethod (env, self->priv->reader, _availableID); - - return TRUE; -} - -void gst_input_stream_reset (GstInputStream *self) -{ - jmethodID _resetID = NULL; - jclass InputStream = NULL; - JNIEnv *env = NULL; - - if (self->priv->disposed || self->priv->vm == NULL || - self->priv->reader == NULL) - { - return; - } - - env = gst_input_stream_get_jenv(self); - if (env == NULL) - { - g_warning("GstInputStream::gst_input_stream_reset failed to get java env"); - return; - } - - InputStream = (*env)->GetObjectClass(env, self->priv->reader); - _resetID = (*env)->GetMethodID(env, InputStream, "reset", "()V"); - if (_resetID == NULL) - { - return; - } - - (*env)->CallVoidMethod (env, self->priv->reader, _resetID); -} - -long gst_input_stream_skip (GstInputStream *self, long size) -{ - jmethodID _seekID = NULL; - jclass InputStream = NULL; - JNIEnv *env = NULL; - - long skipped = -1; - - if (self->priv->disposed || self->priv->vm == NULL || - self->priv->reader == NULL) - { - return skipped; - } - - env = gst_input_stream_get_jenv(self); - if (env == NULL) - { - g_warning("GstInputStream::gst_input_stream_skip failed to get java env"); - return size; - } - - InputStream = (*env)->GetObjectClass(env, self->priv->reader); - _seekID = (*env)->GetMethodID(env, InputStream, "skip", "(J)J"); - if (_seekID == NULL) - { - return skipped; - } - - size = (*env)->CallIntMethod (env, self->priv->reader, _seekID, size); - if (size != 0) - { - return skipped; - } - - return skipped; -} - -gboolean gst_input_stream_can_seek (GstInputStream *self) -{ - if (gst_input_stream_skip(self, 0) != 0) - { - g_warning ("GstInputStream::gst_input_stream_can_seek CANNOT seek"); - return FALSE; - } - - return TRUE; -} - -/* ************************************************************************** */ - -/* getter and setter */ - -static void -gst_input_stream_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GstInputStream *self = GST_INPUT_STREAM (object); - - switch (property_id) - { - case ARG_JVM: - { - self->priv->vm = g_value_get_pointer(value); - } - break; - - case ARG_READER: - { - self->priv->reader = g_value_get_pointer(value); - } - break; - - default: - /* We don't have any other property... */ - G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); - break; - } /* switch */ -} - -static void -gst_input_stream_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GstInputStream *self = GST_INPUT_STREAM (object); - - switch (property_id) - { - case ARG_JVM: - { - g_value_set_pointer (value, self->priv->vm); - } - break; - - case ARG_READER: - { - g_value_set_pointer (value, self->priv->reader); - } - break; - - default: - /* We don't have any other property... */ - G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); - break; - } /* switch */ -} - -/* ************************************************************************** */ - -static void -gst_input_stream_instance_init (GTypeInstance *instance, - gpointer g_class __attribute__ ((unused))) -{ - GstInputStream *self = GST_INPUT_STREAM (instance); - - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INPUT_STREAM, - GstInputStreamPrivate); - - self->priv->vm = NULL; - self->priv->reader = NULL; - self->priv->disposed = FALSE; - self->priv->eof = FALSE; - self->priv->buffer = NULL; - self->priv->size = 0; - self->priv->length = 0; -} - -static void -gst_input_stream_class_init (gpointer g_class, - gpointer g_class_data __attribute__ ((unused))) -{ - GObjectClass *gobject_class; - GstInputStreamClass *klass; - GObjectClass *parent_class; - - GParamSpec *pspec; - - gobject_class = G_OBJECT_CLASS (g_class); - klass = GST_INPUT_STREAM_CLASS (g_class); - gobject_class = G_OBJECT_CLASS (g_class); - - g_type_class_add_private (klass, sizeof (GstInputStreamPrivate)); - - gobject_class->set_property = gst_input_stream_set_property; - gobject_class->get_property = gst_input_stream_get_property; - gobject_class->dispose = gst_input_stream_dispose; - gobject_class->finalize = gst_input_stream_finalize; - gobject_class->constructor = gst_input_stream_constructor; - - parent_class = g_type_class_peek_parent (klass); - - /* register properties */ - pspec = g_param_spec_pointer (GST_ISTREAM_JVM, - "Set the java environment property", - "Set the java environment property", - G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, ARG_JVM, pspec); - - pspec = g_param_spec_pointer (GST_ISTREAM_READER, - "Set the java reader property", - "Set the java reader property", - G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, ARG_READER, pspec); - -} - -/* class constructors */ - -static GObject * -gst_input_stream_constructor (GType type, guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GObject *obj; - GObjectClass *parent_class; - - /* parent */ - GstInputStreamClass *klass; - klass = GST_INPUT_STREAM_CLASS (g_type_class_peek (GST_TYPE_INPUT_STREAM)); - parent_class = g_type_class_peek_parent (klass); - obj = parent_class->constructor (type, n_construct_properties, - construct_properties); - return obj; -} - -static void -gst_input_stream_dispose (GObject *obj) -{ - GObjectClass *parent_class; - GstInputStream *self = GST_INPUT_STREAM (obj); - if (self->priv->disposed) - { - /* If dispose did already run, return. */ - return; - } - - /* Make sure dispose does not run twice. */ - self->priv->disposed = TRUE; - - if (self->priv->buffer != NULL) - g_free(self->priv->buffer); - - /* Chain up to the parent class */ - parent_class = g_type_class_peek_parent (GST_INPUT_STREAM_CLASS (obj)); - G_OBJECT_CLASS (parent_class)->dispose (obj); -} - -static void -gst_input_stream_finalize (GObject *obj) -{ - /* nothing else to do */ - GObjectClass *parent_class = - g_type_class_peek_parent (GST_INPUT_STREAM_CLASS (obj)); - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static JNIEnv * -gst_input_stream_get_jenv(GstInputStream *self) -{ - void *env = NULL; - - if ((*self->priv->vm)->GetEnv(self->priv->vm, &env, JNI_VERSION_1_2) != JNI_OK) - { - if ((*self->priv->vm)->AttachCurrentThreadAsDaemon(self->priv->vm, - &env, NULL) < 0) - { - g_warning ("GstInputStream:- env not attached"); - return NULL; - } - } - - return (JNIEnv *) env; -} - -GType gst_input_stream_get_type (void) -{ - static GType type = 0; - - if (type == 0) - { - static const GTypeInfo info = { - sizeof (GstInputStreamClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - gst_input_stream_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GstInputStream), - 0, /* n_preallocs */ - gst_input_stream_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, - "GstInputStreamType", - &info, 0); - } - - return type; -} diff --git a/libjava/classpath/native/jni/gstreamer-peer/GStreamerIOPeer.c b/libjava/classpath/native/jni/gstreamer-peer/gstreamer_io_peer.c index f5d52e8..7e38b91 100644 --- a/libjava/classpath/native/jni/gstreamer-peer/GStreamerIOPeer.c +++ b/libjava/classpath/native/jni/gstreamer-peer/gstreamer_io_peer.c @@ -1,4 +1,5 @@ -/* GStreamerIOPeer.c -- Implements native methods for class GStreamerNativePeer +/* gstreamer_io_peer.c -- Implements native methods for class + GStreamerNativePeer Copyright (C) 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -49,12 +50,29 @@ #include "jcl.h" -#include "gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer.h" +#include "gst_peer.h" -#include "gstclasspathsrc.h" -#include "gstinputstream.h" +#include "gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer.h" -#define _GST_MALLOC_SIZE_ 256 +#include "gst_classpath_src.h" +#include "gst_input_stream.h" + +/* for caching */ +static jfieldID fileFID = NULL; +static jfieldID pointerDataID = NULL; + +static jfieldID mimetypeFID = NULL; +static jfieldID endiannessFID = NULL; +static jfieldID channelsFID = NULL; +static jfieldID rateFID = NULL; +static jfieldID widthFID = NULL; +static jfieldID depthFID = NULL; +static jfieldID isSignedFID = NULL; +static jfieldID nameFID = NULL; +static jfieldID layerFID = NULL; +static jfieldID bitrateFID = NULL; +static jfieldID framedFID = NULL; +static jfieldID typeFID = NULL; typedef struct _AudioProperties AudioProperties; struct _AudioProperties @@ -116,14 +134,12 @@ struct _AudioProperties const char *type; gboolean done; - }; /* ***** PRIVATE FUNCTIONS DECLARATION ***** */ static gboolean -set_strings (JNIEnv *env, const jclass GstHeader, - const AudioProperties *properties, jobject header); +set_strings (JNIEnv *env, const AudioProperties *properties, jobject header); static gboolean typefind_callback(GstElement *typefind, guint probability, const GstCaps *caps, @@ -134,7 +150,7 @@ element_added (GstBin *bin, GstElement *element, gpointer data); static void new_decoded_pad (GstElement *decoder, GstPad *pad, - gboolean last, GstElement *pipeline); + gboolean last, gpointer data); static gboolean fill_info (GstElement *decoder, AudioProperties *properties); @@ -146,8 +162,8 @@ static gchar * get_boolean_property (const GstStructure *structure, const gchar *property); static gboolean -set_string (JNIEnv *env, const jclass GstHeader, jobject header, - const char *field, const gchar *property); +set_string (JNIEnv *env, jobject header, jfieldID fieldID, + const gchar *property); static void free_properties (AudioProperties *properties); @@ -155,136 +171,97 @@ free_properties (AudioProperties *properties); static void reset_properties (AudioProperties *properties); +static jboolean process_audio (GstElement *source, JNIEnv *env, jobject header); + /* ***** END: PRIVATE FUNCTIONS DECLARATION ***** */ /* ***** NATIVE FUNCTIONS ***** */ -JNIEXPORT jboolean JNICALL -Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer_1get_1audio_1format_1stream - (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject header __attribute__ ((unused)), - jobject jstream __attribute__ ((unused))) +JNIEXPORT void JNICALL +Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_init_1id_1cache + (JNIEnv *env, jclass clazz __attribute__ ((unused))) { - GstInputStream *istream = NULL; - JavaVM *vm = NULL; + jclass pointerClass = NULL; jclass GstHeader = NULL; + + GstHeader = JCL_FindClass(env, "gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer$GstHeader"); + fileFID = (*env)->GetFieldID(env, GstHeader, "file", "Ljava/lang/String;"); + + mimetypeFID = (*env)->GetFieldID(env, GstHeader, "mimetype", + "Ljava/lang/String;"); + endiannessFID = (*env)->GetFieldID(env, GstHeader, "endianness", + "Ljava/lang/String;"); + channelsFID = (*env)->GetFieldID(env, GstHeader, "channels", + "Ljava/lang/String;"); + rateFID = (*env)->GetFieldID(env, GstHeader, "rate", "Ljava/lang/String;"); + widthFID = (*env)->GetFieldID(env, GstHeader, "width", "Ljava/lang/String;"); + depthFID = (*env)->GetFieldID(env, GstHeader, "depth", "Ljava/lang/String;"); + isSignedFID = (*env)->GetFieldID(env, GstHeader, "isSigned", + "Ljava/lang/String;"); + nameFID = (*env)->GetFieldID(env, GstHeader, "name", "Ljava/lang/String;"); + layerFID = (*env)->GetFieldID(env, GstHeader, "layer", "Ljava/lang/String;"); + bitrateFID = (*env)->GetFieldID(env, GstHeader, "bitrate", + "Ljava/lang/String;"); + framedFID = (*env)->GetFieldID(env, GstHeader, "framed", + "Ljava/lang/String;"); + typeFID = (*env)->GetFieldID(env, GstHeader, "type", "Ljava/lang/String;"); + +#if SIZEOF_VOID_P == 8 + pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer64"); + if (pointerClass != NULL) + { + pointerDataID = (*env)->GetFieldID (env, pointerClass, "data", "J"); + } +#else +# if SIZEOF_VOID_P == 4 + pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer32"); + if (pointerClass != NULL) + { + pointerDataID = (*env)->GetFieldID(env, pointerClass, "data", "I"); + } +# else +# error "Pointer size is not supported." +# endif /* SIZEOF_VOID_P == 4 */ +#endif /* SIZEOF_VOID_P == 8 */ - GstElement *pipeline = NULL; +} - GstElement *typefind = NULL; - GstElement *decodebin = NULL; +JNIEXPORT jboolean JNICALL +Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer_1get_1audio_1format_1stream + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject header, + jobject pointer) +{ + GstInputStream *istream = NULL; GstElement *source = NULL; - - AudioProperties *properties = NULL; - - jboolean result = JNI_FALSE; - - GstHeader = (*env)->GetObjectClass(env, header); - + gboolean result = JNI_FALSE; + + if (header == NULL) + return JNI_FALSE; + + if (pointer == NULL) + return JNI_FALSE; + + gst_init (NULL, NULL); + + istream = (GstInputStream *) get_object_from_pointer (env, pointer, + pointerDataID); + if (istream == NULL) + return JNI_FALSE; + + /* init gstreamer */ gst_init (NULL, NULL); - properties = (AudioProperties *) g_malloc0 (sizeof (AudioProperties)); - if (properties == NULL) - { - g_warning ("unable to allocate memory for properties"); - return JNI_FALSE; - } - - /* create the GstInputStream object */ - istream = g_object_new (GST_TYPE_INPUT_STREAM, NULL); - if (istream == NULL) - { - free_properties (properties); - - g_warning ("unable to create an istream"); - return JNI_FALSE; - } - + /* SOURCE */ source = gst_element_factory_make ("classpathsrc", "source"); if (source == NULL) { - free_properties (properties); - g_free ((gpointer) istream); - g_warning ("unable to create a source"); return JNI_FALSE; } - - /* store the vm and the input stream in the gstinputstream class */ - (*env)->GetJavaVM(env, &vm); - g_object_set (G_OBJECT (istream), GST_ISTREAM_JVM, vm, - GST_ISTREAM_READER, jstream, - NULL); g_object_set (G_OBJECT (source), GST_CLASSPATH_SRC_ISTREAM, istream, NULL); - - pipeline = gst_pipeline_new ("pipe"); - if (pipeline == NULL) - { - gst_object_unref (GST_OBJECT (source)); - g_free ((gpointer) istream); - free_properties (properties); - - g_warning ("unable to create the pipeline"); - return JNI_FALSE; - } - decodebin = gst_element_factory_make ("decodebin", "decodebin"); - if (decodebin == NULL) - { - gst_object_unref (GST_OBJECT (source)); - - g_free ((gpointer) istream); - free_properties(properties); - - gst_object_unref(GST_OBJECT(pipeline)); - - g_warning ("unable to create decodebin"); - return JNI_FALSE; - } - - g_signal_connect (decodebin, "new-decoded-pad", G_CALLBACK (new_decoded_pad), - pipeline); - - gst_bin_add_many (GST_BIN (pipeline), source, decodebin, NULL); - gst_element_link (source, decodebin); - - typefind = gst_bin_get_by_name (GST_BIN (decodebin), "typefind"); - if (typefind == NULL) - { - g_free ((gpointer) istream); - free_properties(properties); - - gst_object_unref(GST_OBJECT(pipeline)); - - g_warning ("unable to create decodebin"); - return JNI_FALSE; - } - - g_signal_connect (G_OBJECT (typefind), "have-type", - G_CALLBACK (typefind_callback), properties); - - gst_element_set_state (GST_ELEMENT(pipeline), GST_STATE_PLAYING); - if (gst_element_get_state (pipeline, NULL, NULL, 100000) == - GST_STATE_CHANGE_FAILURE) - { - g_free ((gpointer) istream); - free_properties(properties); - gst_object_unref(GST_OBJECT(pipeline)); - - g_warning ("Failed to go into PLAYING state"); - return JNI_FALSE; - } - - result = JNI_FALSE; - if (fill_info (decodebin, properties)) - { - result = set_strings (env, GstHeader, properties, header); - } + result = process_audio (source, env, header); - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); - - gst_object_unref (GST_OBJECT(pipeline)); - free_properties (properties); - return result; } @@ -292,67 +269,71 @@ JNIEXPORT jboolean JNICALL Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer_1get_1audio_1format_1file (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject header) { - /* will contain the properties we need to put into the given GstHeader */ - AudioProperties *properties = NULL; - /* source file */ const char *file = NULL; /* GStreamer elements */ - GstElement *pipeline = NULL; GstElement *source = NULL; - GstElement *decoder = NULL; - - GstElement *typefind = NULL; - - GstStateChangeReturn res; jboolean result = JNI_FALSE; /* java fields */ - jfieldID _fid = NULL; - jclass GstHeader = NULL; jstring _file = NULL; - GstHeader = (*env)->GetObjectClass(env, header); - _fid = (*env)->GetFieldID(env, GstHeader, "file", "Ljava/lang/String;"); - if (_fid == NULL) - { - return JNI_FALSE; /* failed to find the field */ - } - - _file = (*env)->GetObjectField(env, header, _fid); + _file = (*env)->GetObjectField(env, header, fileFID); file = JCL_jstring_to_cstring (env, _file); if (file == NULL) { return JNI_FALSE; } - - gst_init (NULL, NULL); - - properties = (AudioProperties *) g_malloc0 (sizeof (AudioProperties)); - if (properties == NULL) - { - free_properties (properties); - JCL_free_cstring (env, _file, file); - return JNI_FALSE; - } - - /* this is not really needed */ - reset_properties(properties); + gst_init (NULL, NULL); + /* create the source element, will be used to read the file */ source = gst_element_factory_make ("filesrc", "source"); if (source == NULL) { - free_properties (properties); JCL_free_cstring (env, _file, file); return JNI_FALSE; } /* set the file name */ g_object_set (G_OBJECT (source), "location", file, NULL); + + result = process_audio (source, env, header); + + /* free stuff */ + JCL_free_cstring (env, _file, file); + + return result; +} + +/* ***** END: NATIVE FUNCTIONS ***** */ + +/* ***** PRIVATE FUNCTIONS IMPLEMENTATION ***** */ + +static jboolean process_audio (GstElement *source, JNIEnv *env, jobject header) +{ + /* will contain the properties we need to put into the given GstHeader */ + AudioProperties *properties = NULL; + + /* GStreamer elements */ + GstElement *pipeline = NULL; + GstElement *decoder = NULL; + + GstElement *typefind = NULL; + + GstStateChangeReturn res; + + jboolean result = JNI_FALSE; + properties = (AudioProperties *) g_malloc0 (sizeof (AudioProperties)); + if (properties == NULL) + { + return result; + } + reset_properties(properties); + /* * create the decoder element, this will decode the stream and retrieve * its properties. @@ -363,30 +344,23 @@ Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer decoder = gst_element_factory_make ("decodebin", "decoder"); if (decoder == NULL) { - gst_object_unref (GST_OBJECT (source)); free_properties(properties); - - JCL_free_cstring (env, _file, file); - return JNI_FALSE; + return result; } - g_signal_connect (decoder, "new-decoded-pad", G_CALLBACK (new_decoded_pad), - pipeline); - g_signal_connect (G_OBJECT (decoder), "element-added", - G_CALLBACK (element_added), properties); - /* now, we create a pipeline and fill it with the other elements */ pipeline = gst_pipeline_new ("pipeline"); if (pipeline == NULL) { - gst_object_unref (GST_OBJECT (source)); gst_object_unref (GST_OBJECT (decoder)); - - free_properties(properties); - - JCL_free_cstring (env, _file, file); - return JNI_FALSE; + free_properties(properties); + return result; } + + g_signal_connect (decoder, "new-decoded-pad", G_CALLBACK (new_decoded_pad), + pipeline); + g_signal_connect (G_OBJECT (decoder), "element-added", + G_CALLBACK (element_added), properties); /* * we get the typefind from the decodebin to catch the additional properties @@ -412,58 +386,51 @@ Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer * now, we set the pipeline playing state to pause and traverse it * to get the info we need. */ - + res = gst_element_set_state (pipeline, GST_STATE_PAUSED); if (res == GST_STATE_CHANGE_FAILURE) { - JCL_free_cstring (env, _file, file); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (GST_OBJECT (pipeline)); free_properties(properties); - return JNI_FALSE; + return result; } - /* (GstClockTime) 300000000 ? */ res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); if (res != GST_STATE_CHANGE_SUCCESS) { - JCL_free_cstring (env, _file, file); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (GST_OBJECT (pipeline)); free_properties(properties); - return JNI_FALSE; + return result; } - result = JNI_FALSE; if (fill_info (decoder, properties)) { - result = set_strings (env, GstHeader, properties, header); + result = set_strings (env, properties, header); } - + /* free stuff */ - JCL_free_cstring (env, _file, file); gst_element_set_state (pipeline, GST_STATE_NULL); + + free_properties (properties); gst_object_unref (GST_OBJECT (pipeline)); - - free_properties (properties); - + return result; } -/* ***** END: NATIVE FUNCTIONS ***** */ -/* ***** PRIVATE FUNCTIONS IMPLEMENTATION ***** */ static gboolean typefind_callback(GstElement *typefind __attribute__ ((unused)), guint probability __attribute__ ((unused)), const GstCaps *caps, gpointer data) { - GstStructure *structure = NULL; + GstStructure *structure = NULL; AudioProperties *properties = NULL; const char *mpeg = NULL; @@ -494,14 +461,21 @@ static void new_decoded_pad (GstElement *decoder __attribute__ ((unused)), GstPad *pad, gboolean last __attribute__ ((unused)), - GstElement *pipeline) + gpointer data) { + GstElement *pipeline = NULL; GstElement *fakesink = NULL; GstPad *sinkpad = NULL; + pipeline = (GstElement *) data; + if (pipeline == NULL) + return; + fakesink = gst_element_factory_make ("fakesink", NULL); + if (fakesink == NULL) + return; + gst_bin_add (GST_BIN (pipeline), fakesink); - sinkpad = gst_element_get_pad (fakesink, "sink"); if (GST_PAD_LINK_FAILED (gst_pad_link (pad, sinkpad))) { @@ -514,8 +488,7 @@ new_decoded_pad (GstElement *decoder __attribute__ ((unused)), } static gboolean -set_strings (JNIEnv *env, const jclass GstHeader, - const AudioProperties *properties, jobject header) +set_strings (JNIEnv *env, const AudioProperties *properties, jobject header) { gboolean result = FALSE; @@ -525,34 +498,34 @@ set_strings (JNIEnv *env, const jclass GstHeader, */ /* now, map our properties to the java class */ - set_string (env, GstHeader, header, "mimetype", properties->mimetype); + set_string (env, header, mimetypeFID, properties->mimetype); - if (set_string (env, GstHeader, header, "endianness", - properties->endianness)) result = JNI_TRUE; + if (set_string (env, header, endiannessFID, properties->endianness)) + result = JNI_TRUE; - if (set_string (env, GstHeader, header, "channels", - properties->channels)) result = JNI_TRUE; + if (set_string (env, header, channelsFID, properties->channels)) + result = JNI_TRUE; - if (set_string (env, GstHeader, header, "rate", - properties->rate)) result = JNI_TRUE; + if (set_string (env, header, rateFID, properties->rate)) + result = JNI_TRUE; - if (set_string (env, GstHeader, header, "width", - properties->width)) result = JNI_TRUE; + if (set_string (env, header, widthFID, properties->width)) + result = JNI_TRUE; - if (set_string (env, GstHeader, header, "depth", - properties->depth)) result = JNI_TRUE; + if (set_string (env, header, depthFID, properties->depth)) + result = JNI_TRUE; - if (set_string (env, GstHeader, header, "isSigned", - properties->signess)) result = JNI_TRUE; + if (set_string (env, header, isSignedFID, properties->signess)) + result = JNI_TRUE; - if (set_string (env, GstHeader, header, "name", - properties->name)) result = JNI_TRUE; + if (set_string (env, header, nameFID, properties->name)) + result = JNI_TRUE; /* non primary properties */ - set_string (env, GstHeader, header, "layer", properties->layer); - set_string (env, GstHeader, header, "bitrate", properties->bitrate); - set_string (env, GstHeader, header, "framed", properties->framed); - set_string (env, GstHeader, header, "type", properties->type); + set_string (env, header, layerFID, properties->layer); + set_string (env, header, bitrateFID, properties->bitrate); + set_string (env, header, framedFID, properties->framed); + set_string (env, header, typeFID, properties->type); return result; } @@ -562,7 +535,7 @@ static gboolean fill_info (GstElement *decoder, AudioProperties *properties) GstIterator *it = NULL; gpointer data = NULL; gboolean result = FALSE; - + it = gst_element_iterate_src_pads (decoder); while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) { @@ -638,12 +611,15 @@ static gboolean fill_info (GstElement *decoder, AudioProperties *properties) gst_caps_unref (caps); gst_object_unref (pad); } - + return result; } -static void free_properties (AudioProperties *properties) +static void +free_properties (AudioProperties *properties __attribute__ ((unused))) { + /* FIXME this causes a segfault, a string not allocated by us? double free? */ + /* if (properties->name != NULL) g_free((gpointer) properties->name); if (properties->endianness != NULL) g_free((gpointer) properties->endianness); if (properties->channels != NULL) g_free((gpointer) properties->channels); @@ -655,6 +631,7 @@ static void free_properties (AudioProperties *properties) if (properties->framed != NULL) g_free((gpointer) properties->framed); if (properties != NULL) g_free ((gpointer) properties); + */ } static void reset_properties (AudioProperties *properties) @@ -730,38 +707,28 @@ static gchar *get_boolean_property (const GstStructure *structure, return result; } -static gboolean set_string (JNIEnv *env, const jclass GstHeader, - jobject header, - const char *field, +static gboolean set_string (JNIEnv *env, jobject header, jfieldID fieldID, const gchar *property) -{ - jfieldID _fid = NULL; +{ jstring property_string_field = NULL; - if (property == NULL || field == NULL || header == NULL || GstHeader == NULL) + if (property == NULL || header == NULL) { return JNI_FALSE; } - _fid = (*env)->GetFieldID(env, GstHeader, field, "Ljava/lang/String;"); - if (_fid == NULL) - { - return JNI_FALSE; /* failed to find the field */ - } - property_string_field = (*env)->NewStringUTF(env, property); if (property_string_field == NULL) { return JNI_FALSE; } - (*env)->SetObjectField(env, header, _fid, property_string_field); + (*env)->SetObjectField(env, header, fieldID, property_string_field); return JNI_TRUE; } -static void -element_added (GstBin *bin, GstElement *element, gpointer data) +static void element_added (GstBin *bin, GstElement *element, gpointer data) { GstElementFactory *factory; |