summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/android/pcm-android.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/android/pcm-android.c')
-rw-r--r--firmware/target/hosted/android/pcm-android.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
index 88792cd76f..cbd6cb3228 100644
--- a/firmware/target/hosted/android/pcm-android.c
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -23,14 +23,18 @@
23#include <stdbool.h> 23#include <stdbool.h>
24#define _SYSTEM_WITH_JNI /* for getJavaEnvironment */ 24#define _SYSTEM_WITH_JNI /* for getJavaEnvironment */
25#include <system.h> 25#include <system.h>
26#include <pthread.h>
26#include "debug.h" 27#include "debug.h"
27#include "pcm.h" 28#include "pcm.h"
29#include "pcm-internal.h"
28 30
29extern JNIEnv *env_ptr; 31extern JNIEnv *env_ptr;
30 32
31/* infos about our pcm chunks */ 33/* infos about our pcm chunks */
32static size_t pcm_data_size; 34static size_t pcm_data_size;
33static char *pcm_data_start; 35static char *pcm_data_start;
36static int audio_locked = 0;
37static pthread_mutex_t audio_lock_mutex = PTHREAD_MUTEX_INITIALIZER;
34 38
35/* cache frequently called methods */ 39/* cache frequently called methods */
36static jmethodID play_pause_method; 40static jmethodID play_pause_method;
@@ -42,6 +46,20 @@ static jobject RockboxPCM_instance;
42 46
43 47
44/* 48/*
49 * mutex lock/unlock wrappers neatness' sake
50 */
51static inline void lock_audio(void)
52{
53 pthread_mutex_lock(&audio_lock_mutex);
54}
55
56static inline void unlock_audio(void)
57{
58 pthread_mutex_unlock(&audio_lock_mutex);
59}
60
61
62/*
45 * write pcm samples to the hardware. Calls AudioTrack.write directly (which 63 * write pcm samples to the hardware. Calls AudioTrack.write directly (which
46 * is usually a blocking call) 64 * is usually a blocking call)
47 * 65 *
@@ -54,10 +72,17 @@ JNIEXPORT jint JNICALL
54Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this, 72Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this,
55 jbyteArray temp_array, jint max_size) 73 jbyteArray temp_array, jint max_size)
56{ 74{
75 bool new_buffer = false;
76
77 lock_audio();
78
57 jint left = max_size; 79 jint left = max_size;
58 80
59 if (!pcm_data_size) /* get some initial data */ 81 if (!pcm_data_size) /* get some initial data */
82 {
83 new_buffer = true;
60 pcm_play_get_more_callback((void**) &pcm_data_start, &pcm_data_size); 84 pcm_play_get_more_callback((void**) &pcm_data_start, &pcm_data_size);
85 }
61 86
62 while(left > 0 && pcm_data_size) 87 while(left > 0 && pcm_data_size)
63 { 88 {
@@ -70,23 +95,49 @@ Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this,
70 95
71 ret = (*env)->CallIntMethod(env, this, write_method, 96 ret = (*env)->CallIntMethod(env, this, write_method,
72 temp_array, 0, transfer_size); 97 temp_array, 0, transfer_size);
98
99 if (new_buffer)
100 {
101 new_buffer = false;
102 pcm_play_dma_started_callback();
103
104 /* NOTE: might need to release the mutex and sleep here if the
105 buffer is shorter than the required buffer (like pcm-sdl.c) to
106 have the mixer clocked at a regular interval */
107 }
108
73 if (ret < 0) 109 if (ret < 0)
110 {
111 unlock_audio();
74 return ret; 112 return ret;
113 }
75 114
76 if (pcm_data_size == 0) /* need new data */ 115 if (pcm_data_size == 0) /* need new data */
116 {
117 new_buffer = true;
77 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size); 118 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
119 }
78 else /* increment data pointer and feed more */ 120 else /* increment data pointer and feed more */
79 pcm_data_start += transfer_size; 121 pcm_data_start += transfer_size;
80 } 122 }
123
124 if (new_buffer && pcm_data_size)
125 pcm_play_dma_started_callback();
126
127 unlock_audio();
81 return max_size - left; 128 return max_size - left;
82} 129}
83 130
84void pcm_play_lock(void) 131void pcm_play_lock(void)
85{ 132{
133 if (++audio_locked == 1)
134 lock_audio();
86} 135}
87 136
88void pcm_play_unlock(void) 137void pcm_play_unlock(void)
89{ 138{
139 if (--audio_locked == 0)
140 unlock_audio();
90} 141}
91 142
92void pcm_dma_apply_settings(void) 143void pcm_dma_apply_settings(void)
@@ -153,8 +204,6 @@ void pcm_play_dma_init(void)
153 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V"); 204 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
154 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V"); 205 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
155 write_method = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I"); 206 write_method = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I");
156 /* get initial pcm data, if any */
157 pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
158} 207}
159 208
160void pcm_postinit(void) 209void pcm_postinit(void)
@@ -173,6 +222,7 @@ void pcm_shutdown(void)
173 JNIEnv e = *env_ptr; 222 JNIEnv e = *env_ptr;
174 jmethodID release = e->GetMethodID(env_ptr, RockboxPCM_class, "release", "()V"); 223 jmethodID release = e->GetMethodID(env_ptr, RockboxPCM_class, "release", "()V");
175 e->CallVoidMethod(env_ptr, RockboxPCM_instance, release); 224 e->CallVoidMethod(env_ptr, RockboxPCM_instance, release);
225 pthread_mutex_destroy(&audio_lock_mutex);
176} 226}
177 227
178/* Due to limitations of default_event_handler(), parameters gets swallowed when 228/* Due to limitations of default_event_handler(), parameters gets swallowed when