Provides source and binary compatibility with PulseAudio 0.9.21 which is the current version available in Debian stable.

cusax-fix
Lyubomir Marinov 14 years ago
parent 19c9d83f29
commit 1a4676be4f

@ -4,13 +4,21 @@
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
#define _GNU_SOURCE
#include "net_java_sip_communicator_impl_neomedia_pulseaudio_PA.h"
#include <dlfcn.h>
#include <pulse/pulseaudio.h>
#include <stdint.h>
typedef pa_operation * (*pa_context_set_source_output_volume_t)(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
static void PulseAudio_contextStateCallback(pa_context *c, void *userdata);
#if (PA_MAJOR >= 1)
static jlongArray PulseAudio_getFormatInfos(JNIEnv *env, jclass clazz, jsize length, pa_format_info **formats);
#endif /* #if (PA_MAJOR >= 1) */
static void PulseAudio_infoCallback(pa_context *c, jlong i, int eol, void *userdata, jmethodID methodID);
static void PulseAudio_sinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata);
static void PulseAudio_sourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata);
@ -18,6 +26,7 @@ static void PulseAudio_stateCallback(void *userdata);
static void PulseAudio_streamRequestCallback(pa_stream *s, size_t nbytes, void *userdata);
static void PulseAudio_streamStateCallback(pa_stream *s, void *userdata);
static pa_context_set_source_output_volume_t PulseAudio_contextSetSourceOutputVolume = NULL;
static jclass PulseAudio_runnableClass = NULL;
static jmethodID PulseAudio_runnableMethodID = 0;
static jclass PulseAudio_sinkInfoCbClass = NULL;
@ -177,14 +186,21 @@ JNIEXPORT jlong JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_context_1set_1source_1output_1volume
(JNIEnv *env, jclass clazz, jlong c, jint idx, jlong volume, jobject cb)
{
return
(intptr_t)
pa_context_set_source_output_volume(
pa_operation *o;
if (PulseAudio_contextSetSourceOutputVolume)
{
o
= PulseAudio_contextSetSourceOutputVolume(
(pa_context *) (intptr_t) c,
(uint32_t) idx,
(const pa_cvolume *) (intptr_t) volume,
NULL,
NULL);
}
else
o = NULL;
return (intptr_t) o;
}
JNIEXPORT void JNICALL
@ -236,6 +252,7 @@ Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_cvolume_1set
(pa_volume_t) v);
}
#if (PA_MAJOR >= 1)
JNIEXPORT jint JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_format_1info_1get_1encoding
(JNIEnv *env, jclass clazz, jlong f)
@ -279,6 +296,16 @@ Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_format_1info_1get_1pr
}
return ret;
}
#endif /* #if (PA_MAJOR >= 1) */
JNIEXPORT jstring JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_get_1library_1version
(JNIEnv *env, jclass clazz)
{
const char *chars = pa_get_library_version();
return chars ? (*env)->NewStringUTF(env, chars) : NULL;
}
JNIEXPORT jint JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_operation_1get_1state
@ -371,11 +398,12 @@ JNIEXPORT jstring JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_sink_1info_1get_1description
(JNIEnv *env, jclass clazz, jlong i)
{
const char *description = ((pa_sink_info *) (intptr_t) i)->description;
const char *chars = ((pa_sink_info *) (intptr_t) i)->description;
return description ? (*env)->NewStringUTF(env, description) : NULL;
return chars ? (*env)->NewStringUTF(env, chars) : NULL;
}
#if (PA_MAJOR >= 1)
JNIEXPORT jlongArray JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_sink_1info_1get_1formats
(JNIEnv *env, jclass clazz, jlong i)
@ -387,6 +415,7 @@ Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_sink_1info_1get_1form
env, clazz,
sinkInfo->n_formats, sinkInfo->formats);
}
#endif /* #if (PA_MAJOR >= 1) */
JNIEXPORT jint JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_sink_1info_1get_1index
@ -406,20 +435,18 @@ JNIEXPORT jstring JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_sink_1info_1get_1monitor_1source_1name
(JNIEnv *env, jclass clazz, jlong i)
{
const char *monitorSourceName
= ((pa_sink_info *) (intptr_t) i)->monitor_source_name;
const char *chars = ((pa_sink_info *) (intptr_t) i)->monitor_source_name;
return
monitorSourceName ? (*env)->NewStringUTF(env, monitorSourceName) : NULL;
return chars ? (*env)->NewStringUTF(env, chars) : NULL;
}
JNIEXPORT jstring JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_sink_1info_1get_1name
(JNIEnv *env, jclass clazz, jlong i)
{
const char *name = ((pa_sink_info *) (intptr_t) i)->name;
const char *chars = ((pa_sink_info *) (intptr_t) i)->name;
return name ? (*env)->NewStringUTF(env, name) : NULL;
return chars ? (*env)->NewStringUTF(env, chars) : NULL;
}
JNIEXPORT jint JNICALL
@ -447,11 +474,12 @@ JNIEXPORT jstring JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_source_1info_1get_1description
(JNIEnv *env, jclass clazz, jlong i)
{
const char *description = ((pa_source_info *) (intptr_t) i)->description;
const char *chars = ((pa_source_info *) (intptr_t) i)->description;
return description ? (*env)->NewStringUTF(env, description) : NULL;
return chars ? (*env)->NewStringUTF(env, chars) : NULL;
}
#if (PA_MAJOR >= 1)
JNIEXPORT jlongArray JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_source_1info_1get_1formats
(JNIEnv *env, jclass clazz, jlong i)
@ -463,6 +491,7 @@ Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_source_1info_1get_1fo
env, clazz,
sourceInfo->n_formats, sourceInfo->formats);
}
#endif /* #if (PA_MAJOR >= 1) */
JNIEXPORT jint JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_source_1info_1get_1index
@ -482,9 +511,9 @@ JNIEXPORT jstring JNICALL
Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_source_1info_1get_1name
(JNIEnv *env, jclass clazz, jlong i)
{
const char *name = ((pa_source_info *) (intptr_t) i)->name;
const char *chars = ((pa_source_info *) (intptr_t) i)->name;
return name ? (*env)->NewStringUTF(env, name) : NULL;
return chars ? (*env)->NewStringUTF(env, chars) : NULL;
}
JNIEXPORT jint JNICALL
@ -607,9 +636,9 @@ Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_stream_1new_1with_1pr
= pa_stream_new_with_proplist(
(pa_context *) (intptr_t) c,
nameChars,
(const pa_sample_spec *) ss,
(const pa_channel_map *) map,
(pa_proplist *) p);
(const pa_sample_spec *) (intptr_t) ss,
(const pa_channel_map *) (intptr_t) map,
(pa_proplist *) (intptr_t) p);
(*env)->ReleaseStringUTFChars(env, name, nameChars);
}
return (intptr_t) stream;
@ -914,7 +943,14 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
}
}
}
return PulseAudio_streamRequestCbMethodID ? version : JNI_ERR;
if (PulseAudio_streamRequestCbMethodID)
{
PulseAudio_contextSetSourceOutputVolume
= dlsym(RTLD_DEFAULT, "pa_context_set_source_output_volume");
}
else
version = JNI_ERR;
return version;
}
JNIEXPORT void JNICALL
@ -962,6 +998,7 @@ PulseAudio_contextStateCallback(pa_context *c, void *userdata)
PulseAudio_stateCallback(userdata);
}
#if (PA_MAJOR >= 1)
static jlongArray
PulseAudio_getFormatInfos
(JNIEnv *env, jclass clazz, jsize length, pa_format_info **formats)
@ -981,6 +1018,7 @@ PulseAudio_getFormatInfos
}
return ret;
}
#endif /* #if (PA_MAJOR >= 1) */
static void
PulseAudio_infoCallback

@ -151,6 +151,14 @@ JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_pulseaudio_
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_format_1info_1get_1prop_1int
(JNIEnv *, jclass, jlong, jstring);
/*
* Class: net_java_sip_communicator_impl_neomedia_pulseaudio_PA
* Method: get_library_version
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_pulseaudio_PA_get_1library_1version
(JNIEnv *, jclass);
/*
* Class: net_java_sip_communicator_impl_neomedia_pulseaudio_PA
* Method: operation_get_state

@ -367,7 +367,8 @@ public void callback(long c, long i, int eol)
new CaptureDeviceInfo(
NULL_DEV_CAPTURE_DEVICE_INFO_NAME,
new MediaLocator(LOCATOR_PROTOCOL + ":"),
captureDeviceFormats.toArray(new Format[captureDeviceFormats.size()])));
captureDeviceFormats.toArray(
new Format[captureDeviceFormats.size()])));
}
if (!playbackDevices.isEmpty())
{
@ -492,94 +493,51 @@ private void sourceInfoListCallback(
if (sampleSpecFormat != PA.SAMPLE_S16LE)
return;
long[] formats = PA.source_info_get_formats(sourceInfo);
if ((formats != null) && (formats.length > 0))
int channels = PA.source_info_get_sample_spec_channels(sourceInfo);
int rate = PA.source_info_get_sample_spec_rate(sourceInfo);
List<Format> sourceInfoFormatList = new LinkedList<Format>();
if ((MediaUtils.MAX_AUDIO_CHANNELS != Format.NOT_SPECIFIED)
&& (MediaUtils.MAX_AUDIO_CHANNELS < channels))
channels = MediaUtils.MAX_AUDIO_CHANNELS;
if ((MediaUtils.MAX_AUDIO_SAMPLE_RATE != Format.NOT_SPECIFIED)
&& (MediaUtils.MAX_AUDIO_SAMPLE_RATE < rate))
rate = (int) MediaUtils.MAX_AUDIO_SAMPLE_RATE;
AudioFormat audioFormat
= new AudioFormat(
AudioFormat.LINEAR,
rate,
16,
channels,
AudioFormat.LITTLE_ENDIAN,
AudioFormat.SIGNED,
Format.NOT_SPECIFIED /* frameSizeInBits */,
Format.NOT_SPECIFIED /* frameRate */,
Format.byteArray);
if (!sourceInfoFormatList.contains(audioFormat))
{
int sampleSpecChannels
= PA.source_info_get_sample_spec_channels(sourceInfo);
int sampleSpecRate
= PA.source_info_get_sample_spec_rate(sourceInfo);
List<Format> sourceInfoFormatList = new LinkedList<Format>();
for (long format : formats)
{
int encoding = PA.format_info_get_encoding(format);
if ((encoding != PA.ENCODING_ANY)
&& (encoding != PA.ENCODING_PCM))
continue;
int channels
= PA.format_info_get_prop_int(
format,
PA.PROP_FORMAT_CHANNELS);
if (channels <= 0)
{
channels = sampleSpecChannels;
if (channels <= 0)
continue;
}
int rate
= PA.format_info_get_prop_int(
format,
PA.PROP_FORMAT_RATE);
if (rate <= 0)
{
rate = sampleSpecRate;
if (rate <= 0)
continue;
}
if ((MediaUtils.MAX_AUDIO_CHANNELS != Format.NOT_SPECIFIED)
&& (MediaUtils.MAX_AUDIO_CHANNELS < channels))
channels = MediaUtils.MAX_AUDIO_CHANNELS;
if ((MediaUtils.MAX_AUDIO_SAMPLE_RATE != Format.NOT_SPECIFIED)
&& (MediaUtils.MAX_AUDIO_SAMPLE_RATE < rate))
rate = (int) MediaUtils.MAX_AUDIO_SAMPLE_RATE;
AudioFormat audioFormat
= new AudioFormat(
AudioFormat.LINEAR,
rate,
16,
channels,
AudioFormat.LITTLE_ENDIAN,
AudioFormat.SIGNED,
Format.NOT_SPECIFIED /* frameSizeInBits */,
Format.NOT_SPECIFIED /* frameRate */,
Format.byteArray);
if (!sourceInfoFormatList.contains(audioFormat))
{
sourceInfoFormatList.add(audioFormat);
if (!formatList.contains(audioFormat))
formatList.add(audioFormat);
}
}
sourceInfoFormatList.add(audioFormat);
if (!formatList.contains(audioFormat))
formatList.add(audioFormat);
}
if (!formatList.isEmpty())
{
String description = PA.source_info_get_description(sourceInfo);
String name = PA.source_info_get_name(sourceInfo);
if (!formatList.isEmpty())
{
String description = PA.source_info_get_description(sourceInfo);
String name = PA.source_info_get_name(sourceInfo);
if (description == null)
description = name;
deviceList.add(
new CaptureDeviceInfo(
description,
new MediaLocator(
LOCATOR_PROTOCOL
+ ":"
+ name),
sourceInfoFormatList.toArray(
new Format[
sourceInfoFormatList
.size()])));
}
if (description == null)
description = name;
deviceList.add(
new CaptureDeviceInfo(
description,
new MediaLocator(
LOCATOR_PROTOCOL
+ ":"
+ name),
sourceInfoFormatList.toArray(
new Format[sourceInfoFormatList.size()])));
}
}

@ -7,6 +7,7 @@
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.pulseaudio;
import java.io.*;
import java.util.*;
import javax.media.*;
import javax.media.control.*;
@ -33,7 +34,40 @@ public class DataSource
private static final int FRAGSIZE_IN_TENS_OF_MILLIS = 2;
private static final boolean SOFTWARE_GAIN = false;
private static final boolean SOFTWARE_GAIN;
static {
boolean softwareGain = true;
try
{
String libraryVersion = PA.get_library_version();
if (libraryVersion != null)
{
StringTokenizer st = new StringTokenizer(libraryVersion, ".");
int major = Integer.parseInt(st.nextToken());
int minor = Integer.parseInt(st.nextToken());
if ((major >= 1) && (minor >= 0))
{
softwareGain = false;
if (logger.isDebugEnabled())
{
logger.debug(
"Will control the volume"
+ " through the native PulseAudio API.");
}
}
}
}
catch (Throwable t)
{
if (t instanceof ThreadDeath)
throw (ThreadDeath) t;
}
SOFTWARE_GAIN = softwareGain;
}
private class PulseAudioStream
extends AbstractPullBufferStream

@ -158,6 +158,8 @@ public static native long context_set_source_output_volume(
public static native int format_info_get_prop_int(long f, String key);
public static native String get_library_version();
public static native int operation_get_state(long o);
public static native void operation_unref(long o);

Loading…
Cancel
Save