changeset 44:4a01f1203d48

turned eventloop into a singleton. which revealed a bunch of threading issues; fixed most of the blockers
author Omair Majid <omajid@redhat.com>
date Wed, 06 Aug 2008 14:08:52 -0400
parents 0caab9aa95b1
children c3802b8ed541
files makefile src/org/classpath/icedtea/pulseaudio/ContextEvent$Type.class src/org/classpath/icedtea/pulseaudio/ContextEvent.class src/org/classpath/icedtea/pulseaudio/ContextListener.class src/org/classpath/icedtea/pulseaudio/EventLoop$1.class src/org/classpath/icedtea/pulseaudio/EventLoop.class src/org/classpath/icedtea/pulseaudio/EventLoop.java src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine$1.class src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.class src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java src/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.class src/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.class src/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.class src/org/classpath/icedtea/pulseaudio/StreamEvent$Type.class src/org/classpath/icedtea/pulseaudio/StreamEvent.class src/org/classpath/icedtea/pulseaudio/StreamListener.class src/org/classpath/icedtea/pulseaudio/StreamVolume.java src/org_classpath_icedtea_pulseaudio_EventLoop.c src/org_classpath_icedtea_pulseaudio_EventLoop.h src/org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine.h src/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.h src/org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine.h src/org_classpath_icedtea_pulseaudio_PulseAudioVolumeControl.h unittests/org/classpath/icedtea/pulseaudio/OtherSoundProvidersAvailableTest.java unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerProviderTest.java unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerRawTest.java unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerTest.java unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java
diffstat 29 files changed, 725 insertions(+), 282 deletions(-) [+]
line wrap: on
line diff
--- a/makefile	Tue Aug 05 17:30:50 2008 -0400
+++ b/makefile	Wed Aug 06 14:08:52 2008 -0400
@@ -35,8 +35,9 @@
                       bin/org_classpath_icedtea_pulseaudio_EventLoop.o \
                       bin/org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine.o \
                       bin/org_classpath_icedtea_pulseaudio_PulseAudioVolumeControl.o \
-                      bin/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.o \
+                      bin/org_classpath_icedtea_pulseaudio_StreamVolume.o \
 					  bin/jni-common.o  
+#                      bin/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.o \
 #					  	bin/org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine.o \      
 	gcc -g -shared -o $@ $^ /usr/lib/libpulse.so
 
@@ -57,6 +58,9 @@
 bin/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.o: src/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.c src/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.h
 	gcc $(CFLAGS) $(PLATFORM_FLAGS) -c -o $@ $<
 
+bin/org_classpath_icedtea_pulseaudio_StreamVolume.o: src/org_classpath_icedtea_pulseaudio_StreamVolume.c src/org_classpath_icedtea_pulseaudio_StreamVolume.h
+	gcc $(CFLAGS) $(PLATFORM_FLAGS) -c -o $@ $<
+
 bin/jni-common.o: src/jni-common.c src/jni-common.h
 	gcc $(CFLAGS) $(PLATFORM_FLAGS) -c -o $@ $<
 
@@ -77,6 +81,8 @@
 src/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.h: src/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.class
 	javah -d src -classpath src org.classpath.icedtea.pulseaudio.PulseAudioStreamVolumeControl
 
+src/org_classpath_icedtea_pulseaudio_StreamVolume.h: src/org/classpath/icedtea/pulseaudio/StreamVolume.class
+	javah -d src -classpath src org.classpath.icedtea.pulseaudio.StreamVolume
 
 # Compile Java
 #  Actually, this is not the best thing to do; javac might do some crazy things
Binary file src/org/classpath/icedtea/pulseaudio/ContextEvent$Type.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/ContextEvent.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/ContextListener.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/EventLoop$1.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/EventLoop.class has changed
--- a/src/org/classpath/icedtea/pulseaudio/EventLoop.java	Tue Aug 05 17:30:50 2008 -0400
+++ b/src/org/classpath/icedtea/pulseaudio/EventLoop.java	Wed Aug 06 14:08:52 2008 -0400
@@ -33,7 +33,7 @@
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version.
-*/
+ */
 
 package org.classpath.icedtea.pulseaudio;
 
@@ -60,12 +60,15 @@
 	 */
 	public Object threadLock = new Object();
 
+	private static EventLoop instance = null;
+
 	private List<ContextListener> contextListeners;
 	// private List<SourceDataLine> lines;
 	private String name;
 	private String serverString;
 
 	private int status;
+	//	private boolean eventLoopIsRunning = false;
 
 	public Semaphore finished = new Semaphore(0);
 
@@ -88,11 +91,6 @@
 	/*
 	 * These fields hold pointers
 	 * 
-	 * When going from 32 bit to 64 bit, these will have to be changed to longs,
-	 * but not otherwise
-	 * 
-	 * Pointer sizes change from 32 bit to 64 bit, but java data types's sizes
-	 * dont
 	 * 
 	 */
 	@SuppressWarnings("unused")
@@ -117,8 +115,16 @@
 		}
 	}
 
-	public EventLoop() {
+	private EventLoop() {
 		contextListeners = new ArrayList<ContextListener>();
+
+	}
+
+	synchronized public static EventLoop getEventLoop() {
+		if (instance == null) {
+			instance = new EventLoop();
+		}
+		return instance;
 	}
 
 	public void setAppName(String name) {
@@ -149,7 +155,6 @@
 					native_shutdown();
 					System.out.println(this.getClass().getName()
 							+ ": shutting down");
-					finished.release();
 					return;
 
 				}
@@ -158,9 +163,15 @@
 
 	}
 
-	public void addContextListener(ContextListener l) {
-		synchronized (threadLock) {
-			contextListeners.add(l);
+	public void addContextListener(ContextListener contextListener) {
+		synchronized (contextListeners) {
+			contextListeners.add(contextListener);
+		}
+	}
+
+	public void removeContextListener(ContextListener contextListener) {
+		synchronized (contextListeners) {
+			contextListeners.remove(contextListener);
 		}
 	}
 
@@ -185,6 +196,7 @@
 			case 3:
 				break;
 			case 4:
+				System.out.println(this.getClass().getName() + " is ready!");
 				fireEvent(new ContextEvent(Type.READY));
 				break;
 			case 5:
@@ -200,14 +212,19 @@
 	}
 
 	private void fireEvent(final ContextEvent e) {
-
+		System.out.println(this.getClass().getName() + "firing event: "
+				+ e.getType().toString());
 		Thread th = new Thread(new Runnable() {
 
 			@Override
 			public void run() {
+				System.out.println("notifying listeners");
+				
 				synchronized (contextListeners) {
+					System.out.println(contextListeners.size());
 					for (ContextListener listener : contextListeners) {
 						listener.update(e);
+						System.out.println("updating listeners");
 					}
 				}
 			}
@@ -215,7 +232,7 @@
 		});
 
 		th.start();
-
+		
 	}
 
 	public void setVolume(long streamPointer, int volume) {
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Tue Aug 05 17:30:50 2008 -0400
+++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Wed Aug 06 14:08:52 2008 -0400
@@ -33,7 +33,7 @@
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version.
-*/
+ */
 
 package org.classpath.icedtea.pulseaudio;
 
@@ -218,13 +218,13 @@
 		eventLoopThread.interrupt();
 
 		try {
-			eventLoop.finished.acquire();
+			eventLoopThread.join();
 		} catch (InterruptedException e) {
 			System.out.println(this.getClass().getName()
 					+ ": interrupted while waiting for eventloop to finish");
 		}
 
-		System.out.println(this.getClass().getName() + ": closing");
+		System.out.println(this.getClass().getName() + ": closed");
 
 		this.isOpen = false;
 		fireEvent(new LineEvent(this, LineEvent.Type.CLOSE,
@@ -304,25 +304,29 @@
 			host = host + ":" + String.valueOf(port);
 		}
 
-		eventLoop = new EventLoop();
+		eventLoop = EventLoop.getEventLoop();
 		eventLoop.setAppName(appName);
 		eventLoop.setServer(host);
 
 		final Semaphore ready = new Semaphore(0);
 
-		eventLoop.addContextListener(new ContextListener() {
+		ContextListener initListener = new ContextListener() {
 
 			@Override
 			public void update(ContextEvent e) {
-				System.out.println("Event detected " + e.getType().toString());
+				System.out.println(this.getClass().getName()
+						+ ": Event detected " + e.getType().toString());
 				if (e.getType() == ContextEvent.Type.READY
 						|| e.getType() == ContextEvent.Type.FAILED
 						|| e.getType() == ContextEvent.Type.TERMINATED) {
 					ready.release();
+					System.out.println("realeasing semaphore ready");
 				}
 			}
 
-		});
+		};
+
+		eventLoop.addContextListener(initListener);
 
 		eventLoopThread = new Thread(eventLoop, "PulseAudio Eventloop Thread");
 
@@ -333,17 +337,46 @@
 			System.out.println("waiting...");
 			ready.acquire();
 			if (eventLoop.getStatus() != 4) {
+				/*
+				 * when exiting, wait for the thread to end otherwise we get one
+				 * thread that inits the singletone with new data and the old
+				 * thread then cleans up the singleton asserts fail all over the
+				 * place
+				 */
+				eventLoop.removeContextListener(initListener);
+				eventLoopThread.interrupt();
+				eventLoopThread.join();
 				throw new LineUnavailableException();
 			}
-
+			eventLoop.removeContextListener(initListener);
 			System.out.println("got signal");
 		} catch (InterruptedException e) {
-			System.out.println("got interrupted");
+			System.out.println("PROBLEM: got interrupted");
 		}
 
+		System.out.println(this.getClass().getName() + ": ready");
+		
 		this.isOpen = true;
-		fireEvent(new LineEvent(this, LineEvent.Type.OPEN,
-				AudioSystem.NOT_SPECIFIED));
+
+//		ContextListener eventListener = new ContextListener() {
+//
+//			@Override
+//			public void update(ContextEvent e) {
+//				if (e.getType() == ContextEvent.Type.READY) {
+//
+//					fireEvent(new LineEvent(PulseAudioMixer.this,
+//							LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED));
+//				} else if (e.getType() == ContextEvent.Type.FAILED
+//						|| e.getType() == ContextEvent.Type.TERMINATED) {
+//					fireEvent(new LineEvent(PulseAudioMixer.this,
+//							LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED));
+//				}
+//
+//			}
+//
+//		};
+
+//		eventLoop.addContextListener(eventListener);
 
 	}
 
Binary file src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine$1.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.class has changed
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Tue Aug 05 17:30:50 2008 -0400
+++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Wed Aug 06 14:08:52 2008 -0400
@@ -45,7 +45,6 @@
 import javax.sound.sampled.AudioFormat;
 import javax.sound.sampled.BooleanControl;
 import javax.sound.sampled.Control;
-import javax.sound.sampled.FloatControl;
 import javax.sound.sampled.Line;
 import javax.sound.sampled.LineEvent;
 import javax.sound.sampled.LineListener;
Binary file src/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/PulseAudioVolumeControl.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/StreamEvent$Type.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/StreamEvent.class has changed
Binary file src/org/classpath/icedtea/pulseaudio/StreamListener.class has changed
--- a/src/org/classpath/icedtea/pulseaudio/StreamVolume.java	Tue Aug 05 17:30:50 2008 -0400
+++ b/src/org/classpath/icedtea/pulseaudio/StreamVolume.java	Wed Aug 06 14:08:52 2008 -0400
@@ -45,7 +45,7 @@
 
 	private FloatControl.Type type;
 	private PulseAudioSourceDataLine stream;
-	
+
 	private static final int MIN_PULSE_VOLUME = 0x0;
 	private static final int MAX_PULSE_VOLUME = 0x10000;
 
@@ -62,8 +62,8 @@
 		}
 	}
 
-	private native void native_set_volume(int volume, long streamPointer, long contextPointer);
-	
+	private native void native_set_volume(int volume, long streamPointer);
+
 	protected StreamVolume(PulseAudioSourceDataLine stream) {
 		super(FloatControl.Type.VOLUME, 0f, 100f, 0.1f, 1, 100f, "percent",
 				"mute", "medium", "max");
@@ -101,8 +101,9 @@
 		 * 
 		 */
 		int value = (int) (newValue/100f * MAX_PULSE_VOLUME);
-//		native_set_volume(value, stream.getStreamPointer());
-		
+//		synchronized (eventLoop.threadLock) {
+			native_set_volume(value, stream.getStreamPointer());
+//		}
 		super.setValue(newValue);
 	}
 
--- a/src/org_classpath_icedtea_pulseaudio_EventLoop.c	Tue Aug 05 17:30:50 2008 -0400
+++ b/src/org_classpath_icedtea_pulseaudio_EventLoop.c	Wed Aug 06 14:08:52 2008 -0400
@@ -52,6 +52,8 @@
 	assert(context);
 	assert(userdata == NULL);
 
+	printf("context state changed\n");
+	
 	//java_context_t* java_context = (java_context_t*)userdata;
 	JNIEnv* env = java_context->env;
 	jobject obj = java_context->obj;
@@ -203,6 +205,9 @@
 	free(java_context);
 
 	printf("native_shutdown() returning\n");
+	
+	setJavaPointer(env, obj, "mainloopPointer", NULL);
+	setJavaPointer(env, obj, "contextPointer", NULL);
 
 }
 
--- a/src/org_classpath_icedtea_pulseaudio_EventLoop.h	Tue Aug 05 17:30:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_classpath_icedtea_pulseaudio_EventLoop */
-
-#ifndef _Included_org_classpath_icedtea_pulseaudio_EventLoop
-#define _Included_org_classpath_icedtea_pulseaudio_EventLoop
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     org_classpath_icedtea_pulseaudio_EventLoop
- * Method:    native_setup
- * Signature: (Ljava/lang/String;Ljava/lang/String;)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1setup
-  (JNIEnv *, jobject, jstring, jstring);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_EventLoop
- * Method:    native_iterate
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1iterate
-  (JNIEnv *, jobject, jint);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_EventLoop
- * Method:    native_shutdown
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1shutdown
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_EventLoop
- * Method:    native_set_sink_volume
- * Signature: (JI)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1set_1sink_1volume
-  (JNIEnv *, jobject, jlong, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
--- a/src/org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine.h	Tue Aug 05 17:30:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine */
-
-#ifndef _Included_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
-#define _Included_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_DEFAULT_BUFFER_SIZE
-#define org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_DEFAULT_BUFFER_SIZE 1000L
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_open
- * Signature: (JLjava/lang/String;Ljava/lang/String;FIIZI)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1open
-  (JNIEnv *, jobject, jlong, jstring, jstring, jfloat, jint, jint, jboolean, jint);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_write
- * Signature: ([BII)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1write
-  (JNIEnv *, jobject, jbyteArray, jint, jint);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_get_writable_size
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1get_1writable_1size
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_getOperationState
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1getOperationState
-  (JNIEnv *, jobject, jint);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_flush
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1flush
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_start
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1start
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_pause
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1pause
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_resume
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1resume
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_drain
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1drain
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine
- * Method:    native_close
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1close
-  (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
--- a/src/org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl.h	Tue Aug 05 17:30:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl */
-
-#ifndef _Included_org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl
-#define _Included_org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl
- * Method:    getValue
- * Signature: ()F
- */
-JNIEXPORT jfloat JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl_getValue
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl
- * Method:    setValue
- * Signature: (F)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioStreamVolumeControl_setValue
-  (JNIEnv *, jobject, jfloat);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
--- a/src/org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine.h	Tue Aug 05 17:30:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine */
-
-#ifndef _Included_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
-#define _Included_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    openStream
- * Signature: (Ljava/lang/String;FIIZI)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_openStream
-  (JNIEnv *, jobject, jstring, jfloat, jint, jint, jboolean, jint);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    readFromStream
- * Signature: ([BII)V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_readFromStream
-  (JNIEnv *, jobject, jbyteArray, jint, jint);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    startStream
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_startStream
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    pauseStream
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_pauseStream
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    resumeStream
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_resumeStream
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    available
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_available
-  (JNIEnv *, jobject);
-
-/*
- * Class:     org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine
- * Method:    closeStream
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioTargetDataLine_closeStream
-  (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
--- a/src/org_classpath_icedtea_pulseaudio_PulseAudioVolumeControl.h	Tue Aug 05 17:30:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_classpath_icedtea_pulseaudio_PulseAudioVolumeControl */
-
-#ifndef _Included_org_classpath_icedtea_pulseaudio_PulseAudioVolumeControl
-#define _Included_org_classpath_icedtea_pulseaudio_PulseAudioVolumeControl
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unittests/org/classpath/icedtea/pulseaudio/OtherSoundProvidersAvailableTest.java	Wed Aug 06 14:08:52 2008 -0400
@@ -0,0 +1,105 @@
+/* PulseAudioStreamVolumeControl.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+
+package org.classpath.icedtea.pulseaudio;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+import junit.framework.JUnit4TestAdapter;
+
+import org.junit.Test;
+
+
+public class OtherSoundProvidersAvailableTest {
+	
+	public static junit.framework.Test suite() { 
+	    return new JUnit4TestAdapter(OtherSoundProvidersAvailableTest.class); 
+	}
+	
+	@Test
+	public void testOtherSoundProviders() {
+
+		Mixer.Info mixerInfos [] = AudioSystem.getMixerInfo();
+		Mixer.Info selectedMixerInfo = null;
+		Mixer selectedMixer;
+		
+		int i = 0;
+		for ( Mixer.Info info: mixerInfos) {
+			System.out.println("Mixer Line " + i++ + ": " + info.getName() + " " + info.getDescription());
+			if ( info.getName().contains("0,4")) {
+				selectedMixerInfo =	info; 
+			}
+		}
+		System.out.println(selectedMixerInfo.toString());
+		System.out.println("getting information from selected mixer:");
+		
+		// use 0,4 or the default
+		selectedMixer = AudioSystem.getMixer(selectedMixerInfo);
+		System.out.println(selectedMixer.toString());
+		try {
+			Line.Info sourceDataLineInfo = null;
+			
+			selectedMixer.open();	// initialize the mixer
+			
+			Line.Info allLineInfo[] = selectedMixer.getSourceLineInfo();
+			int j = 0;
+			for ( Line.Info lineInfo : allLineInfo) {
+				System.out.println("Source Line " + j++ + ": " + lineInfo.getLineClass());
+				if ( lineInfo.getLineClass().toString().contains("SourceDataLine")) {
+					sourceDataLineInfo = lineInfo;
+				}
+			}
+			
+			SourceDataLine sourceDataLine = (SourceDataLine) selectedMixer.getLine(sourceDataLineInfo);
+
+			sourceDataLine.open();
+			//sourceDataLine.write('a',  0, 2);
+			sourceDataLine.close();
+			
+		} catch ( LineUnavailableException e ) {
+			System.out.println("Line unavailable");
+		}
+		
+		
+		
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerProviderTest.java	Wed Aug 06 14:08:52 2008 -0400
@@ -0,0 +1,93 @@
+/* PulseAudioMixerProviderTest.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package org.classpath.icedtea.pulseaudio;
+
+import static org.junit.Assert.*;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+import junit.framework.JUnit4TestAdapter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PulseAudioMixerProviderTest {
+
+	private Mixer selectedMixer;
+	private Mixer.Info selectedMixerInfo;
+
+	public static junit.framework.Test suite() { 
+	    return new JUnit4TestAdapter(PulseAudioMixerProviderTest.class); 
+	}
+
+	@Before
+	public void setUp() throws Exception {
+
+		Mixer.Info mixerInfos [] = AudioSystem.getMixerInfo();
+
+		int i = 0;
+		for ( Mixer.Info info: mixerInfos) {
+			System.out.println("Mixer Line " + i++ + ": " + info.getName() + " " + info.getDescription());
+			if ( info.getName().contains("PulseAudio")) {
+				selectedMixerInfo =	info; 
+			}
+		}
+		assertNotNull(selectedMixerInfo);
+	}
+
+	@Test 
+	public void testMixerProvider() throws LineUnavailableException {
+		System.out.println(selectedMixerInfo.toString());
+		System.out.println("getting information from selected mixer:");
+
+		selectedMixer = AudioSystem.getMixer(selectedMixerInfo);
+		assertNotNull(selectedMixer);
+		System.out.println(selectedMixer.toString());
+	}
+
+
+	@After
+	public void tearDown() throws Exception {
+
+	}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerRawTest.java	Wed Aug 06 14:08:52 2008 -0400
@@ -0,0 +1,70 @@
+/* PulseAudioMixerRawTest.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package org.classpath.icedtea.pulseaudio;
+
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PulseAudioMixerRawTest {
+
+	Mixer mixer = null;
+	
+	@Before
+	public void setUp() {
+		mixer = PulseAudioMixer.getInstance();
+	}
+	
+	
+	@Test
+	public void testOpen() throws LineUnavailableException {
+		mixer.open();
+		
+	}
+	
+	
+	
+	@After
+	public void tearDown() {
+		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerTest.java	Wed Aug 06 14:08:52 2008 -0400
@@ -0,0 +1,232 @@
+/* PulseAudioStreamVolumeControl.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.classpath.icedtea.pulseaudio;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.net.UnknownHostException;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+import junit.framework.JUnit4TestAdapter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PulseAudioMixerTest {
+
+	PulseAudioMixer selectedMixer;
+
+	public static junit.framework.Test suite() {
+		return new JUnit4TestAdapter(PulseAudioMixerTest.class);
+	}
+
+	@Before
+	public void setUp() throws Exception {
+		Mixer.Info mixerInfos[] = AudioSystem.getMixerInfo();
+		Mixer.Info selectedMixerInfo = null;
+		// int i = 0;
+		for (Mixer.Info info : mixerInfos) {
+			// System.out.println("Mixer Line " + i++ + ": " + info.getName() +
+			// " " + info.getDescription());
+			if (info.getName().contains("PulseAudio")) {
+				selectedMixerInfo = info;
+			}
+		}
+		assertNotNull(selectedMixerInfo);
+		selectedMixer = (PulseAudioMixer) AudioSystem
+				.getMixer(selectedMixerInfo);
+		assertNotNull(selectedMixer);
+		if (selectedMixer.isOpen()) {
+			selectedMixer.close();
+		}
+
+	}
+
+	@Test
+	public void testLocalOpen() throws LineUnavailableException {
+		System.out.println("This test tries to open to the local system");
+		selectedMixer.openLocal();
+	}
+
+	@Test
+	public void testLocalOpenAppName() throws LineUnavailableException {
+		System.out
+				.println("This test tries to connect to the local system while using an application name");
+		selectedMixer.openLocal("JunitTest");
+
+	}
+
+	@Test(expected = LineUnavailableException.class)
+	public void testRemoteOpenWithInvalidPort() throws UnknownHostException,
+			LineUnavailableException {
+		System.out
+				.println("this test tries to connect to an invalid remote system");
+		selectedMixer.openRemote("JUnitTest", "128.0.0.1", 10);
+
+	}
+
+	/*
+	 * This test assumes a computer named 'town' is in the network with
+	 * pulseaudio listening on port 4173
+	 */
+	@Test
+	public void testRemoteOpenWithValidPort() throws UnknownHostException,
+			LineUnavailableException {
+		System.out.println("This test tries to connect a valid remote system");
+		selectedMixer.openRemote("JUnitTest", "town", 4713);
+		selectedMixer.close();
+	}
+
+	/*
+	 * This test assumes a computer named 'town' is in the network with
+	 * pulseaudio listening
+	 */
+	@Test
+	public void testRemoteOpen() throws UnknownHostException,
+			LineUnavailableException {
+		selectedMixer.openRemote("JUnitTest", "town");
+		selectedMixer.close();
+	}
+
+	@Test(expected = LineUnavailableException.class)
+	public void testInvalidRemoteOpen() throws UnknownHostException,
+			LineUnavailableException {
+		selectedMixer.openRemote("JUnitTest", "127.0.0.1");
+		selectedMixer.close();
+	}
+
+	@Test
+	public void testSourceLinesExist() throws LineUnavailableException {
+		selectedMixer.open();
+		Line.Info allLineInfo[] = selectedMixer.getSourceLineInfo();
+		int j = 0;
+		for (Line.Info lineInfo : allLineInfo) {
+			System.out.println("Source Line " + j++ + ": "
+					+ lineInfo.getLineClass());
+			SourceDataLine sourceDataLine = (SourceDataLine) selectedMixer
+					.getLine(lineInfo);
+			assertNotNull(sourceDataLine);
+
+		}
+
+	}
+
+	@Test
+	public void testOpeningAgain() throws LineUnavailableException,
+			UnsupportedOperationException {
+			selectedMixer.open();
+			selectedMixer.open();
+	}
+
+	@Test
+	public void testClosingAgain() throws LineUnavailableException,
+			UnsupportedOperationException {
+		selectedMixer.close();
+		selectedMixer.close();
+	}
+
+	@Test
+	public void testSourceLinesOpenAndClose() throws LineUnavailableException {
+		selectedMixer.open();
+		Line.Info allLineInfo[] = selectedMixer.getSourceLineInfo();
+		for (Line.Info lineInfo : allLineInfo) {
+			SourceDataLine sourceDataLine = (SourceDataLine) selectedMixer
+					.getLine(lineInfo);
+			sourceDataLine.open();
+			sourceDataLine.close();
+		}
+	}
+
+	@Test
+	public void testOpenEvent() throws LineUnavailableException {
+		LineListener listener = new LineListener() {
+			@Override
+			public void update(LineEvent event) {
+				assert (event.getType() == LineEvent.Type.OPEN);
+			}
+		};
+
+		selectedMixer.addLineListener(listener);
+		selectedMixer.open();
+		selectedMixer.removeLineListener(listener);
+		selectedMixer.close();
+
+	}
+
+	@Test
+	public void testCloseEvent() throws LineUnavailableException {
+		LineListener listener = new LineListener() {
+			@Override
+			public void update(LineEvent event) {
+				assert (event.getType() == LineEvent.Type.CLOSE);
+			}
+		};
+
+		selectedMixer.open();
+		selectedMixer.addLineListener(listener);
+		selectedMixer.close();
+		selectedMixer.removeLineListener(listener);
+
+	}
+
+	@Test
+	public void testLongWait() throws LineUnavailableException {
+		selectedMixer.open();
+		try {
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+			System.out.println("thread interrupted");
+		}
+
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		if (selectedMixer.isOpen())
+			selectedMixer.close();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java	Wed Aug 06 14:08:52 2008 -0400
@@ -0,0 +1,133 @@
+/* PulseSourceDataLineTest.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package org.classpath.icedtea.pulseaudio;
+
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+import junit.framework.JUnit4TestAdapter;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.classpath.icedtea.pulseaudio.PulseAudioMixer;
+
+public class PulseSourceDataLineTest {
+	Mixer mixer;
+	SourceDataLine line;
+	
+	public static junit.framework.Test suite() { 
+	    return new JUnit4TestAdapter(PulseSourceDataLineTest.class); 
+	}
+	
+	@Before
+	public void setUp() throws Exception {
+		mixer = PulseAudioMixer.getInstance();
+		mixer.open();
+		line = (PulseAudioSourceDataLine) mixer.getLine(new Line.Info(PulseAudioSourceDataLine.class));
+		Assert.assertNotNull(line);
+		
+	}
+	
+	@Test
+	public void testPlay() throws LineUnavailableException, UnsupportedAudioFileException, IOException {
+		File soundFile = new File("testsounds/startup.wav");
+		AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+		line.open(audioFormat);
+		line.start();
+
+		byte[] abData = new byte[1000];
+		int bytesRead = 0;
+
+		while (bytesRead >= 0) {
+			bytesRead = audioInputStream.read(abData, 0, abData.length);
+			if (bytesRead > 0) {
+				line.write(abData, 0, bytesRead);
+			}
+		}
+
+		line.flush();
+		line.close();
+
+	}
+
+	@Test
+	public void testPlayLoud() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
+		File soundFile = new File("testsounds/startup.wav");
+		AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+		line.open(audioFormat);
+		
+	
+		line.start();
+
+		byte[] abData = new byte[1000];
+		int bytesRead = 0;
+
+		while (bytesRead >= 0) {
+			bytesRead = audioInputStream.read(abData, 0, abData.length);
+			if (bytesRead > 0) {
+				line.write(abData, 0, bytesRead);
+			}
+		}
+
+		line.flush();
+		line.close();
+		
+	}
+	
+	@After
+	public void tearDown() throws Exception {
+		
+		mixer.close();
+	}
+
+}