1 /*gst_native_pipeline.c - Header file for the GstClasspathPlugin
2 Copyright (C) 2007 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
44 #include <sys/types.h>
52 #endif /* HAVE_FCNTL_H */
54 #if defined(HAVE_SYS_IOCTL_H)
55 #define BSD_COMP /* Get FIONREAD on Solaris2 */
56 #include <sys/ioctl.h>
58 #if defined(HAVE_SYS_FILIO_H) /* Get FIONREAD on Solaris 2.5 */
59 #include <sys/filio.h>
70 #include "gnu_javax_sound_sampled_gstreamer_lines_GstPipeline.h"
71 #include "gst_native_pipeline.h"
73 static jmethodID pointerConstructorMID
= NULL
;
75 static jfieldID pipelineFID
= NULL
;
76 static jfieldID pointerDataFID
= NULL
;
77 static jfieldID nameFID
= NULL
;
78 static jfieldID capacityFID
= NULL
;
81 * Needed to compute the size of the data still available for processing in the
82 * pipeline. We give a default here but this will be overwritten by the
85 static long GST_DETECTED_PIPE_CAPACITY
= 65536;
88 * Note: the Java code uses enum classes, these are not mapped into constants
89 * by the javah tool, changes to these values should be reflected in the Java
100 * Defined as constants in the Java code, hence mapped by javah.
104 READ
= gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_READ
,
105 WRITE
= gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_WRITE
108 struct _GstNativePipelinePrivate
111 jclass GstPipelineClass
;
114 jobject jni_pipeline
;
119 GstElement
*pipeline
;
122 /* ************************************************************************** */
124 static void gst_native_pipeline_clean (GstNativePipeline *self);*/
125 static char *create_name (void);
126 static void init_pointer_IDs (JNIEnv
* env
);
127 static jint
get_free_space (int fd
);
128 static void detect_pipe_max (void);
130 /* ************************************************************************** */
134 JNIEXPORT
void JNICALL
135 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_init_1id_1cache
136 (JNIEnv
*env
, jclass clazz
)
138 pipelineFID
= (*env
)->GetFieldID (env
, clazz
, "pipeline",
139 "Lgnu/classpath/Pointer;");
140 nameFID
= (*env
)->GetFieldID (env
, clazz
, "name", "Ljava/lang/String;");
141 capacityFID
= (*env
)->GetFieldID (env
, clazz
, "capacity", "J");
143 init_pointer_IDs (env
);
146 JNIEXPORT
void JNICALL
147 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_init_1instance
148 (JNIEnv
*env
, jobject pipeline
)
150 GstNativePipeline
*_pipeline
= NULL
;
152 jclass localGstPipelineClass
= NULL
;
153 jclass localPointerClass
= NULL
;
154 jobject _pointer
= NULL
;
157 (GstNativePipeline
*) JCL_malloc (env
, sizeof (GstNativePipeline
));
158 if (_pipeline
== NULL
)
161 _pipeline
->priv
= (GstNativePipelinePrivate
*)
162 JCL_malloc (env
, sizeof (GstNativePipelinePrivate
));
163 if (_pipeline
->priv
== NULL
)
165 JCL_free (env
, _pipeline
);
169 #if SIZEOF_VOID_P == 8
170 localPointerClass
= JCL_FindClass (env
, "gnu/classpath/Pointer64");
172 # if SIZEOF_VOID_P == 4
173 localPointerClass
= JCL_FindClass (env
, "gnu/classpath/Pointer32");
175 # error "Pointer size is not supported."
176 # endif /* SIZEOF_VOID_P == 4 */
177 #endif /* SIZEOF_VOID_P == 8 */
179 localGstPipelineClass
= (*env
)->GetObjectClass(env
, pipeline
);
180 if (localGstPipelineClass
== NULL
|| localGstPipelineClass
== NULL
)
182 JCL_free (env
, _pipeline
->priv
);
183 JCL_free (env
, _pipeline
);
184 JCL_ThrowException (env
, "java/lang/InternalError",
185 "Class Initialization failed.");
189 GST_DETECTED_PIPE_CAPACITY
= (long) (*env
)->GetLongField(env
, pipeline
,
192 /* fill the object */
193 (*env
)->GetJavaVM(env
, &_pipeline
->priv
->vm
);
194 _pipeline
->priv
->jni_pipeline
= (*env
)->NewGlobalRef(env
, pipeline
);
195 _pipeline
->priv
->GstPipelineClass
=
196 (*env
)->NewGlobalRef(env
, localGstPipelineClass
);
197 _pipeline
->priv
->PointerClass
= (*env
)->NewGlobalRef(env
, localPointerClass
);
198 _pipeline
->priv
->pipeline
= NULL
;
200 _pointer
= (*env
)->GetObjectField(env
, pipeline
, pipelineFID
);
202 if (_pointer
== NULL
)
204 #if SIZEOF_VOID_P == 8
205 _pointer
= (*env
)->NewObject(env
, _pipeline
->priv
->PointerClass
,
206 pointerConstructorMID
, (jlong
) _pipeline
);
208 _pointer
= (*env
)->NewObject(env
, _pipeline
->priv
->PointerClass
,
209 pointerConstructorMID
, (jint
) _pipeline
);
214 #if SIZEOF_VOID_P == 8
215 (*env
)->SetLongField(env
, pipeline
, pipelineFID
, (jlong
) _pipeline
);
217 (*env
)->SetIntField(env
, pipeline
, pipelineFID
, (jint
) _pipeline
);
221 /* store back our pointer into the calling class */
222 (*env
)->SetObjectField(env
, pipeline
, pipelineFID
, _pointer
);
225 JNIEXPORT jboolean JNICALL
226 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_set_1state
227 (JNIEnv
*env
, jclass clazz
, jobject pointer
, jint state
)
229 GstNativePipeline
*jpipeline
= NULL
;
230 jboolean result
= JNI_FALSE
;
234 JCL_ThrowException (env
, "javax/sound/sampled/LineUnavailableException",
235 "Can't change pipeline state: " \
236 "pipeline not initialized");
240 jpipeline
= (GstNativePipeline
*) get_object_from_pointer (env
, pointer
,
242 if (jpipeline
== NULL
)
248 gst_element_set_state(GST_ELEMENT(jpipeline
->priv
->pipeline
),
254 gst_element_set_state(GST_ELEMENT(jpipeline
->priv
->pipeline
),
260 #ifndef WITHOUT_FILESYSTEM
261 /* clean the pipeline and kill named pipe */
262 if (jpipeline
->priv
->name
)
264 cpio_removeFile (jpipeline
->priv
->name
);
265 g_free (jpipeline
->priv
->name
);
266 jpipeline
->priv
->name
= NULL
;
268 #endif /* WITHOUT_FILESYSTEM */
270 if (jpipeline
->priv
->pipeline
!= NULL
)
271 gst_object_unref (GST_OBJECT(jpipeline
->priv
->pipeline
));
284 JNIEXPORT
void JNICALL
285 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_open_1native_1pipe
286 (JNIEnv
*env
, jclass clazz
, jobject pointer
, jint mode
)
288 GstNativePipeline
*jpipeline
= NULL
;
290 jpipeline
= (GstNativePipeline
*) get_object_from_pointer (env
, pointer
,
295 jpipeline
->priv
->fd
=
296 open (jpipeline
->priv
->name
, O_RDONLY
| O_NONBLOCK
);
300 /* TODO: no-op currently */
305 JNIEXPORT
void JNICALL
306 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_close_1native_1pipe
307 (JNIEnv
*env
, jclass clazz
, jobject pointer
)
309 #ifndef WITHOUT_FILESYSTEM
310 GstNativePipeline
*jpipeline
= NULL
;
311 jpipeline
= (GstNativePipeline
*) get_object_from_pointer (env
, pointer
,
313 /* kill the named pipe */
314 if (jpipeline
->priv
->name
)
316 cpio_removeFile (jpipeline
->priv
->name
);
317 g_free (jpipeline
->priv
->name
);
318 jpipeline
->priv
->name
= NULL
;
320 #endif /* WITHOUT_FILESYSTEM */
323 JNIEXPORT jboolean JNICALL
324 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_create_1named_1pipe
325 (JNIEnv
*env
, jobject GstPipeline
, jobject pointer
)
327 #ifndef WITHOUT_FILESYSTEM
329 * We get a temp name for the named pipe, create the named pipe and then
330 * set the relative field in the java class.
332 GstNativePipeline
*jpipeline
= NULL
;
333 jstring
*name
= NULL
;
335 jpipeline
= (GstNativePipeline
*) get_object_from_pointer (env
, pointer
,
337 if (jpipeline
== NULL
)
340 jpipeline
->priv
->name
= create_name ();
341 if (jpipeline
->priv
->name
== NULL
)
344 if (mkfifo (jpipeline
->priv
->name
, 0600) < 0)
346 if (jpipeline
->priv
->name
!= NULL
)
347 free (jpipeline
->priv
->name
);
351 /* now set the String field */
352 name
= (*env
)->NewStringUTF(env
, jpipeline
->priv
->name
);
355 cpio_removeFile (jpipeline
->priv
->name
);
356 if (jpipeline
->priv
->name
!= NULL
)
357 free (jpipeline
->priv
->name
);
362 (*env
)->SetObjectField(env
, GstPipeline
, nameFID
, name
);
366 #else /* not WITHOUT_FILESYSTEM */
368 #endif /* not WITHOUT_FILESYSTEM */
371 JNIEXPORT jint JNICALL
372 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_available
373 (JNIEnv
*env
, jclass clazz
, jobject pointer
, jint mode
)
377 #ifndef WITHOUT_FILESYSTEM
379 GstNativePipeline
*jpipeline
= NULL
;
380 jpipeline
= (GstNativePipeline
*) get_object_from_pointer (env
, pointer
,
385 result
= get_free_space (jpipeline
->priv
->fd
);
389 # if defined (FIONREAD)
390 if (ioctl (jpipeline
->priv
->fd
, FIONREAD
, &result
) == -1)
391 g_warning("IMPLEMENT ME: ioctl failed");
393 # else /* not defined (FIONREAD) */
394 g_warning("IMPLEMENT ME: !defined (FIONREAD");
395 # endif /* defined (FIONREAD) */
397 } /* if (mode == READ) */
399 #endif /* not WITHOUT_FILESYSTEM */
404 JNIEXPORT jlong JNICALL
405 Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_detect_1pipe_1size
406 (JNIEnv
*env
, jobject GstPipeline
)
410 return GST_DETECTED_PIPE_CAPACITY
;
413 /* exported library functions */
415 static void gst_native_pipeline_clean (GstNativePipeline *self)
419 env = gst_get_jenv (self->priv->vm);
421 (*env)->DeleteGlobalRef (env, self->priv->jni_pipeline);
422 (*env)->DeleteGlobalRef (env, self->priv->GstPipelineClass);
423 (*env)->DeleteGlobalRef (env, self->priv->PointerClass);
425 if (self->priv->pipeline != NULL)
426 gst_object_unref (GST_OBJECT (self->priv->pipeline));
428 if (self->priv->name)
430 cpio_removeFile (self->priv->name);
431 g_free (self->priv->name);
432 self->priv->name = NULL;
435 JCL_free (env, self->priv);
436 JCL_free (env, self);
439 void gst_native_pipeline_set_pipeline (GstNativePipeline
*self
,
440 GstElement
*pipeline
)
442 if (self
->priv
->pipeline
!= NULL
)
443 gst_object_unref (GST_OBJECT (self
->priv
->pipeline
));
445 self
->priv
->pipeline
= pipeline
;
448 GstElement
*gst_native_pipeline_get_pipeline (GstNativePipeline
*self
)
450 return self
->priv
->pipeline
;
453 char *gst_native_pipeline_get_pipeline_name (GstNativePipeline
*self
)
455 return self
->priv
->name
;
458 int gst_native_pipeline_get_pipeline_fd (GstNativePipeline
*self
)
460 return self
->priv
->fd
;
463 /* private functions */
465 static void init_pointer_IDs (JNIEnv
* env
)
467 jclass PointerClass
= NULL
;
469 #if SIZEOF_VOID_P == 8
470 PointerClass
= JCL_FindClass (env
, "gnu/classpath/Pointer64");
471 if (PointerClass
!= NULL
)
473 pointerDataFID
= (*env
)->GetFieldID (env
, PointerClass
, "data", "J");
474 pointerConstructorMID
= (*env
)->GetMethodID (env
, PointerClass
, "<init>",
478 # if SIZEOF_VOID_P == 4
479 PointerClass
= JCL_FindClass (env
, "gnu/classpath/Pointer32");
480 if (PointerClass
!= NULL
)
482 pointerDataFID
= (*env
)->GetFieldID(env
, PointerClass
, "data", "I");
483 pointerConstructorMID
= (*env
)->GetMethodID(env
, PointerClass
,
487 # error "Pointer size is not supported."
488 # endif /* SIZEOF_VOID_P == 4 */
489 #endif /* SIZEOF_VOID_P == 8 */
492 static jint
get_free_space (int fd
)
496 #if defined (FIONSPACE)
498 if (ioctl (fd
, FIONSPACE
, &result
) == -1)
500 g_warning("IMPLEMENT ME: ioctl failed");
503 #elif defined (FIONREAD)
505 if (ioctl (fd
, FIONREAD
, &result
) == -1)
507 g_warning("IMPLEMENT ME: ioctl failed");
510 result
= GST_DETECTED_PIPE_CAPACITY
- result
;
513 g_warning("IMPLEMENT ME!!! - !defined (FIONSPACE), !defined (FIONREAD");
520 static char *create_name (void)
525 buffer
= (char *) g_malloc0 (_GST_MALLOC_SIZE_
);
528 /* huston, we have a problem... */
532 tmp
= tempnam (NULL
, _GST_PIPELINE_PREFIX_
);
539 g_snprintf (buffer
, _GST_MALLOC_SIZE_
, "%s%s", tmp
, _GST_PIPELINE_SUFFIX_
);
545 static void detect_pipe_max (void)
550 /* can be anything! */
551 char *character
= "a";
554 gboolean available
= TRUE
;
558 pipe
= create_name ();
561 g_warning ("can't create test pipe name");
565 if (mkfifo (pipe
, 0600) < 0)
567 g_warning ("unable to create test pipe...");
573 /* open both end of the pipe */
574 read_fd
= open (pipe
, O_RDONLY
| O_NONBLOCK
);
577 cpio_removeFile (pipe
);
583 write_fd
= open (pipe
, O_WRONLY
| O_NONBLOCK
);
586 cpio_closeFile (write_fd
);
587 cpio_removeFile (pipe
);
597 cpio_write (write_fd
, character
, 1, &w
);
604 GST_DETECTED_PIPE_CAPACITY
= wrote
;
606 cpio_closeFile (write_fd
);
607 cpio_closeFile (read_fd
);
608 cpio_removeFile (pipe
);