gstreamer_io_peer.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /* gstreamer_io_peer.c -- Implements native methods for class
  2. GStreamerNativePeer
  3. Copyright (C) 2007 Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <jni.h>
  35. #include <glib.h>
  36. #include <glib/gprintf.h>
  37. #include <gdk/gdk.h>
  38. #include <gst/gst.h>
  39. #include "jcl.h"
  40. #include "gst_peer.h"
  41. #include "gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer.h"
  42. #include "gst_classpath_src.h"
  43. #include "gst_input_stream.h"
  44. /* for caching */
  45. static jfieldID fileFID = NULL;
  46. static jfieldID pointerDataID = NULL;
  47. static jfieldID mimetypeFID = NULL;
  48. static jfieldID endiannessFID = NULL;
  49. static jfieldID channelsFID = NULL;
  50. static jfieldID rateFID = NULL;
  51. static jfieldID widthFID = NULL;
  52. static jfieldID depthFID = NULL;
  53. static jfieldID isSignedFID = NULL;
  54. static jfieldID nameFID = NULL;
  55. static jfieldID layerFID = NULL;
  56. static jfieldID bitrateFID = NULL;
  57. static jfieldID framedFID = NULL;
  58. static jfieldID typeFID = NULL;
  59. typedef struct _AudioProperties AudioProperties;
  60. struct _AudioProperties
  61. {
  62. /*
  63. * NOTE: descriptions of the properties are taken from:
  64. * http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/section-types-definitions.html#table-audio-types
  65. */
  66. /* decoder name */
  67. const char *name;
  68. /* audio endiannes */
  69. const char *endianness;
  70. /* header size */
  71. const char *header_size;
  72. /* mime */
  73. const char *mimetype;
  74. /* The sample rate of the data, in samples (per channel) per second */
  75. const char *samplerate;
  76. /* The number of channels of audio data */
  77. const char *channels;
  78. const char *layer;
  79. const char *bitrate;
  80. const char *framed;
  81. /*
  82. * Defines if the values of the integer samples are signed or not.
  83. * Signed samples use one bit to indicate sign (negative or positive)
  84. * of the value. Unsigned samples are always positive.
  85. */
  86. const char *signess;
  87. /* */
  88. const char *rate;
  89. /* Number of bits allocated per sample. */
  90. const char *width;
  91. /*
  92. * The number of bits used per sample.
  93. * If the depth is less than the width, the low bits are assumed to be the
  94. * ones used. For example, a width of 32 and a depth of 24 means that
  95. * each sample is stored in a 32 bit word, but only the low
  96. * 24 bits are actually used.
  97. */
  98. const char *depth;
  99. /*
  100. * This is set in the case of the mpeg files.
  101. */
  102. const char *type;
  103. gboolean done;
  104. };
  105. /* ***** PRIVATE FUNCTIONS DECLARATION ***** */
  106. static gboolean
  107. set_strings (JNIEnv *env, const AudioProperties *properties, jobject header);
  108. static gboolean
  109. typefind_callback(GstElement *typefind, guint probability, const GstCaps *caps,
  110. gpointer data);
  111. static void
  112. element_added (GstBin *bin, GstElement *element, gpointer data);
  113. static void
  114. new_decoded_pad (GstElement *decoder, GstPad *pad,
  115. gboolean last, gpointer data);
  116. static gboolean
  117. fill_info (GstElement *decoder, AudioProperties *properties);
  118. static gchar *
  119. get_string_property (const GstStructure *structure, const gchar *property);
  120. static gchar *
  121. get_boolean_property (const GstStructure *structure, const gchar *property);
  122. static gboolean
  123. set_string (JNIEnv *env, jobject header, jfieldID fieldID,
  124. const gchar *property);
  125. static void
  126. free_properties (AudioProperties *properties);
  127. static void
  128. reset_properties (AudioProperties *properties);
  129. static jboolean process_audio (GstElement *source, JNIEnv *env, jobject header);
  130. /* ***** END: PRIVATE FUNCTIONS DECLARATION ***** */
  131. /* ***** NATIVE FUNCTIONS ***** */
  132. JNIEXPORT void JNICALL
  133. Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_init_1id_1cache
  134. (JNIEnv *env, jclass clazz __attribute__ ((unused)))
  135. {
  136. jclass pointerClass = NULL;
  137. jclass GstHeader = NULL;
  138. GstHeader = JCL_FindClass(env, "gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer$GstHeader");
  139. fileFID = (*env)->GetFieldID(env, GstHeader, "file", "Ljava/lang/String;");
  140. mimetypeFID = (*env)->GetFieldID(env, GstHeader, "mimetype",
  141. "Ljava/lang/String;");
  142. endiannessFID = (*env)->GetFieldID(env, GstHeader, "endianness",
  143. "Ljava/lang/String;");
  144. channelsFID = (*env)->GetFieldID(env, GstHeader, "channels",
  145. "Ljava/lang/String;");
  146. rateFID = (*env)->GetFieldID(env, GstHeader, "rate", "Ljava/lang/String;");
  147. widthFID = (*env)->GetFieldID(env, GstHeader, "width", "Ljava/lang/String;");
  148. depthFID = (*env)->GetFieldID(env, GstHeader, "depth", "Ljava/lang/String;");
  149. isSignedFID = (*env)->GetFieldID(env, GstHeader, "isSigned",
  150. "Ljava/lang/String;");
  151. nameFID = (*env)->GetFieldID(env, GstHeader, "name", "Ljava/lang/String;");
  152. layerFID = (*env)->GetFieldID(env, GstHeader, "layer", "Ljava/lang/String;");
  153. bitrateFID = (*env)->GetFieldID(env, GstHeader, "bitrate",
  154. "Ljava/lang/String;");
  155. framedFID = (*env)->GetFieldID(env, GstHeader, "framed",
  156. "Ljava/lang/String;");
  157. typeFID = (*env)->GetFieldID(env, GstHeader, "type", "Ljava/lang/String;");
  158. #if SIZEOF_VOID_P == 8
  159. pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer64");
  160. if (pointerClass != NULL)
  161. {
  162. pointerDataID = (*env)->GetFieldID (env, pointerClass, "data", "J");
  163. }
  164. #else
  165. # if SIZEOF_VOID_P == 4
  166. pointerClass = JCL_FindClass (env, "gnu/classpath/Pointer32");
  167. if (pointerClass != NULL)
  168. {
  169. pointerDataID = (*env)->GetFieldID(env, pointerClass, "data", "I");
  170. }
  171. # else
  172. # error "Pointer size is not supported."
  173. # endif /* SIZEOF_VOID_P == 4 */
  174. #endif /* SIZEOF_VOID_P == 8 */
  175. }
  176. JNIEXPORT jboolean JNICALL
  177. Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer_1get_1audio_1format_1stream
  178. (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject header,
  179. jobject pointer)
  180. {
  181. GstInputStream *istream = NULL;
  182. GstElement *source = NULL;
  183. gboolean result = JNI_FALSE;
  184. if (header == NULL)
  185. return JNI_FALSE;
  186. if (pointer == NULL)
  187. return JNI_FALSE;
  188. gst_init (NULL, NULL);
  189. istream = (GstInputStream *) get_object_from_pointer (env, pointer,
  190. pointerDataID);
  191. if (istream == NULL)
  192. return JNI_FALSE;
  193. /* init gstreamer */
  194. gst_init (NULL, NULL);
  195. /* SOURCE */
  196. source = gst_element_factory_make ("classpathsrc", "source");
  197. if (source == NULL)
  198. {
  199. g_warning ("unable to create a source");
  200. return JNI_FALSE;
  201. }
  202. g_object_set (G_OBJECT (source), GST_CLASSPATH_SRC_ISTREAM, istream, NULL);
  203. result = process_audio (source, env, header);
  204. return result;
  205. }
  206. JNIEXPORT jboolean JNICALL
  207. Java_gnu_javax_sound_sampled_gstreamer_io_GstAudioFileReaderNativePeer_gstreamer_1get_1audio_1format_1file
  208. (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject header)
  209. {
  210. /* source file */
  211. const char *file = NULL;
  212. /* GStreamer elements */
  213. GstElement *source = NULL;
  214. jboolean result = JNI_FALSE;
  215. /* java fields */
  216. jstring _file = NULL;
  217. _file = (*env)->GetObjectField(env, header, fileFID);
  218. file = JCL_jstring_to_cstring (env, _file);
  219. if (file == NULL)
  220. {
  221. return JNI_FALSE;
  222. }
  223. gst_init (NULL, NULL);
  224. /* create the source element, will be used to read the file */
  225. source = gst_element_factory_make ("filesrc", "source");
  226. if (source == NULL)
  227. {
  228. JCL_free_cstring (env, _file, file);
  229. return JNI_FALSE;
  230. }
  231. /* set the file name */
  232. g_object_set (G_OBJECT (source), "location", file, NULL);
  233. result = process_audio (source, env, header);
  234. /* free stuff */
  235. JCL_free_cstring (env, _file, file);
  236. return result;
  237. }
  238. /* ***** END: NATIVE FUNCTIONS ***** */
  239. /* ***** PRIVATE FUNCTIONS IMPLEMENTATION ***** */
  240. static jboolean process_audio (GstElement *source, JNIEnv *env, jobject header)
  241. {
  242. /* will contain the properties we need to put into the given GstHeader */
  243. AudioProperties *properties = NULL;
  244. /* GStreamer elements */
  245. GstElement *pipeline = NULL;
  246. GstElement *decoder = NULL;
  247. GstElement *typefind = NULL;
  248. GstStateChangeReturn res;
  249. jboolean result = JNI_FALSE;
  250. properties = (AudioProperties *) g_malloc0 (sizeof (AudioProperties));
  251. if (properties == NULL)
  252. {
  253. return result;
  254. }
  255. reset_properties(properties);
  256. /*
  257. * create the decoder element, this will decode the stream and retrieve
  258. * its properties.
  259. * We connect a signal to this element, to be informed when it is done
  260. * in decoding the stream and to get the needed informations about the
  261. * audio file.
  262. */
  263. decoder = gst_element_factory_make ("decodebin", "decoder");
  264. if (decoder == NULL)
  265. {
  266. free_properties(properties);
  267. return result;
  268. }
  269. /* now, we create a pipeline and fill it with the other elements */
  270. pipeline = gst_pipeline_new ("pipeline");
  271. if (pipeline == NULL)
  272. {
  273. gst_object_unref (GST_OBJECT (decoder));
  274. free_properties(properties);
  275. return result;
  276. }
  277. g_signal_connect (decoder, "new-decoded-pad", G_CALLBACK (new_decoded_pad),
  278. pipeline);
  279. g_signal_connect (G_OBJECT (decoder), "element-added",
  280. G_CALLBACK (element_added), properties);
  281. /*
  282. * we get the typefind from the decodebin to catch the additional properties
  283. * that the decodebin does not expose to us
  284. */
  285. typefind = gst_bin_get_by_name (GST_BIN (decoder), "typefind");
  286. if (typefind != NULL)
  287. {
  288. /*
  289. * NOTE: the above is not a typo, we can live without the typefind,
  290. * just, our stream detection will not be as accurate as we would.
  291. * Anyway, if this fails, there is some problem, probabily a memory
  292. * error.
  293. */
  294. g_signal_connect (G_OBJECT (typefind), "have-type",
  295. G_CALLBACK (typefind_callback), properties);
  296. }
  297. gst_bin_add_many (GST_BIN (pipeline), source, decoder, NULL);
  298. gst_element_link (source, decoder);
  299. /*
  300. * now, we set the pipeline playing state to pause and traverse it
  301. * to get the info we need.
  302. */
  303. res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
  304. if (res == GST_STATE_CHANGE_FAILURE)
  305. {
  306. gst_element_set_state (pipeline, GST_STATE_NULL);
  307. gst_object_unref (GST_OBJECT (pipeline));
  308. free_properties(properties);
  309. return result;
  310. }
  311. res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
  312. if (res != GST_STATE_CHANGE_SUCCESS)
  313. {
  314. gst_element_set_state (pipeline, GST_STATE_NULL);
  315. gst_object_unref (GST_OBJECT (pipeline));
  316. free_properties(properties);
  317. return result;
  318. }
  319. if (fill_info (decoder, properties))
  320. {
  321. result = set_strings (env, properties, header);
  322. }
  323. /* free stuff */
  324. gst_element_set_state (pipeline, GST_STATE_NULL);
  325. free_properties (properties);
  326. gst_object_unref (GST_OBJECT (pipeline));
  327. return result;
  328. }
  329. static gboolean typefind_callback(GstElement *typefind __attribute__ ((unused)),
  330. guint probability __attribute__ ((unused)),
  331. const GstCaps *caps,
  332. gpointer data)
  333. {
  334. GstStructure *structure = NULL;
  335. AudioProperties *properties = NULL;
  336. const char *mpeg = NULL;
  337. properties = (AudioProperties *) data;
  338. structure = gst_caps_get_structure (caps, 0);
  339. /* MIMETYPE */
  340. properties->mimetype = gst_structure_get_name (structure);
  341. mpeg = get_string_property(structure, "mpegversion");
  342. if (mpeg != NULL)
  343. {
  344. properties->layer = get_string_property(structure, "layer");
  345. properties->type = (gchar *) g_malloc0 (_GST_MALLOC_SIZE_);
  346. g_snprintf ((gpointer) properties->type, _GST_MALLOC_SIZE_,
  347. "MPEG%sV%s", mpeg,
  348. properties->layer);
  349. g_free ((gpointer) mpeg);
  350. }
  351. return TRUE;
  352. }
  353. static void
  354. new_decoded_pad (GstElement *decoder __attribute__ ((unused)),
  355. GstPad *pad,
  356. gboolean last __attribute__ ((unused)),
  357. gpointer data)
  358. {
  359. GstElement *pipeline = NULL;
  360. GstElement *fakesink = NULL;
  361. GstPad *sinkpad = NULL;
  362. pipeline = (GstElement *) data;
  363. if (pipeline == NULL)
  364. return;
  365. fakesink = gst_element_factory_make ("fakesink", NULL);
  366. if (fakesink == NULL)
  367. return;
  368. gst_bin_add (GST_BIN (pipeline), fakesink);
  369. sinkpad = gst_element_get_pad (fakesink, "sink");
  370. if (GST_PAD_LINK_FAILED (gst_pad_link (pad, sinkpad)))
  371. {
  372. gst_bin_remove (GST_BIN (pipeline), fakesink);
  373. }
  374. else
  375. {
  376. gst_element_set_state (fakesink, GST_STATE_PAUSED);
  377. }
  378. }
  379. static gboolean
  380. set_strings (JNIEnv *env, const AudioProperties *properties, jobject header)
  381. {
  382. gboolean result = FALSE;
  383. /*
  384. * we only need at least one of them to be sure we can handle this
  385. * kind of audio data.
  386. */
  387. /* now, map our properties to the java class */
  388. set_string (env, header, mimetypeFID, properties->mimetype);
  389. if (set_string (env, header, endiannessFID, properties->endianness))
  390. result = JNI_TRUE;
  391. if (set_string (env, header, channelsFID, properties->channels))
  392. result = JNI_TRUE;
  393. if (set_string (env, header, rateFID, properties->rate))
  394. result = JNI_TRUE;
  395. if (set_string (env, header, widthFID, properties->width))
  396. result = JNI_TRUE;
  397. if (set_string (env, header, depthFID, properties->depth))
  398. result = JNI_TRUE;
  399. if (set_string (env, header, isSignedFID, properties->signess))
  400. result = JNI_TRUE;
  401. if (set_string (env, header, nameFID, properties->name))
  402. result = JNI_TRUE;
  403. /* non primary properties */
  404. set_string (env, header, layerFID, properties->layer);
  405. set_string (env, header, bitrateFID, properties->bitrate);
  406. set_string (env, header, framedFID, properties->framed);
  407. set_string (env, header, typeFID, properties->type);
  408. return result;
  409. }
  410. static gboolean fill_info (GstElement *decoder, AudioProperties *properties)
  411. {
  412. GstIterator *it = NULL;
  413. gpointer data = NULL;
  414. gboolean result = FALSE;
  415. it = gst_element_iterate_src_pads (decoder);
  416. while (gst_iterator_next (it, &data) == GST_ITERATOR_OK)
  417. {
  418. GstPad *pad = GST_PAD (data);
  419. GstCaps *caps;
  420. GstStructure *structure;
  421. const gchar *caps_string = NULL;
  422. caps = gst_pad_get_caps (pad);
  423. caps_string = gst_caps_to_string (caps);
  424. if (g_str_has_prefix (caps_string, "video"))
  425. {
  426. /* no video support, this is an audio library */
  427. g_free ((gpointer) caps_string);
  428. gst_caps_unref (caps);
  429. gst_object_unref (pad);
  430. continue;
  431. }
  432. g_free ((gpointer) caps_string);
  433. structure = gst_caps_get_structure (GST_CAPS (caps), 0);
  434. /* fill the properties we need */
  435. /* SIGNESS */
  436. properties->signess = get_boolean_property(structure, "signed");
  437. if (properties->signess != NULL)
  438. {
  439. result = TRUE;
  440. }
  441. /* ENDIANNESS */
  442. properties->endianness = get_string_property(structure, "endianness");
  443. if (properties->endianness != NULL)
  444. {
  445. result = TRUE;
  446. }
  447. /* CHANNELS */
  448. properties->channels = get_string_property(structure, "channels");
  449. if (properties->channels != NULL)
  450. {
  451. result = TRUE;
  452. }
  453. /* RATE */
  454. properties->rate = get_string_property(structure, "rate");
  455. if (properties->rate != NULL)
  456. {
  457. result = TRUE;
  458. }
  459. /* WIDTH */
  460. properties->width = get_string_property(structure, "width");
  461. if (properties->width != NULL)
  462. {
  463. result = TRUE;
  464. }
  465. /* DEPTH */
  466. properties->depth = get_string_property(structure, "depth");
  467. if (properties->depth != NULL)
  468. {
  469. result = TRUE;
  470. }
  471. gst_caps_unref (caps);
  472. gst_object_unref (pad);
  473. }
  474. return result;
  475. }
  476. static void
  477. free_properties (AudioProperties *properties __attribute__ ((unused)))
  478. {
  479. /* FIXME this causes a segfault, a string not allocated by us? double free? */
  480. /*
  481. if (properties->name != NULL) g_free((gpointer) properties->name);
  482. if (properties->endianness != NULL) g_free((gpointer) properties->endianness);
  483. if (properties->channels != NULL) g_free((gpointer) properties->channels);
  484. if (properties->rate != NULL) g_free((gpointer) properties->rate);
  485. if (properties->width != NULL) g_free((gpointer) properties->width);
  486. if (properties->depth != NULL) g_free((gpointer) properties->depth);
  487. if (properties->layer != NULL) g_free((gpointer) properties->layer);
  488. if (properties->bitrate != NULL) g_free((gpointer) properties->bitrate);
  489. if (properties->framed != NULL) g_free((gpointer) properties->framed);
  490. if (properties != NULL) g_free ((gpointer) properties);
  491. */
  492. }
  493. static void reset_properties (AudioProperties *properties)
  494. {
  495. properties->done = FALSE;
  496. properties->signess = FALSE;
  497. properties->name = NULL;
  498. properties->endianness = NULL;
  499. properties->channels = NULL;
  500. properties->rate = NULL;
  501. properties->width = NULL;
  502. properties->depth = NULL;
  503. properties->layer = NULL;
  504. properties->bitrate = NULL;
  505. properties->framed = NULL;
  506. }
  507. static gchar *get_string_property (const GstStructure *structure,
  508. const gchar *property)
  509. {
  510. int props = 0;
  511. gchar *result = NULL;
  512. if (property == NULL)
  513. {
  514. return NULL;
  515. }
  516. /* we don't need more */
  517. result = (gchar *) g_malloc0 (_GST_MALLOC_SIZE_);
  518. if (result == NULL)
  519. {
  520. /* huston, we have a problem here... */
  521. return NULL;
  522. }
  523. if (gst_structure_get_int (structure, property, &props))
  524. {
  525. g_snprintf (result, _GST_MALLOC_SIZE_, "%d", props);
  526. }
  527. else
  528. {
  529. g_free ((gpointer) result);
  530. return NULL;
  531. }
  532. return result;
  533. }
  534. static gchar *get_boolean_property (const GstStructure *structure,
  535. const gchar *property)
  536. {
  537. gchar *result = NULL;
  538. gboolean props = FALSE;
  539. result = (gchar *) g_malloc0 (_GST_MALLOC_SIZE_);
  540. if (result == NULL)
  541. {
  542. /* huston, we have a problem here... */
  543. return NULL;
  544. }
  545. if (gst_structure_get_boolean (structure, property, &props))
  546. {
  547. g_snprintf (result, _GST_MALLOC_SIZE_, "%s", (props ? "true" : "false" ));
  548. }
  549. else
  550. {
  551. g_free ((gpointer) result);
  552. return NULL;
  553. }
  554. return result;
  555. }
  556. static gboolean set_string (JNIEnv *env, jobject header, jfieldID fieldID,
  557. const gchar *property)
  558. {
  559. jstring property_string_field = NULL;
  560. if (property == NULL || header == NULL)
  561. {
  562. return JNI_FALSE;
  563. }
  564. property_string_field = (*env)->NewStringUTF(env, property);
  565. if (property_string_field == NULL)
  566. {
  567. return JNI_FALSE;
  568. }
  569. (*env)->SetObjectField(env, header, fieldID, property_string_field);
  570. return JNI_TRUE;
  571. }
  572. static void element_added (GstBin *bin, GstElement *element, gpointer data)
  573. {
  574. GstElementFactory *factory;
  575. factory = gst_element_get_factory (element);
  576. ((AudioProperties *) data)->name = gst_element_factory_get_longname (factory);
  577. }
  578. /* ***** END: PRIVATE FUNCTIONS IMPLEMENTATION ***** */