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.c83
1 files changed, 34 insertions, 49 deletions
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
index ae8e9a296d..88792cd76f 100644
--- a/firmware/target/hosted/android/pcm-android.c
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -36,65 +36,49 @@ static char *pcm_data_start;
36static jmethodID play_pause_method; 36static jmethodID play_pause_method;
37static jmethodID stop_method; 37static jmethodID stop_method;
38static jmethodID set_volume_method; 38static jmethodID set_volume_method;
39static jmethodID write_method;
39static jclass RockboxPCM_class; 40static jclass RockboxPCM_class;
40static jobject RockboxPCM_instance; 41static jobject RockboxPCM_instance;
41 42
42 43
43/* 44/*
44 * transfer our raw data into a java array 45 * write pcm samples to the hardware. Calls AudioTrack.write directly (which
46 * is usually a blocking call)
45 * 47 *
46 * a bit of a monster functions, but it should cover all cases to overcome 48 * temp_array is not strictly needed as a parameter as we could
47 * the issue that the chunk size of the java layer and our pcm chunks are 49 * create it here, but that would result in frequent garbage collection
48 * differently sized
49 *
50 * afterall, it only copies the raw pcm data from pcm_data_start to
51 * the passed byte[]-array
52 * 50 *
53 * it is called from the PositionMarker callback of AudioTrack 51 * it is called from the PositionMarker callback of AudioTrack
54 **/ 52 **/
55JNIEXPORT void JNICALL 53JNIEXPORT jint JNICALL
56Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env, 54Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this,
57 jobject this, 55 jbyteArray temp_array, jint max_size)
58 jbyteArray arr)
59{ 56{
60 (void)this; 57 jint left = max_size;
61 size_t len; 58
62 size_t array_size = (*env)->GetArrayLength(env, arr); 59 if (!pcm_data_size) /* get some initial data */
63 if (array_size > pcm_data_size) 60 pcm_play_get_more_callback((void**) &pcm_data_start, &pcm_data_size);
64 len = pcm_data_size; 61
65 else 62 while(left > 0 && pcm_data_size)
66 len = array_size; 63 {
67 64 jint ret;
68 (*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start); 65 jsize transfer_size = MIN((size_t)left, pcm_data_size);
69 66 /* decrement both by the amount we're going to write */
70 if (array_size > pcm_data_size) 67 pcm_data_size -= transfer_size; left -= transfer_size;
71 { /* didn't have enough data for the array ? */ 68 (*env)->SetByteArrayRegion(env, temp_array, 0,
72 size_t remaining = array_size - pcm_data_size; 69 transfer_size, (jbyte*)pcm_data_start);
73 size_t offset = len; 70
74 retry: 71 ret = (*env)->CallIntMethod(env, this, write_method,
75 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size); 72 temp_array, 0, transfer_size);
76 if (pcm_data_size == 0) 73 if (ret < 0)
77 { 74 return ret;
78 DEBUGF("out of data\n"); 75
79 return; 76 if (pcm_data_size == 0) /* need new data */
80 } 77 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
81 if (remaining > pcm_data_size) 78 else /* increment data pointer and feed more */
82 { /* got too little data, get more ... */ 79 pcm_data_start += transfer_size;
83 (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start);
84 /* advance in the java array by the amount we copied */
85 offset += pcm_data_size;
86 /* we copied at least a bit */
87 remaining -= pcm_data_size;
88 pcm_data_size = 0;
89 /* let's get another buch of data and try again */
90 goto retry;
91 }
92 else
93 (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
94 len = remaining;
95 } 80 }
96 pcm_data_start += len; 81 return max_size - left;
97 pcm_data_size -= len;
98} 82}
99 83
100void pcm_play_lock(void) 84void pcm_play_lock(void)
@@ -120,7 +104,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
120void pcm_play_dma_stop(void) 104void pcm_play_dma_stop(void)
121{ 105{
122 /* NOTE: due to how pcm_play_get_more_callback() works, this is 106 /* NOTE: due to how pcm_play_get_more_callback() works, this is
123 * possibly called from pcmSamplesToByteArray(), i.e. another thread. 107 * possibly called from writeNative(), i.e. another thread.
124 * => We need to discover the env_ptr */ 108 * => We need to discover the env_ptr */
125 JNIEnv* env = getJavaEnvironment(); 109 JNIEnv* env = getJavaEnvironment();
126 (*env)->CallVoidMethod(env, 110 (*env)->CallVoidMethod(env,
@@ -168,6 +152,7 @@ void pcm_play_dma_init(void)
168 play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V"); 152 play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
169 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V"); 153 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
170 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V"); 154 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
155 write_method = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I");
171 /* get initial pcm data, if any */ 156 /* get initial pcm data, if any */
172 pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size); 157 pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
173} 158}