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.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
new file mode 100644
index 0000000000..91978f422b
--- /dev/null
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -0,0 +1,174 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2010 Thomas Martitz
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <jni.h>
23#include <stdbool.h>
24#include <system.h>
25#include "pcm.h"
26
27extern JNIEnv *env_ptr;
28extern jclass RockboxActivity_class;
29extern jobject RockboxActivity_instance;
30
31/* infos about our pcm chunks */
32static size_t pcm_data_size;
33static char *pcm_data_start;
34
35/* cache frequently called methods */
36static jmethodID play_pause_method;
37static jmethodID stop_method;
38static jmethodID set_volume_method;
39static jclass RockboxPCM_class;
40static jobject RockboxPCM_instance;
41
42
43/*
44 * transfer our raw data into a java array
45 *
46 * a bit of a monster functions, but it should cover all cases to overcome
47 * the issue that the chunk size of the java layer and our pcm chunks are
48 * differently sized
49 *
50 * afterall, it only copies the raw pcm data from pcm_data_start to
51 * the passed byte[]-array
52 *
53 * it is called from the PositionMarker callback of AudioTrack
54 **/
55JNIEXPORT void JNICALL
56Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
57 jobject this,
58 jbyteArray arr)
59{
60 (void)this;
61 size_t len;
62 size_t array_size = (*env)->GetArrayLength(env, arr);
63 if (array_size > pcm_data_size)
64 len = pcm_data_size;
65 else
66 len = array_size;
67
68 (*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start);
69
70 if (array_size > pcm_data_size)
71 { /* didn't have enough data for the array ? */
72 size_t remaining = array_size - pcm_data_size;
73 size_t offset = len;
74 retry:
75 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
76 if (pcm_data_size == 0)
77 return;
78 if (remaining > pcm_data_size)
79 { /* got too little data, get more ... */
80 (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start);
81 /* advance in the java array by the amount we copied */
82 offset += pcm_data_size;
83 /* we copied at least a bit */
84 remaining -= pcm_data_size;
85 /* let's get another buch of data and try again */
86 goto retry;
87 }
88 else
89 (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
90 len = remaining;
91 }
92 pcm_data_start += len;
93 pcm_data_size -= len;
94}
95
96void pcm_play_lock(void)
97{
98}
99
100void pcm_play_unlock(void)
101{
102}
103
104void pcm_dma_apply_settings(void)
105{
106}
107
108void pcm_play_dma_start(const void *addr, size_t size)
109{
110 pcm_data_start = (char*)addr;
111 pcm_data_size = size;
112
113 pcm_play_dma_pause(false);
114}
115
116void pcm_play_dma_stop(void)
117{
118 (*env_ptr)->CallVoidMethod(env_ptr,
119 RockboxPCM_instance,
120 stop_method);
121}
122
123void pcm_play_dma_pause(bool pause)
124{
125 (*env_ptr)->CallVoidMethod(env_ptr,
126 RockboxPCM_instance,
127 play_pause_method,
128 (int)pause);
129}
130
131size_t pcm_get_bytes_waiting(void)
132{
133 return pcm_data_size;
134}
135
136const void * pcm_play_dma_get_peak_buffer(int *count)
137{
138 uintptr_t addr = (uintptr_t)pcm_data_start;
139 *count = pcm_data_size / 4;
140 return (void *)((addr + 3) & ~3);
141}
142
143void pcm_play_dma_init(void)
144{
145 /* in order to have background music playing after leaving the activity,
146 * we need to allocate the PCM object from the Rockbox thread (the Activity
147 * runs in a separate thread because it would otherwise kill us when
148 * stopping it)
149 *
150 * Luckily we only reference the PCM object from here, so it's safe (and
151 * clean) to allocate it here
152 **/
153 JNIEnv e = *env_ptr;
154 /* get the class and its constructor */
155 RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM");
156 jmethodID constructor = e->GetMethodID(env_ptr, RockboxPCM_class, "<init>", "()V");
157 /* instance = new RockboxPCM() */
158 RockboxPCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor);
159 /* cache needed methods */
160 play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
161 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
162 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
163 /* get initial pcm data, if any */
164 pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
165}
166
167void pcm_postinit(void)
168{
169}
170
171void pcm_set_mixer_volume(int volume)
172{
173 (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume);
174}