Redirect (L)DEBUGFs to adb logcat in DEBUG enabled builds.
[kugel-rb.git] / firmware / target / hosted / android / pcm-android.c
blobc8bc410a549ce5fea93f83b99868348d502a2b36
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (c) 2010 Thomas Martitz
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <jni.h>
23 #include <stdbool.h>
24 #include <system.h>
25 #include "debug.h"
26 #include "pcm.h"
28 extern JNIEnv *env_ptr;
30 /* infos about our pcm chunks */
31 static size_t pcm_data_size;
32 static char *pcm_data_start;
34 /* cache frequently called methods */
35 static jmethodID play_pause_method;
36 static jmethodID stop_method;
37 static jmethodID set_volume_method;
38 static jclass RockboxPCM_class;
39 static jobject RockboxPCM_instance;
43 * transfer our raw data into a java array
45 * a bit of a monster functions, but it should cover all cases to overcome
46 * the issue that the chunk size of the java layer and our pcm chunks are
47 * differently sized
49 * afterall, it only copies the raw pcm data from pcm_data_start to
50 * the passed byte[]-array
52 * it is called from the PositionMarker callback of AudioTrack
53 **/
54 JNIEXPORT void JNICALL
55 Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
56 jobject this,
57 jbyteArray arr)
59 (void)this;
60 size_t len;
61 size_t array_size = (*env)->GetArrayLength(env, arr);
62 if (array_size > pcm_data_size)
63 len = pcm_data_size;
64 else
65 len = array_size;
67 (*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start);
69 if (array_size > pcm_data_size)
70 { /* didn't have enough data for the array ? */
71 size_t remaining = array_size - pcm_data_size;
72 size_t offset = len;
73 retry:
74 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
75 if (pcm_data_size == 0)
77 DEBUGF("out of data\n");
78 return;
80 if (remaining > pcm_data_size)
81 { /* got too little data, get more ... */
82 (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start);
83 /* advance in the java array by the amount we copied */
84 offset += pcm_data_size;
85 /* we copied at least a bit */
86 remaining -= pcm_data_size;
87 pcm_data_size = 0;
88 /* let's get another buch of data and try again */
89 goto retry;
91 else
92 (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
93 len = remaining;
95 pcm_data_start += len;
96 pcm_data_size -= len;
99 void pcm_play_lock(void)
103 void pcm_play_unlock(void)
107 void pcm_dma_apply_settings(void)
111 void pcm_play_dma_start(const void *addr, size_t size)
113 pcm_data_start = (char*)addr;
114 pcm_data_size = size;
116 pcm_play_dma_pause(false);
119 void pcm_play_dma_stop(void)
121 (*env_ptr)->CallVoidMethod(env_ptr,
122 RockboxPCM_instance,
123 stop_method);
126 void pcm_play_dma_pause(bool pause)
128 (*env_ptr)->CallVoidMethod(env_ptr,
129 RockboxPCM_instance,
130 play_pause_method,
131 (int)pause);
134 size_t pcm_get_bytes_waiting(void)
136 return pcm_data_size;
139 const void * pcm_play_dma_get_peak_buffer(int *count)
141 uintptr_t addr = (uintptr_t)pcm_data_start;
142 *count = pcm_data_size / 4;
143 return (void *)((addr + 3) & ~3);
146 void pcm_play_dma_init(void)
148 /* in order to have background music playing after leaving the activity,
149 * we need to allocate the PCM object from the Rockbox thread (the Activity
150 * runs in a separate thread because it would otherwise kill us when
151 * stopping it)
153 * Luckily we only reference the PCM object from here, so it's safe (and
154 * clean) to allocate it here
156 JNIEnv e = *env_ptr;
157 /* get the class and its constructor */
158 RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM");
159 jmethodID constructor = e->GetMethodID(env_ptr, RockboxPCM_class, "<init>", "()V");
160 /* instance = new RockboxPCM() */
161 RockboxPCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor);
162 /* cache needed methods */
163 play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
164 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
165 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
166 /* get initial pcm data, if any */
167 pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
170 void pcm_postinit(void)
174 void pcm_set_mixer_volume(int volume)
176 (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume);