changeset in /hg/pulseaudio: 2008-08-15 Omair Majid <omajid at redh...
Omair Majid
omajid at redhat.com
Fri Aug 15 09:03:10 PDT 2008
changeset a2034200b782 in /hg/pulseaudio
details: http://icedtea.classpath.org/hg/pulseaudio?cmd=changeset;node=a2034200b782
description:
2008-08-15 Omair Majid <omajid at redhat.com>
* src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java
removed all native functions. uses the stream class to work now
* src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeContro
fixed to use the stream class
* src/java/org/classpath/icedtea/pulseaudio/Stream.java:
initial implementation
* src/native/jni-common.c: added callJavaVoidMethod()
* src/native/jni-common.h: same
* src/native/org_classpath_icedtea_pulseaudio_Stream.c:
implemented callbacks
diffstat:
6 files changed, 486 insertions(+), 196 deletions(-)
src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java | 159 +---
src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java | 2
src/java/org/classpath/icedtea/pulseaudio/Stream.java | 322 +++++++---
src/native/jni-common.c | 23
src/native/jni-common.h | 3
src/native/org_classpath_icedtea_pulseaudio_Stream.c | 173 +++++
diffs (truncated from 1114 to 500 lines):
diff -r 5f856aeca15a -r a2034200b782 src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Thu Aug 14 14:24:17 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Fri Aug 15 10:26:12 2008 -0400
@@ -37,7 +37,6 @@ exception statement from your version.
package org.classpath.icedtea.pulseaudio;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -62,7 +61,6 @@ public class PulseAudioSourceDataLine im
private static final String PULSEAUDIO_FORMAT_KEY = "PulseAudioFormatKey";
private String streamName = "Java Stream";
- private List<StreamListener> streamListeners = new ArrayList<StreamListener>();
private EventLoop eventLoop = null;
@@ -80,50 +78,13 @@ public class PulseAudioSourceDataLine im
private PulseAudioStreamVolumeControl volumeControl;
private boolean muted;
private float volume;
-
+
private long currentFramePosition = 0;
- /*
- * When moving from 32bit platform to 64 bit platform, these variables
- * should make life fun
- *
- */
- @SuppressWarnings("unused")
- private long streamPointer;
-
- private native void native_open(long contextPointer, String streamName,
- String encoding, int sampleRate, int channels, int bufferSize);
-
- private native void native_write(byte[] data, int offset, int length);
-
- private native int native_get_writable_size();
-
- private native long native_flush();
-
- private native void native_start();
-
- private native void native_pause();
-
- private native void native_resume();
-
- private native long native_drain();
-
- private native void native_close();
-
- static {
- try {
- String library = new java.io.File(".").getCanonicalPath()
- + java.io.File.separatorChar
- + System.mapLibraryName("pulse-java");
- System.out.println(library);
- System.load(library);
- } catch (IOException e) {
- assert ("Loading failed".endsWith("library"));
- }
-
- }
+ private Stream stream;
public PulseAudioSourceDataLine(EventLoop eventLoop) {
+
this.eventLoop = eventLoop;
this.lineListeners = new ArrayList<LineListener>();
this.volume = PulseAudioVolumeControl.MAX_VOLUME;
@@ -338,10 +299,10 @@ public class PulseAudioSourceDataLine im
for (AudioFormat myFormat : supportedFormats) {
if (format.matches(myFormat)) {
- native_open(eventLoop.getContextPointer(), streamName,
- (String) myFormat.getProperty(PULSEAUDIO_FORMAT_KEY),
- (int) format.getSampleRate(), format.getChannels(),
- bufferSize);
+ stream = new Stream(eventLoop.getContextPointer(), streamName,
+ Stream.Format.valueOf((String) myFormat
+ .getProperty(PULSEAUDIO_FORMAT_KEY)),
+ (int) format.getSampleRate(), format.getChannels());
currentFormat = format;
isOpen = true;
}
@@ -351,15 +312,15 @@ public class PulseAudioSourceDataLine im
throw new IllegalArgumentException("Invalid format");
}
- StreamListener openCloseListener = new StreamListener() {
+ Stream.StateListener openCloseListener = new Stream.StateListener() {
@Override
- public void update(StreamEvent e) {
- if (e.getType() == StreamEvent.Type.READY) {
+ public void update() {
+ if (stream.getState() == Stream.State.READY) {
fireLineEvent(new LineEvent(PulseAudioSourceDataLine.this,
LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED));
- } else if (e.getType() == StreamEvent.Type.TERMINATED
- || e.getType() == StreamEvent.Type.FAILED) {
+ } else if (stream.getState() == Stream.State.TERMINATED
+ || stream.getState() == Stream.State.FAILED) {
fireLineEvent((new LineEvent(PulseAudioSourceDataLine.this,
LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED)));
}
@@ -367,22 +328,22 @@ public class PulseAudioSourceDataLine im
};
- addStreamListener(openCloseListener);
+ stream.addStateListener(openCloseListener);
final Semaphore semaphore = new Semaphore(0);
synchronized (eventLoop.threadLock) {
- this.addStreamListener(new StreamListener() {
+ stream.addStateListener(new Stream.StateListener() {
@Override
- public void update(StreamEvent e) {
- if (e.getType() == StreamEvent.Type.READY) {
+ public void update() {
+ if (stream.getState() == Stream.State.READY) {
semaphore.release();
}
}
});
- native_start();
+ stream.connectForPlayback(null);
}
try {
@@ -440,7 +401,7 @@ public class PulseAudioSourceDataLine im
while (remainingLength != 0) {
synchronized (eventLoop.threadLock) {
- availableSize = native_get_writable_size();
+ availableSize = stream.getWritableSize();
if (availableSize < 0) {
return sizeWritten;
}
@@ -448,19 +409,18 @@ public class PulseAudioSourceDataLine im
availableSize = remainingLength;
}
/* write a little bit of the buffer */
- native_write(data, position, availableSize);
+ stream.write(data, position, availableSize);
sizeWritten += availableSize;
position += availableSize;
remainingLength -= availableSize;
-
}
}
// all the data should have been played by now
assert (sizeWritten == length);
- currentFramePosition += (sizeWritten/getFormat().getFrameSize());
+ currentFramePosition += (sizeWritten / getFormat().getFrameSize());
/*
* FIXME when the stream is flushed() etc, instead of returning length
* this should unblock and return the the size of data written so far
@@ -470,7 +430,7 @@ public class PulseAudioSourceDataLine im
public void start() {
if (isPaused) {
- native_resume();
+ stream.cork(false);
isPaused = false;
}
@@ -483,7 +443,7 @@ public class PulseAudioSourceDataLine im
public void stop() {
synchronized (eventLoop.threadLock) {
- native_pause();
+ stream.cork(true);
}
isPaused = true;
@@ -497,25 +457,13 @@ public class PulseAudioSourceDataLine im
this.lineListeners.remove(listener);
}
- private void addStreamListener(StreamListener listener) {
- synchronized (streamListeners) {
- this.streamListeners.add(listener);
- }
- }
-
- private void removeStreamListener(StreamListener listener) {
- synchronized (streamListeners) {
- this.streamListeners.remove(listener);
- }
- }
-
public boolean isOpen() {
return isOpen;
}
public int available() {
synchronized (eventLoop.threadLock) {
- return native_get_writable_size();
+ return stream.getWritableSize();
}
};
@@ -524,26 +472,27 @@ public class PulseAudioSourceDataLine im
final Semaphore semaphore = new Semaphore(0);
- StreamListener closeListener = new StreamListener() {
+ Stream.StateListener closeListener = new Stream.StateListener() {
@Override
- public void update(StreamEvent e) {
- if (e.getType() == StreamEvent.Type.TERMINATED
- || e.getType() == StreamEvent.Type.FAILED) {
+ public void update() {
+ if (stream.getState() == Stream.State.TERMINATED
+ || stream.getState() == Stream.State.FAILED) {
semaphore.release();
}
}
};
- addStreamListener(closeListener);
+ stream.addStateListener(closeListener);
synchronized (eventLoop.threadLock) {
- native_close();
+ stream.drain();
+ stream.disconnect();
}
try {
semaphore.acquire();
System.out.println("stream closed");
- removeStreamListener(closeListener);
+ stream.removeStateListener(closeListener);
} catch (InterruptedException e) {
// throw new LineUnavailableException("unable to prepare
// stream");
@@ -569,7 +518,7 @@ public class PulseAudioSourceDataLine im
}
public int getFramePosition() {
- return (int)currentFramePosition;
+ return (int) currentFramePosition;
}
public float getLevel() {
@@ -583,8 +532,8 @@ public class PulseAudioSourceDataLine im
public long getMicrosecondPosition() {
float frameRate = currentFormat.getFrameRate();
- float time = currentFramePosition/frameRate; // seconds
- long microseconds = (long)(time * 1000);
+ float time = currentFramePosition / frameRate; // seconds
+ long microseconds = (long) (time * 1000);
return microseconds;
}
@@ -640,7 +589,7 @@ public class PulseAudioSourceDataLine im
Operation operation;
Operation.State operationState;
synchronized (eventLoop.threadLock) {
- operation = new Operation(native_drain());
+ operation = stream.drain();
operationState = operation.getState();
}
@@ -659,7 +608,7 @@ public class PulseAudioSourceDataLine im
Operation operation;
Operation.State operationState;
synchronized (eventLoop.threadLock) {
- operation = new Operation(native_flush());
+ operation = stream.flush();
operationState = operation.getState();
}
// FIXME need to find a way to do a wait than a busy loop
@@ -673,50 +622,18 @@ public class PulseAudioSourceDataLine im
}
- public void update(int status) {
- synchronized (eventLoop.threadLock) {
- switch (status) {
- case 0:
- fireStreamEvent(new StreamEvent(StreamEvent.Type.UNCONNECTED));
- break;
- case 1:
- fireStreamEvent(new StreamEvent(StreamEvent.Type.CREATING));
- break;
- case 2:
- fireStreamEvent(new StreamEvent(StreamEvent.Type.READY));
- break;
- case 3:
- fireStreamEvent(new StreamEvent(StreamEvent.Type.FAILED));
- break;
- case 4:
- fireStreamEvent(new StreamEvent(StreamEvent.Type.TERMINATED));
- break;
- default:
- assert ("not supposed to happen".indexOf("false") >= 0);
- }
- }
- }
-
private void fireLineEvent(LineEvent e) {
for (LineListener lineListener : lineListeners) {
lineListener.update(e);
}
}
- private void fireStreamEvent(StreamEvent e) {
- synchronized (streamListeners) {
- for (StreamListener streamListener : streamListeners) {
- streamListener.update(e);
- }
- }
- }
-
protected EventLoop getEventLoop() {
return this.eventLoop;
}
- public long getStreamPointer() {
- return streamPointer;
+ public Stream getStream() {
+ return stream;
}
}
diff -r 5f856aeca15a -r a2034200b782 src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java Thu Aug 14 14:24:17 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java Fri Aug 15 10:26:12 2008 -0400
@@ -28,7 +28,7 @@ public class PulseAudioStreamVolumeContr
protected PulseAudioStreamVolumeControl(PulseAudioSourceDataLine line) {
super(line);
- this.streamPointer = line.getStreamPointer();
+ this.streamPointer = line.getStream().getStreamPointer();
this.eventLoop = line.getEventLoop();
this.line = line;
}
diff -r 5f856aeca15a -r a2034200b782 src/java/org/classpath/icedtea/pulseaudio/Stream.java
--- a/src/java/org/classpath/icedtea/pulseaudio/Stream.java Thu Aug 14 14:24:17 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/Stream.java Fri Aug 15 10:26:12 2008 -0400
@@ -1,6 +1,7 @@ package org.classpath.icedtea.pulseaudio
package org.classpath.icedtea.pulseaudio;
-import javax.sound.sampled.AudioFormat;
+import java.util.LinkedList;
+import java.util.List;
/**
*
@@ -10,16 +11,64 @@ import javax.sound.sampled.AudioFormat;
*/
public class Stream {
+ public interface StateListener {
+ public void update();
+ }
+
+ public interface WriteListener {
+ public void update();
+ }
+
+ public interface ReadListener {
+ public void update();
+ }
+
+ public interface OverflowListener {
+ public void update();
+ }
+
+ public interface UnderflowListener {
+ public void update();
+ }
+
+ public interface PlaybackStartedListener {
+ public void update();
+ }
+
+ public interface LatencyUpdateListener {
+ public void update();
+ }
+
+ public interface MovedListener {
+ public void update();
+ }
+
+ public interface SuspendedListener {
+ public void update();
+ }
+
public static enum State {
UNCONNECTED, CREATING, READY, FAILED, TERMINATED,
}
public static enum Format {
- PA_SAMPLE_U8, PA_SAMPLE_ULAW, PA_SAMPLE_ALAW, PA_SAMPLE_S16LE, PA_SAMPLE_S16BE, PA_SAMPLE_FLOAT32LE, PA_SAMPLE_FLOAT32BE, PA_SAMPLE_S32LE, PA_SAMPLE_S32BE,
+ PA_SAMPLE_U8, PA_SAMPLE_ULAW, PA_SAMPLE_ALAW, PA_SAMPLE_S16LE, PA_SAMPLE_S16BE, PA_SAMPLE_FLOAT32LE, PA_SAMPLE_FLOAT32BE, PA_SAMPLE_S32LE, PA_SAMPLE_S32BE
}
@SuppressWarnings("unused")
private long streamPointer;
+
+ private Format format;
+
+ private List<StateListener> stateListeners;
+ private List<WriteListener> writeListeners;
+ private List<ReadListener> readListeners;
+ private List<OverflowListener> overflowListeners;
+ private List<UnderflowListener> underflowListeners;
+ private List<PlaybackStartedListener> playbackStartedListeners;
+ private List<LatencyUpdateListener> latencyUpdateListeners;
+ private List<MovedListener> movedListeners;
+ private List<SuspendedListener> suspendedListeners;
private native void native_pa_stream_new(long contextPointer, String name,
String format, int sampleRate, int channels);
@@ -65,32 +114,7 @@ public class Stream {
/*
* Drain a playback stream. pa_operation pa_stream_update_timing_info
* (pa_stream *p, pa_stream_success_cb_t cb, void *userdata) Request a
- * timing info structure update for a stream. void
- * pa_stream_set_state_callback (pa_stream *s, pa_stream_notify_cb_t cb,
- * void *userdata) Set the callback function that is called whenever the
- * state of the stream changes. void pa_stream_set_write_callback (pa_stream
- * *p, pa_stream_request_cb_t cb, void *userdata) Set the callback function
- * that is called when new data may be written to the stream. void
- * pa_stream_set_read_callback (pa_stream *p, pa_stream_request_cb_t cb,
- * void *userdata) Set the callback function that is called when new data is
- * available from the stream. void pa_stream_set_overflow_callback
- * (pa_stream *p, pa_stream_notify_cb_t cb, void *userdata) Set the callback
- * function that is called when a buffer overflow happens. void
- * pa_stream_set_underflow_callback (pa_stream *p, pa_stream_notify_cb_t cb,
- * void *userdata) Set the callback function that is called when a buffer
- * underflow happens. void pa_stream_set_started_callback (pa_stream *p,
- * pa_stream_notify_cb_t cb, void *userdata) Set the callback function that
- * is called when a the server starts playback after an underrun or on
- * initial startup. void pa_stream_set_latency_update_callback (pa_stream
- * *p, pa_stream_notify_cb_t cb, void *userdata) Set the callback function
- * that is called whenever a latency information update happens. void
- * pa_stream_set_moved_callback (pa_stream *p, pa_stream_notify_cb_t cb,
- * void *userdata) Set the callback function that is called whenever the
- * stream is moved to a different sink/source. void
- * pa_stream_set_suspended_callback (pa_stream *p, pa_stream_notify_cb_t cb,
- * void *userdata) Set the callback function that is called whenever the
- * sink/source this stream is connected to is suspended or resumed.
- *
+ * timing info structure update for a stream.
*/
private native long native_pa_stream_cork(int b);
@@ -146,9 +170,107 @@ public class Stream {
public Stream(long contextPointer, String name, Format format,
int sampleRate, int channels) {
- System.out.println("format: "+ format.toString());
+ System.out.println("format: " + format.toString());
+
+ stateListeners = new LinkedList<StateListener>();
+ writeListeners = new LinkedList<WriteListener>();
+ readListeners = new LinkedList<ReadListener>();
+ overflowListeners = new LinkedList<OverflowListener>();
+ underflowListeners = new LinkedList<UnderflowListener>();
+ playbackStartedListeners = new LinkedList<PlaybackStartedListener>();
+ latencyUpdateListeners = new LinkedList<LatencyUpdateListener>();
+ movedListeners = new LinkedList<MovedListener>();
+ suspendedListeners = new LinkedList<SuspendedListener>();
+
+ this.format = format;
+
native_pa_stream_new(contextPointer, name, format.toString(),
sampleRate, channels);
+ }
+
+ public void addStateListener(StateListener listener) {
+ synchronized (stateListeners) {
+ stateListeners.add(listener);
+ }
+ }
+
+ public void removeStateListener(StateListener listener) {
+ synchronized (stateListeners) {
+ stateListeners.remove(listener);
+ }
+
+ }
+
+ public void addWriteListener(WriteListener listener) {
More information about the distro-pkg-dev
mailing list