1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
GNU Classpath GStreamer Sound Backend README - Last updated: October 8, 2007
(for release 0.96)
* Introduction
From 0.96, GNU Classpath has a preliminary backend implementation for the
Java Sound API based on the GStreamer framework.
The backend is considered unstable and is currently disabled by default. To
enable it, you should pass "--enable-gstreamer-peer" to configure.
We suggest that you leave this option set to the default on production systems,
but enable it for testing. The backend has only been tested successfully on Linux
i386 and amd64. There are known issues on powerpc64 (see bug:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33701)
The peer supports any kind of stream you have a gstreamer plugin for (modulo
the eventual bugs of course!!) and no special steps are needed to enable them.
The only requirement is a working installation of at least gstreamer,
gstreamer-base and gstreamer-plugins-base, all with a version number of at least
0.10.10.
The minor version number could eventually be lowered but the peer was
developed on a Fedora 7 machine with GStreamer 0.10.10, so they may rely on
new functions introduced during the GStreamer 0.10 timeline. GStreamer 0.8
will most likely not work due to API changes, but porting to the old system
should not be too hard, as the backend only uses a small subset of all the
API.
Currently, most methods in the backend are missings or are just stubbed.
The lack of event handling routines especially prevents this backend being
useful for anything other than simple examples.
We have included in the example directory a simple implementation of an audio
player. To run the example just type on the command line:
$ java -cp examples/examples.zip \
gnu.classpath.examples.sound.AudioPlayerSample audio_file
Where "java" is a GNU Classpath based VM and audio_file can be any type of
audio file that can be read by your GStreamer installation (e.g. ogg and wav).
* Implementation details
Currently the backend relies on filesystem named pipes to pass data from the
java layer to the native gstreamer layer. This is because GStreamer is heavily
multi-threaded; reading requests are asynchronous and performed by the
framework. While it's possible to control this flow, we have found through
experimentation that the best performance occurs when the framework itself handles
all the buffering, reading and streaming of audio data.
The file detection routines instead read directly from an InputStream with a
special GStreamer plugin. This will change in the next few releases to also use
filesystem named pipes as a more reliable way to pass data from one side of
the peer to the other as we have found that the current process of reading from a
java InputStream has a few drawbacks. For example, sometimes data is not handled
correctly, or even introduces the risk of deadlocks (see below).
* Know Bugs and Limitations
* Not all the methods described by the API are implemented.
* The peer is not currently tested on all the architectures.
* There is a bug in the file detection code (native code) that deadlocks the
application. This is usually triggered when you obtain both an
AudioInputStream and AudioFileFormat from the same file, in (bad) code
like the following:
AudioInputStream is = AudioSystem.getAudioInputStream(new File(file));
AudioFileFormat ff = AudioSystem.getAudioFileFormat(new File(file));
[... use ff or is at your need ...]
This is a corner case, but indeed may happen and may also trigger the bug.
* No event handling is implemented. We will add that in the next release.
* The backend relies on filesystem named pipes to stream audio data and will
not work if the system is not allowed to create named pipes (for example,
when GNU Classpath is built for systems without a filesystem).
* To allow correct behaviour of the "available" method (return the free space
in the pipeline) we measure the number of bytes currently in the pipeline for
processing and substract that from the size of the pipeline.
Few operating systems allow us to know in advance the size of a pipeline (usually
you can retrieve the number of bytes waiting for processing or tell if the next
write will block, but not the number of bytes you can write before
blocking), so we detect the size of the pipeline when the backend is first used.
This operation can be time consuming, so the result is stored as a preference
and used each time instead of detecting again.
If you use the MemoryBasedPreferences preference backend, no data is
actually written in a persistent storage, so the detection routine is called
again each time the class is initialized. Currently this occurs in the
constructor! A better approach would be to move this in to the static initializer,
and this will be fixed in the next release.
The preference node for this value is:
* gnu.javax.sound.sampled.gstreamer.lines.GStreamer
and the key:
* Capacity
If you use the GConf preference backend, it's easy to edit this node, just
search for this key (assuming all the default values are used, otherwise,
pay attention to the defined root node if it's different than
"/apps/classpath"):
* /apps/classpath/gnu/javax/sound/sampled/gstreamer/lines/GStreamer
and edit the key Capacity. Do this only if you know the correct size of the
pipe and you think the detection code will not work reliably on your system
(for example, if you have tweaked the kernel to allow very large named pipes
the operation may require a lot of time to complete, as all that the code
does is write bytes to the pipe until it becomes full).
|