Mercurial > hg > pulseaudio
changeset 70:3c53bfe980bc
2008-08-13 Omair Majid <omajid@redhat.com>
* build.xml: now generates headers for PulseAudioClip.java
* src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java: new file.
implements the Clip interface. currently mainly a stub
* src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java:
added support for getting a clip from the mixer
* src/native/Makefile.am: added src/native/*PulseAudioClip.{c,h} to list
of files to build
* src/native/org_classpath_icedtea_pulseaudio_PulseAudioClip.c: new file
* unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java:
new file. junit tests for PulseAudioClip
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Wed, 13 Aug 2008 13:00:36 -0400 |
parents | c054a0681a49 |
children | 9ed589465932 |
files | build.xml src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java src/native/Makefile.am src/native/org_classpath_icedtea_pulseaudio_PulseAudioClip.c unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java |
diffstat | 6 files changed, 357 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/build.xml Wed Aug 13 10:12:49 2008 -0400 +++ b/build.xml Wed Aug 13 13:00:36 2008 -0400 @@ -38,6 +38,7 @@ <class name="org.classpath.icedtea.pulseaudio.EventLoop"/> <class name="org.classpath.icedtea.pulseaudio.Operation"/> <class name="org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine"/> + <class name="org.classpath.icedtea.pulseaudio.PulseAudioClip"/> <class name="org.classpath.icedtea.pulseaudio.PulseAudioStreamVolumeControl"/> </javah> </target>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java Wed Aug 13 13:00:36 2008 -0400 @@ -0,0 +1,268 @@ +package org.classpath.icedtea.pulseaudio; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.Control; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Control.Type; + +public class PulseAudioClip implements Clip { + + private byte[] data = null; + private int bufferSize = 0; + + // these are frame indices. so counted from 0 + private long currentFrame = 0; + private int frameCount = 0; + private long startFrame = 0; + private long endFrame = 0; + private long framesSinceOpen = 0; + + private AudioFormat currentFormat = null; + private static final AudioFormat DEFAULT_FORMAT = new AudioFormat( + AudioFormat.Encoding.PCM_UNSIGNED, 22050, 8, 2, 2, 22050 / 2, false); + + private boolean isOpen = false; + + private List<LineListener> lineListeners = null; + + private static final int DEFAULT_BUFFER_SIZE = 0; + + @SuppressWarnings("unused") + private long streamPointer = 0; + + private native void native_open(); + + private native void native_close(); + + private native void native_start(); + + private native void native_stop(); + + private native long native_drain(); + + private native long native_flush(); + + 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")); + } + } + + public PulseAudioClip() { + lineListeners = new LinkedList<LineListener>(); + } + + @Override + public void addLineListener(LineListener listener) { + lineListeners.add(listener); + } + + @Override + public int available() { + return 0; // a clip always returns 0 + } + + @Override + public void close() { + // TODO Auto-generated method stub + native_close(); + isOpen = false; + } + + @Override + public void drain() { + // TODO Auto-generated method stub + native_drain(); + } + + @Override + public void flush() { + // TODO Auto-generated method stub + native_flush(); + } + + @Override + public int getBufferSize() { + return bufferSize; + } + + @Override + public Control getControl(Type control) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Control[] getControls() { + // TODO Auto-generated method stub + return null; + } + + @Override + public AudioFormat getFormat() { + if (!isOpen) { + return DEFAULT_FORMAT; + } + return currentFormat; + } + + @Override + public int getFrameLength() { + return frameCount; + } + + @Override + public int getFramePosition() { + return (int) framesSinceOpen; + } + + @Override + public float getLevel() { + // TODO Auto-generated method stub + return AudioSystem.NOT_SPECIFIED; + } + + @Override + public javax.sound.sampled.Line.Info getLineInfo() { + return new Line.Info(this.getClass()); + } + + @Override + public long getLongFramePosition() { + return framesSinceOpen; + } + + @Override + public long getMicrosecondLength() { + if (!isOpen) { + return AudioSystem.NOT_SPECIFIED; + } + return frameCount / currentFormat.getFrameSize(); + } + + @Override + public long getMicrosecondPosition() { + return framesSinceOpen / currentFormat.getFrameSize(); + } + + @Override + public boolean isActive() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isControlSupported(Type control) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isOpen() { + return isOpen; + } + + @Override + public boolean isRunning() { + // really confused about what this is supposed to do + return isActive(); + } + + @Override + public void loop(int count) { + // TODO Auto-generated method stub + + } + + @Override + public void open() throws LineUnavailableException { + throw new IllegalArgumentException("open() on a Clip is not allowed"); + } + + @Override + public void open(AudioFormat format, byte[] data, int offset, int bufferSize) + throws LineUnavailableException { + // TODO Auto-generated method stub + + native_open(); + + isOpen = true; + } + + @Override + public void open(AudioInputStream stream) throws LineUnavailableException, + IOException { + // TODO Auto-generated method stub + + byte[] buffer = new byte[(int) (stream.getFrameLength() * stream + .getFormat().getFrameSize())]; + + open(stream.getFormat(), buffer, 0, DEFAULT_BUFFER_SIZE); + + } + + @Override + public void removeLineListener(LineListener listener) { + lineListeners.remove(listener); + } + + @Override + public void setFramePosition(int frames) { + + if (frames > frameCount) { + throw new IllegalArgumentException("incorreft frame value"); + } + + currentFrame = frames; + + } + + @Override + public void setLoopPoints(int start, int end) { + if (end == -1) { + end = frameCount; + } + + if (end < start) { + throw new IllegalArgumentException( + "ending point must be greater than or equal to the starting point"); + } + + startFrame = start; + endFrame = end; + + } + + @Override + public void setMicrosecondPosition(long microseconds) { + float frameIndex = microseconds * currentFormat.getFrameRate(); + currentFrame = (long) frameIndex; + + } + + @Override + public void start() { + native_start(); + } + + @Override + public void stop() { + native_stop(); + } + +}
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 13 10:12:49 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 13 13:00:36 2008 -0400 @@ -73,7 +73,8 @@ private List<PulseAudioSourceDataLine> sourceLines = new ArrayList<PulseAudioSourceDataLine>(); // private List<PulseAudioTargetDataLine> targetLines = null; - + private List<PulseAudioClip> clips = new ArrayList<PulseAudioClip>(); + // private Line.Info targetDataLineInfo = new // Line.Info(PulseAudioTargetDataLine.class); @@ -144,6 +145,14 @@ // return targetLine; // } + PulseAudioClip clip = new PulseAudioClip(); + + if (info.matches(clip.getLineInfo())) { + clips.add(clip); + return clip; + } + + throw new IllegalArgumentException(); }
--- a/src/native/Makefile.am Wed Aug 13 10:12:49 2008 -0400 +++ b/src/native/Makefile.am Wed Aug 13 13:00:36 2008 -0400 @@ -10,7 +10,9 @@ org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.c \ org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.h \ org_classpath_icedtea_pulseaudio_Operation.h \ - org_classpath_icedtea_pulseaudio_Operation.c + org_classpath_icedtea_pulseaudio_Operation.c \ + org_classpath_icedtea_pulseaudio_PulseAudioClip.c \ + org_classpath_icedtea_pulseaudio_PulseAudioClip.h AM_CFLAGS = -g -Wall -Werror $(PLATFORM_FLAGS) $(LIBPULSE_CFLAGS) AM_LDFLAGS = -g -Wall -Werror $(LIBPULSE_LIBS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/native/org_classpath_icedtea_pulseaudio_PulseAudioClip.c Wed Aug 13 13:00:36 2008 -0400 @@ -0,0 +1,24 @@ +#include "org_classpath_icedtea_pulseaudio_PulseAudioClip.h" + +#include "jni-common.h" + +/* + * Class: org_classpath_icedtea_pulseaudio_PulseAudioClip + * Method: native_open + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioClip_native_1open +(JNIEnv* env, jobject obj) { + +} + +/* + * Class: org_classpath_icedtea_pulseaudio_PulseAudioClip + * Method: native_close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioClip_native_1close +(JNIEnv* env, jobject obj) { + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java Wed Aug 13 13:00:36 2008 -0400 @@ -0,0 +1,51 @@ +package org.classpath.icedtea.pulseaudio; + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +import junit.framework.JUnit4TestAdapter; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PulseAudioClipTest { + + Mixer mixer; + + public static junit.framework.Test suite() { + return new JUnit4TestAdapter(PulseAudioClipTest.class); + } + + @Before + public void setUp() throws LineUnavailableException { + Mixer.Info wantedMixerInfo = null; + Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo(); + for (Mixer.Info mixerInfo : mixerInfos) { + if (mixerInfo.getName().contains("PulseAudio")) { + wantedMixerInfo = mixerInfo; + break; + } + } + assert (wantedMixerInfo != null); + mixer = AudioSystem.getMixer(wantedMixerInfo); + mixer.open(); + } + + @Test + public void testObtainingAClip() throws LineUnavailableException { + Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class)); + Assert.assertNotNull(clip); + } + + + @After + public void tearDown() { + + } + +}