[sip-comm-dev] [PATCH] fix for jportaudio, Convert device name charset from system to UNICODE, at system with not UTF-8 and ISO8859-1 system charset.


#1

Index: src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c

···

===================================================================
--- src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c (revision 7011)
+++ src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c (working copy)
@@ -59,6 +59,7 @@
#define DEFAULT_SAMPLE_RATE 44100.0

static void PortAudio_throwException(JNIEnv *env, PaError errorCode);
+static jstring PortAudio_converString4SystemCharset2UTF(JNIEnv *env, const char *name);
static PaStreamParameters * PortAudio_fixInputParametersSuggestedLatency(
     PaStreamParameters *inputParameters);
static PaStreamParameters * PortAudio_fixOutputParametersSuggestedLatency(
@@ -618,7 +619,9 @@
{
     const char *name = ((PaDeviceInfo *) deviceInfo)->name;

- return name ? (*env)->NewStringUTF(env, name) : NULL;
+ jstring jstr = PortAudio_converString4SystemCharset2UTF(env, name);
+
+ return jstr ? jstr : (name ? (*env)->NewStringUTF(env, name) : NULL);
}

JNIEXPORT jdouble JNICALL
@@ -683,7 +686,9 @@
{
     const char *name = ((PaHostApiInfo *) hostApi)->name;

- return name ? (*env)->NewStringUTF(env, name) : NULL;
+ jstring jstr = PortAudio_converString4SystemCharset2UTF(env, name);
+
+ return jstr ? jstr : (name ? (*env)->NewStringUTF(env, name) : NULL);
}

JNIEXPORT jint JNICALL
@@ -730,6 +735,35 @@
     return (jlong) streamParameters;
}

+static jstring PortAudio_converString4SystemCharset2UTF(JNIEnv *env, const char *name)
+{
+ /** Convert string from System charset to UNICODE **/
+ jstring jstr = NULL;
+ jthrowable exc;
+ jclass clazz1 = (*env)->FindClass(env, "net/java/sip/communicator/util/CharsetConverter");
+ if (clazz1) {
+ jmethodID mid1 = (*env)->GetMethodID(env, clazz1, "<init>" ,"()V");
+ if (mid1) {
+ jobject jo1 = (*env)->NewObject(env, clazz1, mid1);
+ if (jo1) {
+ jmethodID mid2 = (*env)->GetMethodID(env, clazz1, "conver4SystemCharset2UTF" ,"([B)Ljava/lang/String;");
+ if (mid2) {
+ jbyteArray jba = (*env)->NewByteArray(env, strlen(name));
+ (*env)->SetByteArrayRegion(env, jba, (jint)0, (jint)strlen(name) , (jbyte*)name);
+ jstr = (*env)->CallObjectMethod(env, jo1, mid2, jba);
+ (*env)->ReleaseByteArrayElements(env, jba, (jbyte*)name, JNI_COMMIT);
+ }
+ }
+ }
+ }
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ //(*env)->ExceptionDescribe(env); //Enable only for debug.
+ (*env)->ExceptionClear(env);
+ }
+ return jstr;
+}
+
static PaStreamParameters *
PortAudio_fixInputParametersSuggestedLatency(
     PaStreamParameters *inputParameters)
Index: src/net/java/sip/communicator/util/CharsetConverter.java

--- src/net/java/sip/communicator/util/CharsetConverter.java (revision 0)
+++ src/net/java/sip/communicator/util/CharsetConverter.java (revision 0)
@@ -0,0 +1,40 @@
+package net.java.sip.communicator.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.io.ByteArrayInputStream;
+
+
+public final class CharsetConverter
+{
+ public static String systemCharset;
+
+ private static boolean initialized = false;
+
+ public String conver4SystemCharset2UTF(byte[] sourceString)
+ throws IOException, UnsupportedEncodingException {
+
+ StringBuffer buffer = new StringBuffer();
+ ByteArrayInputStream ains = new ByteArrayInputStream(sourceString);
+ InputStreamReader isr = new InputStreamReader(ains, systemCharset);
+ Reader in = new BufferedReader(isr);
+ int ch;
+ while ((ch = in.read()) > -1)
+ buffer.append((char)ch);
+ in.close();
+ return buffer.toString();
+ }
+
+ public CharsetConverter()
+ throws IOException {
+ if (!initialized) {
+ initialized = true;
+ systemCharset = new OutputStreamWriter( System.out ).getEncoding();
+ }
+ }
+
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#2

Thank you for the bug report!

The solution offered in the patch seems too complex to me though: if
you need to perform the conversion of the bytes into a Java String
using Java code and based on the charset available in Java, I don't
understand why you don't just return the bytes and then do the
conversation instead of calling back from the native code to the Java
code, introducing a new class, etc.

···

2010/4/18 admin@lefoyer.ru <admin@lefoyer.ru>:

Index: src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c

--- src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c (revision 7011)
+++ src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c (working copy)
@@ -59,6 +59,7 @@
#define DEFAULT_SAMPLE_RATE 44100.0

static void PortAudio_throwException(JNIEnv *env, PaError errorCode);
+static jstring PortAudio_converString4SystemCharset2UTF(JNIEnv *env, const char *name);
static PaStreamParameters * PortAudio_fixInputParametersSuggestedLatency(
PaStreamParameters *inputParameters);
static PaStreamParameters * PortAudio_fixOutputParametersSuggestedLatency(
@@ -618,7 +619,9 @@
{
const char *name = ((PaDeviceInfo *) deviceInfo)->name;

- return name ? (*env)->NewStringUTF(env, name) : NULL;
+ jstring jstr = PortAudio_converString4SystemCharset2UTF(env, name);
+
+ return jstr ? jstr : (name ? (*env)->NewStringUTF(env, name) : NULL);
}

JNIEXPORT jdouble JNICALL
@@ -683,7 +686,9 @@
{
const char *name = ((PaHostApiInfo *) hostApi)->name;

- return name ? (*env)->NewStringUTF(env, name) : NULL;
+ jstring jstr = PortAudio_converString4SystemCharset2UTF(env, name);
+
+ return jstr ? jstr : (name ? (*env)->NewStringUTF(env, name) : NULL);
}

JNIEXPORT jint JNICALL
@@ -730,6 +735,35 @@
return (jlong) streamParameters;
}

+static jstring PortAudio_converString4SystemCharset2UTF(JNIEnv *env, const char *name)
+{
+ /** Convert string from System charset to UNICODE **/
+ jstring jstr = NULL;
+ jthrowable exc;
+ jclass clazz1 = (*env)->FindClass(env, "net/java/sip/communicator/util/CharsetConverter");
+ if (clazz1) {
+ jmethodID mid1 = (*env)->GetMethodID(env, clazz1, "<init>" ,"()V");
+ if (mid1) {
+ jobject jo1 = (*env)->NewObject(env, clazz1, mid1);
+ if (jo1) {
+ jmethodID mid2 = (*env)->GetMethodID(env, clazz1, "conver4SystemCharset2UTF" ,"([B)Ljava/lang/String;");
+ if (mid2) {
+ jbyteArray jba = (*env)->NewByteArray(env, strlen(name));
+ (*env)->SetByteArrayRegion(env, jba, (jint)0, (jint)strlen(name) , (jbyte*)name);
+ jstr = (*env)->CallObjectMethod(env, jo1, mid2, jba);
+ (*env)->ReleaseByteArrayElements(env, jba, (jbyte*)name, JNI_COMMIT);
+ }
+ }
+ }
+ }
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ //(*env)->ExceptionDescribe(env); //Enable only for debug.
+ (*env)->ExceptionClear(env);
+ }
+ return jstr;
+}
+
static PaStreamParameters *
PortAudio_fixInputParametersSuggestedLatency(
PaStreamParameters *inputParameters)
Index: src/net/java/sip/communicator/util/CharsetConverter.java

--- src/net/java/sip/communicator/util/CharsetConverter.java (revision 0)
+++ src/net/java/sip/communicator/util/CharsetConverter.java (revision 0)
@@ -0,0 +1,40 @@
+package net.java.sip.communicator.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.io.ByteArrayInputStream;
+
+
+public final class CharsetConverter
+{
+ public static String systemCharset;
+
+ private static boolean initialized = false;
+
+ public String conver4SystemCharset2UTF(byte[] sourceString)
+ throws IOException, UnsupportedEncodingException {
+
+ StringBuffer buffer = new StringBuffer();
+ ByteArrayInputStream ains = new ByteArrayInputStream(sourceString);
+ InputStreamReader isr = new InputStreamReader(ains, systemCharset);
+ Reader in = new BufferedReader(isr);
+ int ch;
+ while ((ch = in.read()) > -1)
+ buffer.append((char)ch);
+ in.close();
+ return buffer.toString();
+ }
+
+ public CharsetConverter()
+ throws IOException {
+ if (!initialized) {
+ initialized = true;
+ systemCharset = new OutputStreamWriter( System.out ).getEncoding();
+ }
+ }
+
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#3

Здравствуйте, Lubomir.

Thank you for the bug report!

The solution offered in the patch seems too complex to me though: if
you need to perform the conversion of the bytes into a Java String
using Java code and based on the charset available in Java, I don't
understand why you don't just return the bytes and then do the
conversation instead of calling back from the native code to the Java
code, introducing a new class, etc.

New version patch.

Index: src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c

···

===================================================================
--- src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c (revision 7012)
+++ src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c (working copy)
@@ -612,13 +612,16 @@
}

-JNIEXPORT jstring JNICALL
-Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getName(
+JNIEXPORT jbyteArray JNICALL
+Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getNameJba(
     JNIEnv *env, jclass clazz, jlong deviceInfo)
{
     const char *name = ((PaDeviceInfo *) deviceInfo)->name;

- return name ? (*env)->NewStringUTF(env, name) : NULL;
+ jbyteArray jba = (*env)->NewByteArray(env, strlen(name));
+ (*env)->SetByteArrayRegion(env, jba, (jint)0, (jint)strlen(name) , (jbyte*)name);
+
+ return jba ? jba : NULL;
}

JNIEXPORT jdouble JNICALL
@@ -677,13 +680,16 @@
     return ((PaHostApiInfo *) hostApi)->type;
}

-JNIEXPORT jstring JNICALL
-Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetName
+JNIEXPORT jbyteArray JNICALL
+Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetNameJba
   (JNIEnv *env, jclass clazz, jlong hostApi)
{
     const char *name = ((PaHostApiInfo *) hostApi)->name;

- return name ? (*env)->NewStringUTF(env, name) : NULL;
+ jbyteArray jba = (*env)->NewByteArray(env, strlen(name));
+ (*env)->SetByteArrayRegion(env, jba, (jint)0, (jint)strlen(name) , (jbyte*)name);
+
+ return jba ? jba : NULL;
}

JNIEXPORT jint JNICALL
Index: src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h

--- src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h (revision 7012)
+++ src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h (working copy)
@@ -170,7 +170,7 @@
  * Method: PaDeviceInfo_getName
  * Signature: (J)Ljava/lang/String;
  */
-JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getName
+JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getNameJba
   (JNIEnv *, jclass, jlong);

/*
@@ -242,7 +242,7 @@
  * Method: PaHostApiInfo_GetName
  * Signature: (J)Ljava/lang/String;
  */
-JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetName
+JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetNameJba
   (JNIEnv *, jclass, jlong);

/*
Index: src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java

--- src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java (revision 7012)
+++ src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java (working copy)
@@ -6,6 +6,13 @@
  */
package net.java.sip.communicator.impl.media.protocol.portaudio;

+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.ByteArrayInputStream;
+
+
/**
  * PortAudio functions.
  * @author Lubomir Marinov
@@ -17,6 +24,8 @@
         System.loadLibrary("jportaudio");
     }

+ public static String systemCharset;
+
     /**
      * Can be passed as the framesPerBuffer parameter to
      * Pa_OpenStream() or Pa_OpenDefaultStream() to indicate that the stream
@@ -131,10 +140,30 @@
         if (!initialized)
         {
             Pa_Initialize();
+ systemCharset = new OutputStreamWriter( System.out ).getEncoding();
             initialized = true;
         }
     }

+
+ public static String conver4SystemCharset2UTF(byte[] sourceString) {
+
+ try {
+ StringBuffer buffer = new StringBuffer();
+ ByteArrayInputStream ains = new ByteArrayInputStream(sourceString);
+ InputStreamReader isr = new InputStreamReader(ains, systemCharset);
+ Reader in = new BufferedReader(isr);
+ int ch;
+ while ((ch = in.read()) > -1)
+ buffer.append((char)ch);
+ in.close();
+ return buffer.toString();
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+
     /**
      * Set params for echocancel and turns on/off noise suppression.
      * @param inputStream the input stream.
@@ -348,8 +377,15 @@
      * @param deviceInfo device info pointer.
      * @return The name of the device.
      */
- public static native String PaDeviceInfo_getName(long deviceInfo);
+ public static native byte[] PaDeviceInfo_getNameJba(long deviceInfo);

+
+ public static String PaDeviceInfo_getName(long deviceInfo){
+
+ return conver4SystemCharset2UTF(PaDeviceInfo_getNameJba(deviceInfo));
+ }
+
+
     /**
      * The default samplerate for the deviec.
      * @param deviceInfo device info pointer.
@@ -428,8 +464,14 @@
      * @param hostApiInfo pointer to host api info structure.
      * @return host api name.
      */
- public static native String PaHostApiInfo_GetName(long hostApiInfo);
+ public static native byte[] PaHostApiInfo_GetNameJba(long hostApiInfo);

+
+ public static String PaHostApiInfo_GetName(long hostApiInfo){
+
+ return conver4SystemCharset2UTF(PaHostApiInfo_GetNameJba(hostApiInfo));
+ }
+
     /**
      * The number of devices belonging to this host API.
      * @param hostApiInfo pointer to host api info structure.
Index: src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java

--- src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java (revision 7012)
+++ src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java (working copy)
@@ -6,6 +6,12 @@
  */
package net.java.sip.communicator.impl.neomedia.portaudio;

+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.ByteArrayInputStream;
+
/**
  * PortAudio functions.
  *
@@ -19,6 +25,8 @@
         System.loadLibrary("jportaudio");
     }

+ public static String systemCharset;
+
     /**
      * Can be passed as the framesPerBuffer parameter to
      * Pa_OpenStream() or Pa_OpenDefaultStream() to indicate that the stream
@@ -133,10 +141,29 @@
         if (!initialized)
         {
             Pa_Initialize();
+ systemCharset = new OutputStreamWriter( System.out ).getEncoding();
             initialized = true;
         }
     }

+
+ public static String conver4SystemCharset2UTF(byte[] sourceString) {
+
+ try {
+ StringBuffer buffer = new StringBuffer();
+ ByteArrayInputStream ains = new ByteArrayInputStream(sourceString);
+ InputStreamReader isr = new InputStreamReader(ains, systemCharset);
+ Reader in = new BufferedReader(isr);
+ int ch;
+ while ((ch = in.read()) > -1)
+ buffer.append((char)ch);
+ in.close();
+ return buffer.toString();
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
     /**
      * Set params for echocancel and turns on/off noise suppression.
      * @param inputStream the input stream.
@@ -379,8 +406,14 @@
      * @param deviceInfo device info pointer.
      * @return The name of the device.
      */
- public static native String PaDeviceInfo_getName(long deviceInfo);
+ public static native byte[] PaDeviceInfo_getNameJba(long deviceInfo);

+
+ public static String PaDeviceInfo_getName(long deviceInfo){
+
+ return conver4SystemCharset2UTF(PaDeviceInfo_getNameJba(deviceInfo));
+ }
+
     /**
      * The default samplerate for the deviec.
      * @param deviceInfo device info pointer.
@@ -459,8 +492,14 @@
      * @param hostApiInfo pointer to host api info structure.
      * @return host api name.
      */
- public static native String PaHostApiInfo_GetName(long hostApiInfo);
+ public static native byte[] PaHostApiInfo_GetNameJba(long hostApiInfo);

+
+ public static String PaHostApiInfo_GetName(long hostApiInfo){
+
+ return conver4SystemCharset2UTF(PaHostApiInfo_GetNameJba(hostApiInfo));
+ }
+
     /**
      * The number of devices belonging to this host API.
      * @param hostApiInfo pointer to host api info structure.

--
С уважением,
Admin mailto:admin@lefoyer.ru

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#4

Здравствуйте, Lubomir.
С уважением,

:slight_smile: I'd like to point out that the dev mailing list is read by pretty
much everyone involved in development related to SIP Communicator and
English is the language of the dev mailing list so we must abide to
it.

New version patch.

Thank you for your continued effort! I'm afraid I'd like to ask
another favor of you though :wink: I've committed a fix for
PaDeviceInfo_getName() in r7026 which is based on your patch but it's
kind of different in the details. Could you please rebuild your local
jportaudio library with the files from r7026, try reproducing the
issue with it and report your observations?

Admin mailto:admin@lefoyer.ru

Once we get this issue fixed, I'll have to acknowledge your
contribution on our Team and Contributors page so I'll need the name
with which you want your contribution to be associated. I used the
name Admin in the SVN comment.

···

2010/4/19 <admin@lefoyer.ru>:

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net