From 240923a801382c86545d10be167a15892a556fb6 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Mon, 2 Aug 2010 20:34:47 +0000 Subject: Rockbox as an application: Commit current Android port progress. General state is: Rockbox is usable (plays music, saves configuration, touchscreen works too). Problems: - Playing music in the background (i.e. when switching to another app) doesn't work reliably, but I'm working on that now. - no cabbiev2 (only some preliminary files for it), no other default theme. - screen flickers sometimes if the updates are too frequent - no multi screen apk/package - strange behavior when a phone call comes in The java files (and the eclipse project) resides in android/, which is also supposed to be the build folder. I've put a small README in there for instructions. There are some steps needed after the make part, which are described there, and which eclipse mostly handles. But there ought to be some script/makefile rules which do that instead in the future. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27668 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/hosted/android/pcm-android.c | 174 +++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 firmware/target/hosted/android/pcm-android.c (limited to 'firmware/target/hosted/android/pcm-android.c') 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 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (c) 2010 Thomas Martitz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include "pcm.h" + +extern JNIEnv *env_ptr; +extern jclass RockboxActivity_class; +extern jobject RockboxActivity_instance; + +/* infos about our pcm chunks */ +static size_t pcm_data_size; +static char *pcm_data_start; + +/* cache frequently called methods */ +static jmethodID play_pause_method; +static jmethodID stop_method; +static jmethodID set_volume_method; +static jclass RockboxPCM_class; +static jobject RockboxPCM_instance; + + +/* + * transfer our raw data into a java array + * + * a bit of a monster functions, but it should cover all cases to overcome + * the issue that the chunk size of the java layer and our pcm chunks are + * differently sized + * + * afterall, it only copies the raw pcm data from pcm_data_start to + * the passed byte[]-array + * + * it is called from the PositionMarker callback of AudioTrack + **/ +JNIEXPORT void JNICALL +Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env, + jobject this, + jbyteArray arr) +{ + (void)this; + size_t len; + size_t array_size = (*env)->GetArrayLength(env, arr); + if (array_size > pcm_data_size) + len = pcm_data_size; + else + len = array_size; + + (*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start); + + if (array_size > pcm_data_size) + { /* didn't have enough data for the array ? */ + size_t remaining = array_size - pcm_data_size; + size_t offset = len; + retry: + pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size); + if (pcm_data_size == 0) + return; + if (remaining > pcm_data_size) + { /* got too little data, get more ... */ + (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start); + /* advance in the java array by the amount we copied */ + offset += pcm_data_size; + /* we copied at least a bit */ + remaining -= pcm_data_size; + /* let's get another buch of data and try again */ + goto retry; + } + else + (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start); + len = remaining; + } + pcm_data_start += len; + pcm_data_size -= len; +} + +void pcm_play_lock(void) +{ +} + +void pcm_play_unlock(void) +{ +} + +void pcm_dma_apply_settings(void) +{ +} + +void pcm_play_dma_start(const void *addr, size_t size) +{ + pcm_data_start = (char*)addr; + pcm_data_size = size; + + pcm_play_dma_pause(false); +} + +void pcm_play_dma_stop(void) +{ + (*env_ptr)->CallVoidMethod(env_ptr, + RockboxPCM_instance, + stop_method); +} + +void pcm_play_dma_pause(bool pause) +{ + (*env_ptr)->CallVoidMethod(env_ptr, + RockboxPCM_instance, + play_pause_method, + (int)pause); +} + +size_t pcm_get_bytes_waiting(void) +{ + return pcm_data_size; +} + +const void * pcm_play_dma_get_peak_buffer(int *count) +{ + uintptr_t addr = (uintptr_t)pcm_data_start; + *count = pcm_data_size / 4; + return (void *)((addr + 3) & ~3); +} + +void pcm_play_dma_init(void) +{ + /* in order to have background music playing after leaving the activity, + * we need to allocate the PCM object from the Rockbox thread (the Activity + * runs in a separate thread because it would otherwise kill us when + * stopping it) + * + * Luckily we only reference the PCM object from here, so it's safe (and + * clean) to allocate it here + **/ + JNIEnv e = *env_ptr; + /* get the class and its constructor */ + RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM"); + jmethodID constructor = e->GetMethodID(env_ptr, RockboxPCM_class, "", "()V"); + /* instance = new RockboxPCM() */ + RockboxPCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor); + /* cache needed methods */ + 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) +{ +} + +void pcm_set_mixer_volume(int volume) +{ + (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume); +} -- cgit v1.2.3