changeset 2620:1364a03b0f2b

PR1741: Replace pulse audio enums with static longs. 2011-06-16 Denis Lila <dlila@redhat.com> * Makefile.am: Add ContextEvent to the list of pulse audio classes that need javah run on them. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/ContextEvent.java (Type): Remove and replace with... (UNCONNECTED, CONNECTING, AUTHORIZING, SETTING_NAME, READY, FAILED, TERMINATED): New static long variables replacing enum Type. (init_constants): New native method to initialize the above variables. (checkNativeEnumReturn): Make sure that the input is one of the longs representing the type of ContextEvent. (type): Change type from Type to long. (ContextEvent): Take a long argument, instead of a Type. (getType): Return a long, not a Type. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java (status): Change from int to long. (native_set_sink_volume): Remove. It was unimplemented in the JNI side. (getStatus): Return long instead of int. (update): Replace int argument with long argument. Remove the switch statement. (setVolume): Remove. Unused. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java (State): Remove and replace with... (Running, Done, Cancelled): Static longs, enumerating the possible operation states. (init_constants): New native method to initialize the above variables. (checkNativeOperationState): Make sure that the input is one of the longs representing the operation state. (native_get_state): Change return type from int to long. (getState): Change return type to long; remove switch. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java Remove the names of enums from the names of constants since most of them were changed to static longs. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Same changes as in PulseAudioDataLine.java. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java (State): Remove and replace with... (UNCONNECTED, CREATING, READY, FAILED, TERMINATED): New static long variables replacing enum Type. (init_constants): New native method to initialize the above variables. (checkNativeStreamState): Make sure that the input is one of the longs representing the kind of StreamState. (native_pa_stream_get_state): Change the return from int to long. (getState): Remove the switch. * pulseaudio/src/native/jni-common.h (SET_JAVA_STATIC_LONG_FIELD_TO_PA_ENUM): Macro that sets one of the java static longs to the corresponding pa_constant. * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_ContextEvent.c New file. (SET_CONTEXT_ENUM): Macro that sets the ContextEvent types. (Java_org_classpath_icedtea_pulseaudio_ContextEvent_init_1constants): Implementation of ContextEvent.init_constants. * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c (context_change_callback): Change the fourth argument of GetMethodID to "(J)V" to reflect the change in the signature of EventLoop.update. * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Operation.c (SET_OP_ENUM): Macro that sets the operation types. (Java_org_classpath_icedtea_pulseaudio_Operation_init_1constants): Implementation of Operation.init_constants. (Java_org_classpath_icedtea_pulseaudio_Operation_native_1get_1state): Change return type to jlong. * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c (SET_STREAM_ENUM): Macro that sets the stream states. (Java_org_classpath_icedtea_pulseaudio_Stream_init_1constants): Implementation of Stream.init_constants. (Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1get_1state): Change return type to jlong.
author Andrew John Hughes <gnu_andrew@member.fsf.org>
date Wed, 02 Mar 2016 05:23:53 +0000
parents 7f9a42012be7
children ae07c41dc3c2
files ChangeLog Makefile.am pulseaudio/src/java/org/classpath/icedtea/pulseaudio/ContextEvent.java pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java pulseaudio/src/native/jni-common.h pulseaudio/src/native/org_classpath_icedtea_pulseaudio_ContextEvent.c pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Operation.c pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c
diffstat 13 files changed, 313 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jun 28 13:27:42 2012 -0400
+++ b/ChangeLog	Wed Mar 02 05:23:53 2016 +0000
@@ -1,3 +1,71 @@
+2011-06-16  Denis Lila  <dlila@redhat.com>
+
+	* Makefile.am: Add ContextEvent to the list of pulse audio classes that
+	need javah run on them.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/ContextEvent.java
+	(Type): Remove and replace with...
+	(UNCONNECTED, CONNECTING, AUTHORIZING, SETTING_NAME, READY, FAILED,
+	 TERMINATED): New static long variables replacing enum Type.
+	(init_constants): New native method to initialize the above variables.
+	(checkNativeEnumReturn): Make sure that the input is one of the longs
+	representing the type of ContextEvent.
+	(type): Change type from Type to long.
+	(ContextEvent): Take a long argument, instead of a Type.
+	(getType): Return a long, not a Type.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java
+	(status): Change from int to long.
+	(native_set_sink_volume): Remove. It was unimplemented in the JNI side.
+	(getStatus): Return long instead of int.
+	(update): Replace int argument with long argument. Remove the switch
+	statement.
+	(setVolume): Remove. Unused.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java
+	(State): Remove and replace with...
+	(Running, Done, Cancelled): Static longs, enumerating the possible
+	operation states.
+	(init_constants): New native method to initialize the above variables.
+	(checkNativeOperationState): Make sure that the input is one of the longs
+	representing the operation state.
+	(native_get_state): Change return type from int to long.
+	(getState): Change return type to long; remove switch.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java
+	Remove the names of enums from the names of constants since most of them
+	were changed to static longs.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java
+	Same changes as in PulseAudioDataLine.java.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java
+	(State): Remove and replace with...
+	(UNCONNECTED, CREATING, READY, FAILED, TERMINATED): New static long variables
+	replacing enum Type.
+	(init_constants): New native method to initialize the above variables.
+	(checkNativeStreamState): Make sure that the input is one of the longs
+	representing the kind of StreamState.
+	(native_pa_stream_get_state): Change the return from int to long.
+	(getState): Remove the switch.
+	* pulseaudio/src/native/jni-common.h
+	(SET_JAVA_STATIC_LONG_FIELD_TO_PA_ENUM): Macro that sets one of the java
+	 static longs to the corresponding pa_constant.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_ContextEvent.c
+	New file.
+	(SET_CONTEXT_ENUM): Macro that sets the ContextEvent types.
+	(Java_org_classpath_icedtea_pulseaudio_ContextEvent_init_1constants):
+	Implementation of ContextEvent.init_constants.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c
+	(context_change_callback): Change the fourth argument of GetMethodID
+	to "(J)V" to reflect the change in the signature of EventLoop.update.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Operation.c
+	(SET_OP_ENUM): Macro that sets the operation types.
+	(Java_org_classpath_icedtea_pulseaudio_Operation_init_1constants):
+	Implementation of Operation.init_constants.
+	(Java_org_classpath_icedtea_pulseaudio_Operation_native_1get_1state):
+	Change return type to jlong.
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c
+	(SET_STREAM_ENUM): Macro that sets the stream states.
+	(Java_org_classpath_icedtea_pulseaudio_Stream_init_1constants):
+	Implementation of Stream.init_constants.
+	(Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1get_1state):
+	Change return type to jlong.
+
 2012-06-28  Omair Majid  <omajid@redhat.com>
 
 	PR1050: Stream objects not garbage collected
--- a/Makefile.am	Thu Jun 28 13:27:42 2012 -0400
+++ b/Makefile.am	Wed Mar 02 05:23:53 2016 +0000
@@ -1937,6 +1937,8 @@
 	  org.classpath.icedtea.pulseaudio.PulseAudioSourcePort
 	$(BOOT_DIR)/bin/javah -d $(PULSE_JAVA_NATIVE_BUILDDIR) -classpath $(PULSE_JAVA_CLASS_DIR) \
 	  org.classpath.icedtea.pulseaudio.PulseAudioTargetPort
+	$(BOOT_DIR)/bin/javah -d $(PULSE_JAVA_NATIVE_BUILDDIR) -classpath $(PULSE_JAVA_CLASS_DIR) \
+	  -J-Xbootclasspath/p:$(PULSE_JAVA_CLASS_DIR) org.classpath.icedtea.pulseaudio.ContextEvent;
 	mkdir -p stamps
 	touch $@
 
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/ContextEvent.java	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/ContextEvent.java	Wed Mar 02 05:23:53 2016 +0000
@@ -37,32 +37,68 @@
 
 package org.classpath.icedtea.pulseaudio;
 
+import java.util.Arrays;
+
 /**
  * This class encapsulates a change in the PulseAudio's connection context.
  * 
  * When this event is fired, something has happened to the connection of this
  * program to the PulseAudio server.
- * 
  */
-
 class ContextEvent {
-
+    // There are certain enumerations from pulse audio that we need to use in
+    // the java side. For all of these, we declare static longs in the proper
+    // java classes and we use static native methods to initialize them to
+    // the values used by pulse audio. This makes us immune to changes in
+    // the integer values of the enum symbols in pulse audio.
     /**
      *  Basically, what is the new state of the context
-     * 
+     *  These will be initialized to the proper values in the JNI.
      */
-    public static enum Type {
-        UNCONNECTED, CONNECTING, AUTHORIZING, SETTING_NAME, READY, FAILED, TERMINATED
+    static long UNCONNECTED  = -1,
+                CONNECTING   = -1,
+                AUTHORIZING  = -1,
+                SETTING_NAME = -1,
+                READY        = -1,
+                FAILED       = -1,
+                TERMINATED   = -1;
+
+    private static native void init_constants();
+
+    static {
+        SecurityWrapper.loadNativeLibrary();
+        init_constants();
     }
 
-    private Type type;
-
-    public ContextEvent(Type type) {
-        this.type = type;
+    /**
+     * Throws an IllegalStateException if value is not one of the above
+     * context events. We do this for all pulse audio enumerations that
+     * we need to use in the java side. If pulse audio decides to add
+     * new events/states, we need to add them to the classes. The exception
+     * will let us know.
+     * return the input if there is no error
+     *
+     * @param value is the context event to be checked against one of the known
+     *        events.
+     * @return value if it is a known event. Otherwise throw an exception.
+     */
+    public static long checkNativeEnumReturn(long value) {
+        if (!Arrays.asList(
+                UNCONNECTED, CONNECTING, AUTHORIZING, SETTING_NAME,
+                READY, FAILED, TERMINATED
+            ).contains(value)) {
+            throw new IllegalStateException("Illegal constant for ContextEvent: " + value);
+        }
+        return value;
     }
 
-    public Type getType() {
+    private long type;
+
+    public ContextEvent(long type) {
+        this.type = checkNativeEnumReturn(type);
+    }
+
+    public long getType() {
         return type;
     }
-
 }
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Wed Mar 02 05:23:53 2016 +0000
@@ -40,14 +40,12 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.classpath.icedtea.pulseaudio.ContextEvent.Type;
+import org.classpath.icedtea.pulseaudio.ContextEvent;
 import org.classpath.icedtea.pulseaudio.Debug.DebugLevel;
 
 /**
  * This class wraps pulseaudio's event loop. It also holds the lock used in the
  * rest of pulse-java
- * 
- * 
  */
 
 final class EventLoop implements Runnable {
@@ -70,7 +68,7 @@
     private String appName;
     private String serverString;
 
-    private int status;
+    private long status;
     // private boolean eventLoopIsRunning = false;
 
     private List<String> targetPortNameList = new ArrayList<String>();
@@ -89,18 +87,12 @@
 
     private native void native_shutdown();
 
-    private native void native_set_sink_volume(byte[] streamPointer, int volume);
-
     /*
      * These fields hold pointers
      */
     private byte[] contextPointer;
     private byte[] mainloopPointer;
 
-    /*
-     * 
-     */
-
     static {
         SecurityWrapper.loadNativeLibrary();
     }
@@ -171,42 +163,21 @@
         }
     }
 
-    int getStatus() {
+    long getStatus() {
         return this.status;
     }
 
-    void update(int status) {
+    void update(long status) {
         synchronized (threadLock) {
             // System.out.println(this.getClass().getName()
             // + ".update() called! status = " + status);
             this.status = status;
-            switch (status) {
-            case 0:
-                fireEvent(new ContextEvent(Type.UNCONNECTED));
-                break;
-            case 1:
-                fireEvent(new ContextEvent(Type.CONNECTING));
-                break;
-            case 2:
-                // no op
-                break;
-            case 3:
-                // no op
-                break;
-            case 4:
-                fireEvent(new ContextEvent(Type.READY));
-                break;
-            case 5:
-                fireEvent(new ContextEvent(Type.FAILED));
-                Debug.println(DebugLevel.Warning,
-                        "EventLoop.update(): Context failed");
-                break;
-            case 6:
-                fireEvent(new ContextEvent(Type.TERMINATED));
-                break;
-            default:
+            fireEvent(new ContextEvent(status));
+        }
 
-            }
+        if (status == ContextEvent.FAILED) {
+            Debug.println(DebugLevel.Warning,
+                          "EventLoop.update(): Context failed");
         }
     }
 
@@ -223,12 +194,6 @@
 
     }
 
-    void setVolume(byte[] streamPointer, int volume) {
-        synchronized (threadLock) {
-            native_set_sink_volume(streamPointer, volume);
-        }
-    }
-
     byte[] getContextPointer() {
         return contextPointer;
     }
@@ -250,7 +215,7 @@
 
         op.waitForCompletion();
 
-        assert (op.getState() == Operation.State.Done);
+        assert (op.getState() == Operation.DONE);
 
         op.releaseReference();
         return targetPortNameList;
@@ -265,7 +230,7 @@
 
         op.waitForCompletion();
 
-        assert (op.getState() == Operation.State.Done);
+        assert (op.getState() == Operation.DONE);
 
         op.releaseReference();
         return sourcePortNameList;
@@ -278,5 +243,4 @@
     public void sink_callback(String name) {
         targetPortNameList.add(name);
     }
-
 }
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Wed Mar 02 05:23:53 2016 +0000
@@ -37,6 +37,8 @@
 
 package org.classpath.icedtea.pulseaudio;
 
+import java.util.Arrays;
+
 /**
  * Encapsulates a pa_operation object
  * 
@@ -57,19 +59,33 @@
     private byte[] operationPointer;
     private EventLoop eventLoop;
 
-    public enum State {
-        Running, Done, Cancelled,
-    }
+    // These should never be written to in java. They will be initialized
+    // properly in native code.
+    public static long RUNNING   = -1,
+                       DONE      = -1,
+                       CANCELLED = -1;
+
+    private static native void init_constants();
 
     static {
         SecurityWrapper.loadNativeLibrary();
+        init_constants();
+    }
+
+    // If value is not one of RUNNING, DONE, CANCELLED, throw an
+    // IllegalStateException. Otherwise return the input.
+    private static long checkNativeOperationState(long value) {
+        if (!Arrays.asList(RUNNING, DONE, CANCELLED).contains(value)) {
+            throw new IllegalStateException("Unknown operation state: " + value);
+        }
+        return value;
     }
 
     private native void native_ref();
 
     private native void native_unref();
 
-    private native int native_get_state();
+    private native long native_get_state();
 
     Operation(byte[] operationPointer) {
         assert (operationPointer != null);
@@ -113,23 +129,11 @@
         return false;
     }
 
-    State getState() {
+    long getState() {
         assert (operationPointer != null);
-        int state;
         synchronized (eventLoop.threadLock) {
-            state = native_get_state();
+            return checkNativeOperationState(native_get_state());
         }
-        switch (state) {
-        case 0:
-            return State.Running;
-        case 1:
-            return State.Done;
-        case 2:
-            return State.Cancelled;
-        default:
-            throw new IllegalStateException("Invalid operation State");
-        }
-
     }
 
     /**
@@ -142,7 +146,7 @@
         boolean interrupted = false;
         do {
             synchronized (eventLoop.threadLock) {
-                if (getState() == Operation.State.Done) {
+                if (getState() == DONE) {
                     return;
                 }
                 try {
@@ -152,7 +156,7 @@
                     interrupted = true;
                 }
             }
-        } while (getState() != State.Done);
+        } while (getState() != DONE);
 
         // let the caller know about the interrupt
         if (interrupted) {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java	Wed Mar 02 05:23:53 2016 +0000
@@ -170,7 +170,7 @@
                      * the listener is guaranteed to have run
                      */
 
-                    if (stream.getState() == Stream.State.READY) {
+                    if (stream.getState() == Stream.READY) {
                         if (sendEvents) {
                             fireLineEvent(new LineEvent(
                                     PulseAudioDataLine.this,
@@ -178,8 +178,8 @@
                         }
                         semaphore.release();
 
-                    } else if (stream.getState() == Stream.State.TERMINATED
-                            || stream.getState() == Stream.State.FAILED) {
+                    } else if (stream.getState() == Stream.TERMINATED
+                            || stream.getState() == Stream.FAILED) {
                         if (sendEvents) {
                             fireLineEvent((new LineEvent(
                                     PulseAudioDataLine.this,
@@ -273,7 +273,7 @@
         try {
             semaphore.acquire();
             synchronized (eventLoop.threadLock) {
-                if (stream.getState() != Stream.State.READY) {
+                if (stream.getState() != Stream.READY) {
                     stream.disconnect();
                     stream.free();
                     throw new LineUnavailableException(
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Wed Mar 02 05:23:53 2016 +0000
@@ -658,11 +658,11 @@
         ContextListener generalEventListener = new ContextListener() {
             @Override
             public void update(ContextEvent e) {
-                if (e.getType() == ContextEvent.Type.READY) {
+                if (e.getType() == ContextEvent.READY) {
                     fireEvent(new LineEvent(PulseAudioMixer.this,
                             LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED));
-                } else if (e.getType() == ContextEvent.Type.FAILED
-                        || e.getType() == ContextEvent.Type.TERMINATED) {
+                } else if (e.getType() == ContextEvent.FAILED
+                        || e.getType() == ContextEvent.TERMINATED) {
                     fireEvent(new LineEvent(PulseAudioMixer.this,
                             LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED));
                 }
@@ -677,9 +677,9 @@
 
             @Override
             public void update(ContextEvent e) {
-                if (e.getType() == ContextEvent.Type.READY
-                        || e.getType() == ContextEvent.Type.FAILED
-                        || e.getType() == ContextEvent.Type.TERMINATED) {
+                if (e.getType() == ContextEvent.READY
+                        || e.getType() == ContextEvent.FAILED
+                        || e.getType() == ContextEvent.TERMINATED) {
                     ready.release();
                 }
             }
@@ -701,7 +701,7 @@
         try {
             // System.out.println("waiting...");
             ready.acquire();
-            if (eventLoop.getStatus() != 4) {
+            if (eventLoop.getStatus() != ContextEvent.READY) {
                 /*
                  * when exiting, wait for the thread to end otherwise we get one
                  * thread that inits the singleton with new data and the old
@@ -716,8 +716,7 @@
             eventLoop.removeContextListener(initListener);
             // System.out.println("got signal");
         } catch (InterruptedException e) {
-            System.out
-                    .println("PulseAudioMixer: got interrupted while waiting for the EventLoop to initialize");
+            System.out.println("PulseAudioMixer: got interrupted while waiting for the EventLoop to initialize");
         }
 
         // System.out.println(this.getClass().getName() + ": ready");
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java	Wed Mar 02 05:23:53 2016 +0000
@@ -37,6 +37,7 @@
 
 package org.classpath.icedtea.pulseaudio;
 
+import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -98,12 +99,42 @@
         public void update();
     }
 
-    public static enum State {
-        UNCONNECTED, CREATING, READY, FAILED, TERMINATED,
+    // see comments in ContextEvent.java and Operation.java
+    // These are the possible stream states.
+    // TODO: perhaps we should do this for stream flags too.
+    public static long UNCONNECTED = -1,
+                       CREATING    = -1,
+                       READY       = -1,
+                       FAILED      = -1,
+                       TERMINATED  = -1;
+
+    private static native void init_constants();
+
+    // Throw an IllegalStateException if value is not one of the possible
+    // states. Otherwise return the input.
+    public static long checkNativeStreamState(long value) {
+        if (!Arrays.asList(UNCONNECTED, CREATING, READY, FAILED, TERMINATED)
+                .contains(value)) {
+            throw new IllegalStateException("Illegal constant for ContextEvent: " + value);
+        }
+        return value;
     }
 
+    // We don't change this to static longs like we did with all other pulse
+    // audio enums mirrored in java because we never use the pulse audio
+    // integer value of formats on the java side. In java, the handling of
+    // formats is strictly symbolic and string based. For that, enums are
+    // better.
     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
     }
 
     public static final String DEFAULT_DEVICE = null;
@@ -115,6 +146,7 @@
 
     static {
         SecurityWrapper.loadNativeLibrary();
+        init_constants();
     }
 
     private Format format;
@@ -136,7 +168,7 @@
 
     private native void native_pa_stream_unref();
 
-    private native int native_pa_stream_get_state();
+    private native long native_pa_stream_get_state();
 
     private native byte[] native_pa_stream_get_context();
 
@@ -388,23 +420,8 @@
         }
     }
 
-    Stream.State getState() {
-        int state = native_pa_stream_get_state();
-        switch (state) {
-        case 0:
-            return State.UNCONNECTED;
-        case 1:
-            return State.CREATING;
-        case 2:
-            return State.READY;
-        case 3:
-            return State.FAILED;
-        case 4:
-            return State.TERMINATED;
-        default:
-            throw new IllegalStateException("invalid stream state");
-        }
-
+    long getState() {
+        return checkNativeStreamState(native_pa_stream_get_state());
     }
 
     byte[] getContextPointer() {
--- a/pulseaudio/src/native/jni-common.h	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/native/jni-common.h	Wed Mar 02 05:23:53 2016 +0000
@@ -39,11 +39,20 @@
 #define _JNI_COMMON_H
 
 #include <jni.h>
+
 /*
- * This file contains some commonly used functions 
- * 
+ * This file contains some commonly used functions
+ *
  */
 
+// Sets the field with name field_name from jclass clz to pa_prefix_field_name.
+#define SET_JAVA_STATIC_LONG_FIELD_TO_PA_ENUM(env, clz, pa_prefix, field_name)    \
+    do {                                                                          \
+        jfieldID fid = (*env)->GetStaticFieldID(env, clz, #field_name, "J");      \
+        assert(fid);                                                              \
+        (*env)->SetStaticLongField(env, clz, fid, PA_##pa_prefix##_##field_name); \
+    } while(0);
+
 typedef struct java_context_t {
     JNIEnv* env;
     jobject obj;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_ContextEvent.c	Wed Mar 02 05:23:53 2016 +0000
@@ -0,0 +1,61 @@
+/* org_classpath_icedtea_pulseaudio_EventLoop.c
+ Copyright (C) 2011 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.
+ */
+
+#include <pulse/pulseaudio.h>
+
+#include "org_classpath_icedtea_pulseaudio_ContextEvent.h"
+#include "jni-common.h"
+
+#define SET_CONTEXT_ENUM(env, clz, name) \
+    SET_JAVA_STATIC_LONG_FIELD_TO_PA_ENUM(env, clz, CONTEXT, name)
+
+/*
+ * Class:     org_classpath_icedtea_pulseaudio_ContextEvent
+ * Method:    init_constants
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_ContextEvent_init_1constants
+  (JNIEnv *env, jclass clz) {
+    SET_CONTEXT_ENUM(env, clz, UNCONNECTED);
+    SET_CONTEXT_ENUM(env, clz, CONNECTING);
+    SET_CONTEXT_ENUM(env, clz, AUTHORIZING);
+    SET_CONTEXT_ENUM(env, clz, SETTING_NAME);
+    SET_CONTEXT_ENUM(env, clz, READY);
+    SET_CONTEXT_ENUM(env, clz, FAILED);
+    SET_CONTEXT_ENUM(env, clz, TERMINATED);
+}
+
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Wed Mar 02 05:23:53 2016 +0000
@@ -106,7 +106,7 @@
      */
     jclass cls = (*env)->GetObjectClass(env, obj);
     assert(cls);
-    jmethodID mid = (*env)->GetMethodID(env, cls, "update", "(I)V");
+    jmethodID mid = (*env)->GetMethodID(env, cls, "update", "(J)V");
     assert(mid);
     (*env)->CallVoidMethod(env, obj, mid, pa_context_get_state(context));
     return;
@@ -281,7 +281,7 @@
     } else {
         pa_operation_unref(o);
     }
-    
+
     pa_context_unref(context);
     (*env)->DeleteGlobalRef(env, java_context->obj);
 
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Operation.c	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Operation.c	Wed Mar 02 05:23:53 2016 +0000
@@ -40,6 +40,22 @@
 #include "jni-common.h"
 #include <pulse/pulseaudio.h>
 
+#define SET_OP_ENUM(env, clz, name) \
+    SET_JAVA_STATIC_LONG_FIELD_TO_PA_ENUM(env, clz, OPERATION, name)
+
+/*
+ * Class:     org_classpath_icedtea_pulseaudio_Operation
+ * Method:    init_constants
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_Operation_init_1constants
+  (JNIEnv *env, jclass clz) {
+    SET_OP_ENUM(env, clz, RUNNING);
+    SET_OP_ENUM(env, clz, DONE);
+    SET_OP_ENUM(env, clz, CANCELLED);
+}
+
+
 /*
  * Class:     org_classpath_icedtea_pulseaudio_Operation
  * Method:    native_ref
@@ -65,7 +81,6 @@
     pa_operation* operation = (pa_operation*) getJavaPointer(env, obj, "operationPointer");
     assert(operation);
     pa_operation_unref(operation);
-
 }
 
 /*
@@ -73,11 +88,11 @@
  * Method:    native_get_state
  * Signature: ()I
  */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_Operation_native_1get_1state
+JNIEXPORT jlong JNICALL Java_org_classpath_icedtea_pulseaudio_Operation_native_1get_1state
 (JNIEnv *env, jobject obj) {
 
     pa_operation* operation = (pa_operation*) getJavaPointer(env, obj, "operationPointer");
     assert(operation);
-    int state = pa_operation_get_state(operation);
+    jlong state = pa_operation_get_state(operation);
     return state;
 }
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c	Thu Jun 28 13:27:42 2012 -0400
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_Stream.c	Wed Mar 02 05:23:53 2016 +0000
@@ -240,6 +240,23 @@
 
 }
 
+#define SET_STREAM_STATE_ENUM(env, clz, state_name) \
+    SET_JAVA_STATIC_LONG_FIELD_TO_PA_ENUM(env, clz, STREAM, state_name)
+
+/*
+ * Class:     org_classpath_icedtea_pulseaudio_Stream
+ * Method:    init_constants
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_init_1constants
+  (JNIEnv *env, jclass clz) {
+    SET_STREAM_STATE_ENUM(env, clz, UNCONNECTED);
+    SET_STREAM_STATE_ENUM(env, clz, CREATING);
+    SET_STREAM_STATE_ENUM(env, clz, READY);
+    SET_STREAM_STATE_ENUM(env, clz, FAILED);
+    SET_STREAM_STATE_ENUM(env, clz, TERMINATED);
+}
+
 /*
  * Class:     org_classpath_icedtea_pulseaudio_Stream
  * Method:    native_pa_stream_new
@@ -343,7 +360,7 @@
  * Method:    native_pa_stream_get_state
  * Signature: ()I
  */
-JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1get_1state
+JNIEXPORT jlong JNICALL Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1get_1state
 (JNIEnv* env, jobject obj) {
     pa_stream* stream = (pa_stream*) getJavaPointer(env, obj, STREAM_POINTER);
     assert(stream);