@ -55,9 +55,7 @@ struct fields fields;
# define VLC_JNI_VERSION JNI_VERSION_1_2
# define THREAD_NAME "libvlcjni"
int jni_attach_thread ( JNIEnv * * env , const char * thread_name ) ;
void jni_detach_thread ( ) ;
int jni_get_env ( JNIEnv * * env ) ;
JNIEnv * jni_get_env ( const char * name ) ;
static void add_media_options ( libvlc_media_t * p_md , JNIEnv * env , jobjectArray mediaOptions )
{
@ -117,28 +115,17 @@ static void releaseMediaPlayer(JNIEnv *env, jobject thiz)
}
}
/* Pointer to the Java virtual machine
* Note : It ' s okay to use a static variable for the VM pointer since there
* can only be one instance of this shared library in a single VM
*/
static JavaVM * myVm ;
static jobject eventHandlerInstance = NULL ;
static void vlc_event_callback ( const libvlc_event_t * ev , void * data )
{
JNIEnv * env ;
bool isAttached = false ;
if ( eventHandlerInstance = = NULL )
return ;
if ( jni_get_env ( & env ) < 0 ) {
if ( jni_attach_thread ( & env , THREAD_NAME ) < 0 )
return ;
isAttached = true ;
}
if ( ! ( env = jni_get_env ( THREAD_NAME ) ) )
return ;
/* Creating the bundle in C allows us to subscribe to more events
* and get better flexibility for each event . For example , we can
@ -216,8 +203,55 @@ static void vlc_event_callback(const libvlc_event_t *ev, void *data)
end :
( * env ) - > DeleteLocalRef ( env , bundle ) ;
if ( isAttached )
jni_detach_thread ( ) ;
}
/* Pointer to the Java virtual machine
* Note : It ' s okay to use a static variable for the VM pointer since there
* can only be one instance of this shared library in a single VM
*/
static JavaVM * myVm ;
static pthread_key_t jni_env_key ;
/* This function is called when a thread attached to the Java VM is canceled or
* exited */
static void jni_detach_thread ( void * data )
{
//JNIEnv *env = data;
( * myVm ) - > DetachCurrentThread ( myVm ) ;
}
JNIEnv * jni_get_env ( const char * name )
{
JNIEnv * env ;
env = pthread_getspecific ( jni_env_key ) ;
if ( env = = NULL ) {
/* if GetEnv returns JNI_OK, the thread is already attached to the
* JavaVM , so we are already in a java thread , and we don ' t have to
* setup any destroy callbacks */
if ( ( * myVm ) - > GetEnv ( myVm , ( void * * ) & env , VLC_JNI_VERSION ) ! = JNI_OK )
{
/* attach the thread to the Java VM */
JavaVMAttachArgs args ;
jint result ;
args . version = VLC_JNI_VERSION ;
args . name = name ;
args . group = NULL ;
if ( ( * myVm ) - > AttachCurrentThread ( myVm , & env , & args ) ! = JNI_OK )
return NULL ;
/* Set the attached env to the thread-specific data area (TSD) */
if ( pthread_setspecific ( jni_env_key , env ) ! = 0 )
{
( * myVm ) - > DetachCurrentThread ( myVm ) ;
return NULL ;
}
}
}
return env ;
}
jint JNI_OnLoad ( JavaVM * vm , void * reserved )
@ -228,9 +262,16 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
if ( ( * vm ) - > GetEnv ( vm , ( void * * ) & env , VLC_JNI_VERSION ) ! = JNI_OK )
return - 1 ;
/* Create a TSD area and setup a destroy callback when a thread that
* previously set the jni_env_key is canceled or exited */
if ( pthread_key_create ( & jni_env_key , jni_detach_thread ) ! = 0 )
return - 1 ;
pthread_mutex_init ( & vout_android_lock , NULL ) ;
pthread_cond_init ( & vout_android_surf_attached , NULL ) ;
# define GET_CLASS(clazz, str, b_globlal) do { \
( clazz ) = ( * env ) - > FindClass ( env , ( str ) ) ; \
if ( ! ( clazz ) ) { \
@ -356,29 +397,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved)
( * env ) - > DeleteGlobalRef ( env , fields . String . clazz ) ;
( * env ) - > DeleteGlobalRef ( env , fields . VLCObject . clazz ) ;
( * env ) - > DeleteGlobalRef ( env , fields . Media . clazz ) ;
}
int jni_attach_thread ( JNIEnv * * env , const char * thread_name )
{
JavaVMAttachArgs args ;
jint result ;
args . version = VLC_JNI_VERSION ;
args . name = thread_name ;
args . group = NULL ;
result = ( * myVm ) - > AttachCurrentThread ( myVm , env , & args ) ;
return result = = JNI_OK ? 0 : - 1 ;
}
void jni_detach_thread ( )
{
( * myVm ) - > DetachCurrentThread ( myVm ) ;
}
int jni_get_env ( JNIEnv * * env )
{
return ( * myVm ) - > GetEnv ( myVm , ( void * * ) env , VLC_JNI_VERSION ) = = JNI_OK ? 0 : - 1 ;
pthread_key_delete ( jni_env_key ) ;
}
void Java_org_videolan_libvlc_LibVLC_nativeInit ( JNIEnv * env , jobject thiz )
@ -908,10 +928,10 @@ int jni_GetWindowSize(int *width, int *height)
int aout_get_native_sample_rate ( void )
{
JNIEnv * p_env ;
jni_attach_thread ( & p_env , THREAD_NAME ) ;
if ( ! ( p_env = jni_get_env ( THREAD_NAME ) ) )
return - 1 ;
jclass cls = ( * p_env ) - > FindClass ( p_env , " android/media/AudioTrack " ) ;
jmethodID method = ( * p_env ) - > GetStaticMethodID ( p_env , cls , " getNativeOutputSampleRate " , " (I)I " ) ;
int sample_rate = ( * p_env ) - > CallStaticIntMethod ( p_env , cls , method , 3 ) ; // AudioManager.STREAM_MUSIC
jni_detach_thread ( ) ;
return sample_rate ;
}