diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
index ae8e9a2..b763337 100644
--- a/firmware/target/hosted/android/pcm-android.c
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -23,6 +23,7 @@
#include <stdbool.h>
#define _SYSTEM_WITH_JNI /* for getJavaEnvironment */
#include <system.h>
+#include <pthread.h>
#include "debug.h"
#include "pcm.h"
@@ -31,6 +32,8 @@ extern JNIEnv *env_ptr;
/* infos about our pcm chunks */
static size_t pcm_data_size;
static char *pcm_data_start;
+static int audio_locked = 0;
+static pthread_mutex_t audio_lock_mutex = PTHREAD_MUTEX_INITIALIZER;
/* cache frequently called methods */
static jmethodID play_pause_method;
@@ -41,6 +44,20 @@ static jobject RockboxPCM_instance;
/*
+ * mutex lock/unlock wrappers neatness' sake
+ */
+static inline void lock_audio(void)
+{
+ pthread_mutex_lock(&audio_lock_mutex);
+}
+
+static inline void unlock_audio(void)
+{
+ pthread_mutex_unlock(&audio_lock_mutex);
+}
+
+
+/*
* transfer our raw data into a java array
*
* a bit of a monster functions, but it should cover all cases to overcome
@@ -57,6 +74,8 @@ Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
jobject this,
jbyteArray arr)
{
+ lock_audio();
+
(void)this;
size_t len;
size_t array_size = (*env)->GetArrayLength(env, arr);
@@ -76,6 +95,7 @@ Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
if (pcm_data_size == 0)
{
DEBUGF("out of data\n");
+ unlock_audio();
return;
}
if (remaining > pcm_data_size)
@@ -90,19 +110,26 @@ Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
goto retry;
}
else
+ {
(*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
+ }
len = remaining;
}
pcm_data_start += len;
pcm_data_size -= len;
+ unlock_audio();
}
void pcm_play_lock(void)
{
+ if (++audio_locked == 1)
+ lock_audio();
}
void pcm_play_unlock(void)
{
+ if (--audio_locked == 0)
+ unlock_audio();
}
void pcm_dma_apply_settings(void)
@@ -168,8 +195,6 @@ void pcm_play_dma_init(void)
play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
- /* get initial pcm data, if any */
- pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
}
void pcm_postinit(void)