changeset 100:1a1a426b17cc

2008-08-27 Omair Majid <omajid@redhat.com> * src/java/org/classpath/icedtea/pulseaudio/Eventloop.java (run): Made the eventloop block when not doing anything. Saves cpu cycles greatly. Since blocking works, fixed the comments. * src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java Removed duplicate variable currentFormat. Added a List of Controls. (getControl): Return Control[] when open. (loop): Added a call to super.start() to indicate that the loop has started. Fixes the problem when doing a loop() and then stop() would fail. (start): Added a check that the Clip hasnt already been started. (stop): Added a check that the Clip has been started. * src/native/jni-common.c (getLockObject): New function. Returns the Eventloop.threadLock object. (notifyWaitingOperations): Calls getLockObject to obtain the lock. * src/native/jni-common.h (getLockObject): New function. * src/native/org_classpath_icedtea_pulseaudio_EventLoop.c (poll_function): New function. This function calls poll but releases the lock on EventLoop.threadLock so that other threads dont have to wait for the poll to timeout before they can do anything. Allows native_iterate to block, which reduces needless loops. (Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1setup): Now sets the polling function to poll_function. * unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerTest.java (testLongWait): Changed the duration to 10000 to get a longer window to obtain the CPU usage when the program isnt doing anything.
author Omair Majid <omajid@redhat.com>
date Wed, 27 Aug 2008 14:22:14 -0400
parents 548fa22ff716
children f489a16be6f1
files src/java/org/classpath/icedtea/pulseaudio/EventLoop.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java src/native/jni-common.c src/native/jni-common.h src/native/org_classpath_icedtea_pulseaudio_EventLoop.c unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerTest.java
diffstat 6 files changed, 55 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Wed Aug 27 12:04:55 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Wed Aug 27 14:22:14 2008 -0400
@@ -145,11 +145,9 @@
 		 */
 		while (true) {
 			synchronized (threadLock) {
-				// timeout is a funky parameter (in milliseconds)
+				// timeout is in milliseconds
 				// timout = 0 means dont block
-				// setting it to even 1 makes the program crawl
-				// question is, why?
-				native_iterate(0);
+				native_iterate(100);
 
 				if (Thread.interrupted()) {
 					native_shutdown();
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Wed Aug 27 12:04:55 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Wed Aug 27 14:22:14 2008 -0400
@@ -39,6 +39,7 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Semaphore;
 
 import javax.sound.sampled.AudioFormat;
@@ -62,9 +63,9 @@
 	private int endFrame = 0;
 	private int framesSinceOpen = 0;
 
-	private AudioFormat currentFormat = null;
+	public static final String DEFAULT_CLIP_NAME = "Clip";
 
-	public static final String DEFAULT_CLIP_NAME = "Clip";
+	private List<Control> controls = null;
 
 	private Object clipLock = new Object();
 	private boolean clipThreadStarted;
@@ -201,13 +202,20 @@
 
 	@Override
 	public Control getControl(Type control) {
+		if (isOpen) {
+
+		}
 		throw new IllegalArgumentException(control.toString()
 				+ " not supported");
 	}
 
 	@Override
 	public Control[] getControls() {
-		return new Control[] {};
+		if (!isOpen) {
+			return new Control[] {};
+		}
+
+		return (Control[]) controls.toArray(new Control[0]);
 	}
 
 	@Override
@@ -282,11 +290,16 @@
 
 	@Override
 	public void loop(int count) {
+
 		System.out.println("Loop " + count + " called");
+
 		if (clipThreadStarted && count != 0) {
 			// Do nothing; behavior not specified by the Java API
 			return;
 		}
+
+		super.start();
+
 		synchronized (clipLock) {
 			if (currentFrame > endFrame) {
 				loopsLeft = 0;
@@ -375,6 +388,10 @@
 
 	@Override
 	public void start() {
+		if (isStarted) {
+			throw new IllegalStateException("already started");
+		}
+
 		super.start();
 
 		if (!clipThread.isAlive()) {
@@ -387,6 +404,9 @@
 	}
 
 	public void stop() {
+		if (!isStarted) {
+			throw new IllegalStateException("not started, so cant stop");
+		}
 
 		if (clipThread.isAlive()) {
 			clipThread.interrupt();
--- a/src/native/jni-common.c	Wed Aug 27 12:04:55 2008 -0400
+++ b/src/native/jni-common.c	Wed Aug 27 14:22:14 2008 -0400
@@ -104,8 +104,8 @@
 
 }
 
-void notifyWaitingOperations(JNIEnv* env) {
-
+jobject getLockObject(JNIEnv* env) {
+	
 	const char* eventLoopClassName =
 			"Lorg/classpath/icedtea/pulseaudio/EventLoop;";
 	jclass eventLoopClass = (*env)->FindClass(env, eventLoopClassName);
@@ -126,6 +126,12 @@
 
 	jobject lockObject = (*env)->GetObjectField(env, eventLoop, lockID);
 	assert(lockObject);
+	return lockObject;
+
+}
+
+void notifyWaitingOperations(JNIEnv* env) {
+	jobject lockObject = getLockObject(env);
 
 	(*env)->MonitorEnter(env, lockObject);
 
@@ -140,8 +146,6 @@
 
 }
 
-
-
 /*
  * 
  * 
--- a/src/native/jni-common.h	Wed Aug 27 12:04:55 2008 -0400
+++ b/src/native/jni-common.h	Wed Aug 27 14:22:14 2008 -0400
@@ -70,6 +70,7 @@
 void throwByName(JNIEnv* const env, const char* const name,
 		const char* const msg);
 
+jobject getLockObject(JNIEnv* env);
 void notifyWaitingOperations(JNIEnv* env);
 
 void* getJavaPointer(JNIEnv* env, jobject obj, char* name);
--- a/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Wed Aug 27 12:04:55 2008 -0400
+++ b/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Wed Aug 27 14:22:14 2008 -0400
@@ -40,6 +40,8 @@
 #include "org_classpath_icedtea_pulseaudio_EventLoop.h"
 #include "jni-common.h"
 
+#include <poll.h>
+
 const int PA_ITERATE_BLOCK = 1;
 const int PA_ITERATE_NOBLOCK = 0;
 
@@ -76,6 +78,20 @@
 
 }
 
+static int poll_function(struct pollfd *ufds, unsigned long nfds, int timeout,
+		void *userdata) {
+
+	JNIEnv* env = pulse_thread_env;
+	jobject lockObject = getLockObject(env);
+
+	(*env)->MonitorExit(env, lockObject);
+
+	int value = poll(ufds, nfds, timeout);
+
+	(*env)->MonitorEnter(env, lockObject);
+	return value;
+}
+
 /*
  * Class:     org_classpath_icedtea_pulseaudio_EventLoop
  * Method:    native_setup
@@ -133,6 +149,9 @@
 		pa_context_connect(context, NULL, 0, NULL);
 	}
 
+	// set polling function
+	pa_mainloop_set_poll_func(mainloop, poll_function, NULL);
+
 	setJavaPointer(env, obj, "mainloopPointer", mainloop);
 	setJavaPointer(env, obj, "contextPointer", context);
 	//	printf("native_setup() returning\n");
@@ -181,7 +200,7 @@
 JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1shutdown
 (JNIEnv *env, jobject obj) {
 
-//	printf("native_shutdown() starting\n");
+	//	printf("native_shutdown() starting\n");
 
 	pa_mainloop* mainloop = (pa_mainloop*) getJavaPointer(env, obj, "mainloopPointer");
 	assert(mainloop != NULL);
--- a/unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerTest.java	Wed Aug 27 12:04:55 2008 -0400
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioMixerTest.java	Wed Aug 27 14:22:14 2008 -0400
@@ -343,7 +343,7 @@
 	public void testLongWait() throws LineUnavailableException {
 		selectedMixer.open();
 		try {
-			Thread.sleep(1000);
+			Thread.sleep(10000);
 		} catch (InterruptedException e) {
 			System.out.println("thread interrupted");
 		}