Mercurial > hg > pulseaudio
changeset 46:2331da2e5f6a
fixed the problem with listeners remaining attached to a eventloop even after shutting down the eventloop; removed extra printing
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Wed, 06 Aug 2008 16:30:43 -0400 |
parents | c3802b8ed541 |
children | 2785b9eba70d |
files | .hgignore src/jni-common.c src/org/classpath/icedtea/pulseaudio/EventLoop.java src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java src/org/classpath/icedtea/pulseaudio/PulseAudioMixerInfo.java src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java src/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java src/org_classpath_icedtea_pulseaudio_EventLoop.c src/org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine.c |
diffstat | 9 files changed, 147 insertions(+), 144 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Wed Aug 06 14:55:15 2008 -0400 +++ b/.hgignore Wed Aug 06 16:30:43 2008 -0400 @@ -6,3 +6,5 @@ *~ org_classpath_icedtea_*.h *.log +bin/* +lib/*
--- a/src/jni-common.c Wed Aug 06 14:55:15 2008 -0400 +++ b/src/jni-common.c Wed Aug 06 16:30:43 2008 -0400 @@ -1,40 +1,39 @@ /* jni-common.c - Copyright (C) 2008 Red Hat, Inc. + 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. + This file is part of IcedTea. -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. + 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. -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. + 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. -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. + 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. -*/ - + 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. + */ #include "jni-common.h" @@ -89,17 +88,53 @@ void* getJavaPointer(JNIEnv* env, jobject obj, char* name) { /* + * on a 64 bit machine, the value of the long is 64 bits, which should be the pointer + * size and everything should be ok + * + * So the problem is 32 bit architectures: + * * A reference snippet * int a_int = 0x1020; long a_long = 0x102030; long long a_long_long = 0x1020304150607080; - printf("size of int: %d\nsize of long: %d\nsize of long long: %d\n", sizeof(int), sizeof(long), sizeof(long long)); + printf("size of int: %d\nsize of long: %d\nsize of long long: %d\n", + sizeof(int), sizeof(long), sizeof(long long)); printf("int to long long: %X -> %llX\n", a_int, (long long) a_int); printf("long long to int: %llX -> %X\n", a_long_long, (int)a_long_long); * this shows that long long -> int does a bitwise mask to get the lower order bits only - * FIXME what about endianness? will it get the opposite bits? + * this is a guess at how it works: + * + * raw data in register is 0x 10203040 50607080 + * 32 bits 32 bits + * + * we are interested in the 50607080 part of data + * + * Big endian: + * 10 <-- Pointer < 32bit pointer (for an int) + * 20 < + * 30 < + * 40 < + * 50 + * 60 + * 70 + * 80 + * (for big endian, will need to do masking and shifting) + * + * + * Little Endian + * 80 <-- Pointer < 32bit pointer (for an int) + * 70 < + * 60 < + * 50 < + * 40 + * 30 + * 20 + * 10 + * (so little endian works by default!) + * + * */ /*
--- a/src/org/classpath/icedtea/pulseaudio/EventLoop.java Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/EventLoop.java Wed Aug 06 16:30:43 2008 -0400 @@ -153,8 +153,14 @@ if (Thread.interrupted()) { native_shutdown(); - System.out.println(this.getClass().getName() - + ": shutting down"); + // System.out.println(this.getClass().getName() + // + ": shutting down"); + + // clean up the listeners + synchronized (contextListeners) { + contextListeners.clear(); + } + return; } @@ -181,8 +187,8 @@ public void update(int status) { synchronized (threadLock) { - System.out.println(this.getClass().getName() - + ".update() called! status = " + status); + // System.out.println(this.getClass().getName() + // + ".update() called! status = " + status); this.status = status; switch (status) { case 0: @@ -196,7 +202,6 @@ case 3: break; case 4: - System.out.println(this.getClass().getName() + " is ready!"); fireEvent(new ContextEvent(Type.READY)); break; case 5: @@ -212,26 +217,22 @@ } private void fireEvent(final ContextEvent e) { - System.out.println(this.getClass().getName() + "firing event: " - + e.getType().toString()); - System.out.println("notifying listeners"); +// System.out.println(this.getClass().getName() + "firing event: " +// + e.getType().toString()); synchronized (contextListeners) { - System.out.println(contextListeners.size()); +// System.out.println(contextListeners.size()); for (ContextListener listener : contextListeners) { listener.update(e); - System.out.println("updating listeners"); } } } public void setVolume(long streamPointer, int volume) { - synchronized (threadLock) { native_set_sink_volume(streamPointer, volume); } - } public long getContextPointer() {
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 06 16:30:43 2008 -0400 @@ -224,7 +224,7 @@ + ": interrupted while waiting for eventloop to finish"); } - System.out.println(this.getClass().getName() + ": closed"); + // System.out.println(this.getClass().getName() + ": closed"); this.isOpen = false; fireEvent(new LineEvent(this, LineEvent.Type.CLOSE, @@ -249,7 +249,7 @@ @Override public javax.sound.sampled.Line.Info getLineInfo() { - System.out.println("DEBUG: PulseAudioMixer.getLineInfo() called"); + // System.out.println("DEBUG: PulseAudioMixer.getLineInfo() called"); return new Line.Info(PulseAudioMixer.class); } @@ -308,47 +308,33 @@ eventLoop.setAppName(appName); eventLoop.setServer(host); - - ContextListener eventListener = new ContextListener() { - + ContextListener generalEventListener = new ContextListener() { @Override public void update(ContextEvent e) { - System.out.println("General listener was notified"); - System.out.println(" eventType: " + e.getType()); if (e.getType() == ContextEvent.Type.READY) { - System.out.println("firing event ready.."); fireEvent(new LineEvent(PulseAudioMixer.this, LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED)); - System.out.println("done"); } else if (e.getType() == ContextEvent.Type.FAILED || e.getType() == ContextEvent.Type.TERMINATED) { fireEvent(new LineEvent(PulseAudioMixer.this, LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED)); } - System.out.println("general listener returning"); } - }; - eventLoop.addContextListener(eventListener); - - + eventLoop.addContextListener(generalEventListener); + final Semaphore ready = new Semaphore(0); ContextListener initListener = new ContextListener() { @Override public void update(ContextEvent e) { - System.out.println("specific listener notifed"); - 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"); } - System.out.println("specific listener returning"); } }; @@ -361,7 +347,7 @@ eventLoopThread.start(); try { - System.out.println("waiting..."); +// System.out.println("waiting..."); ready.acquire(); if (eventLoop.getStatus() != 4) { /* @@ -376,17 +362,15 @@ throw new LineUnavailableException(); } eventLoop.removeContextListener(initListener); - System.out.println("got signal"); +// System.out.println("got signal"); } catch (InterruptedException e) { - System.out.println("PROBLEM: got interrupted"); + System.out.println("PulseAudioMixer: got interrupted while waiting for the EventLoop to initialize"); } - System.out.println(this.getClass().getName() + ": ready"); +// System.out.println(this.getClass().getName() + ": ready"); this.isOpen = true; - - } @Override @@ -395,18 +379,15 @@ } /* - * Should this method be synchronized? I had a few reasons, but i forgot them - * Pros: - * - Thread safety? + * Should this method be synchronized? I had a few reasons, but i forgot + * them Pros: - Thread safety? * - * Cons: - * - eventListeners are run from other threads, if those then call fireEvent - * while a method is waiting on a listener, this synchronized block wont - * be entered: deadlock! + * Cons: - eventListeners are run from other threads, if those then call + * fireEvent while a method is waiting on a listener, this synchronized + * block wont be entered: deadlock! * */ private void fireEvent(final LineEvent e) { - System.out.println(this.getClass().getName() + "fireEvent(): firing event"); synchronized (lineListeners) { for (LineListener lineListener : lineListeners) { lineListener.update(e);
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioMixerInfo.java Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioMixerInfo.java Wed Aug 06 16:30:43 2008 -0400 @@ -53,7 +53,7 @@ // the "getInstance()" method synchronized public static PulseAudioMixerInfo getInfo() { if (_instance == null) { - _instance = new PulseAudioMixerInfo("PulseAudio Mixer", "openjdk", + _instance = new PulseAudioMixerInfo("PulseAudio Mixer", "icedtea", "the ear-candy mixer", "0.01"); }
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Wed Aug 06 16:30:43 2008 -0400 @@ -205,15 +205,12 @@ this.addStreamListener(new StreamListener() { @Override public void update(StreamEvent e) { - System.out.println(this.getClass().getName() - + " waiting to stream to become ready"); if (e.getType() == StreamEvent.Type.READY) { semaphore.release(); } } }); - System.out.println("about to open stream"); native_start(); } @@ -223,7 +220,7 @@ // throw new LineUnavailableException("unable to prepare // stream"); } - System.out.println(this.getClass().getName() + "stream is ready"); + } /* @@ -369,8 +366,6 @@ public void update(int status) { synchronized (eventLoop.threadLock) { - System.out.println(this.getClass().getCanonicalName() - + ".update() called! status = " + status); switch (status) { case 0: fireEvent(new StreamEvent(StreamEvent.Type.UNCONNECTED));
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Wed Aug 06 16:30:43 2008 -0400 @@ -90,10 +90,6 @@ private native void openStream(String encoding, float rate, int size, int channels, boolean bigEndian, int bufferSize); - static { - System.loadLibrary("PulseAudioSourceDataLine"); - } - @Override public int read(byte[] b, int off, int len) { readFromStream(b, off, len);
--- a/src/org_classpath_icedtea_pulseaudio_EventLoop.c Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org_classpath_icedtea_pulseaudio_EventLoop.c Wed Aug 06 16:30:43 2008 -0400 @@ -1,40 +1,39 @@ /* org_classpath_icedtea_pulseaudio_EventLoop.c - Copyright (C) 2008 Red Hat, Inc. + 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. + This file is part of IcedTea. -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. + 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. -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. + 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. -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. + 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. -*/ - + 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. + */ #include <pulse/pulseaudio.h> @@ -52,13 +51,11 @@ 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; - printf("context state changed to %d\n", pa_context_get_state(context)); + // printf("context state changed to %d\n", pa_context_get_state(context)); /* Call the 'update' method in java * to handle all java-side events @@ -89,7 +86,7 @@ assert(appName != NULL); - printf("native_setup() called\n"); + // printf("native_setup() called\n"); pa_mainloop *mainloop = pa_mainloop_new(); assert(mainloop != NULL); pa_mainloop_api *mainloop_api = pa_mainloop_get_api(mainloop); @@ -102,7 +99,7 @@ if (string_appName == NULL) { return; /* a OutOfMemoryError thrown by vm */ } - printf("using appName : %s\n", string_appName); + // printf("using appName : %s\n", string_appName); context = pa_context_new(mainloop_api, string_appName); assert(mainloop != NULL); (*env)->ReleaseStringUTFChars(env, appName, string_appName); @@ -128,17 +125,17 @@ free(java_context); return; /* OutOfMemoryError */ } - printf("About to connect to server: %s\n", string_server); + // printf("About to connect to server: %s\n", string_server); pa_context_connect(context, string_server, 0, NULL); (*env)->ReleaseStringUTFChars(env, appName, string_server); } else { - printf("using default server\n"); + // printf("using default server\n"); pa_context_connect(context, NULL, 0, NULL); } setJavaPointer(env, obj, "mainloopPointer", mainloop); setJavaPointer(env, obj, "contextPointer", context); - printf("native_setup() returning\n"); + // printf("native_setup() returning\n"); return; } @@ -184,7 +181,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); @@ -204,11 +201,11 @@ free(java_context); - printf("native_shutdown() returning\n"); - setJavaPointer(env, obj, "mainloopPointer", NULL); setJavaPointer(env, obj, "contextPointer", NULL); + // printf("native_shutdown() returning\n"); + } static void sink_input_volume_change_complete(pa_context* contest, int success,
--- a/src/org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine.c Wed Aug 06 14:55:15 2008 -0400 +++ b/src/org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine.c Wed Aug 06 16:30:43 2008 -0400 @@ -60,7 +60,7 @@ assert(stream); assert(userdata); - printf("entering stream_state_change_callback\n"); + // printf("entering stream_state_change_callback\n"); java_context_t* java_context = (java_context_t*)userdata; JNIEnv* env; @@ -68,7 +68,6 @@ /* needed so we can create a stream from another thread */ if (pa_stream_get_state(stream) == PA_STREAM_CREATING) { - printf("java thread\n"); env = java_context->env; } else { env = pulse_thread_env; @@ -76,7 +75,7 @@ jobject obj = java_context->obj; - printf("stream state changed to %d\n", pa_stream_get_state(stream)); + // printf("stream state changed to %d\n", pa_stream_get_state(stream)); /* Call the 'update' method in java * to handle all java-side events @@ -92,10 +91,10 @@ return; } - printf("calling update on java\n"); + // printf("calling update on java\n"); (*env)->CallVoidMethod(env, obj, mid, pa_stream_get_state(stream)); - printf("returning form stream_state_change_callback\n"); + // printf("returning form stream_state_change_callback\n"); return; } @@ -110,7 +109,7 @@ //TODO: Need to deal with the buffer size. Currently ignored - printf("entering native_open\n"); + // printf("entering native_open\n"); java_context_t* java_context = malloc(sizeof(java_context)); java_context->env = env; java_context->obj = (*env)->NewGlobalRef(env, obj); @@ -137,7 +136,7 @@ } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 0)) { sample_spec.format = PA_SAMPLE_S32LE; } else { - printf("error in open"); + printf("error in open\n"); throwByName(env, "IllegalArgumentException", "Invalid format"); /* clean up */ free(java_context); @@ -155,7 +154,7 @@ if (stream_name == NULL) { return; /* OutOfMemoryError */ } - printf("About to create stream: %s\n", stream_name); + // printf("About to create stream: %s\n", stream_name); pa_stream* stream = pa_stream_new(context, stream_name, &sample_spec, NULL); assert(stream != NULL); (*env)->ReleaseStringUTFChars(env, name, stream_name); @@ -163,7 +162,7 @@ pa_stream_set_state_callback(stream, stream_state_change_callback, java_context); setJavaPointer(env, obj, "streamPointer", stream); - printf("returning from native_open\n"); + // printf("returning from native_open\n"); } @@ -229,8 +228,6 @@ */ JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_PulseAudioSourceDataLine_native_1start (JNIEnv *env, jobject obj) { - printf("start called\n"); - pa_stream *stream = (pa_stream*)getJavaPointer(env, obj, "streamPointer"); pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL); @@ -283,7 +280,6 @@ } else { pa_operation_unref(o); } - - + }