Hi all,
Finally gathered up the courage to give music streaming on Android another
try. On Android SDL_RWFromFile cleverly reads from the APK archive’s assets
folder via the JNI. This is great, but for streaming music it’s a problem
because it’s not thread-safe. This shouldn’t surprise anyone: streaming
data from a zip file, through java, the JNI, SDL, SDL_mixer… it’s a
recipe for disaster. As a result I’m exporting the files I want to stream
to the sdcard first, then streaming them (safely) from there.
At least that’s the idea. Trouble is Mixer_LoadMUS itself calls upon
SDL_RWFromFile, hence Mixer_LoadMUS("/sdcard/data/music.ogg") calls
SDL_RWFromFile("/sdcard/data/music.ogg") which, unless I’ve very much
mis-read the situation, goes looking for “/sdcard/data/music.ogg” in the
assets folder of the APP (?). The code that does this trick is *line 448 of
SDL_rwops.c
*#if defined(ANDROID)
rwops = SDL_AllocRW();
if (!rwops)
return NULL; / SDL_SetError already setup by
SDL_AllocRW() /
if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
SDL_FreeRW(rwops);
return NULL;
}
rwops->seek = Android_JNI_FileSeek;
rwops->read = Android_JNI_FileRead;
rwops->write = Android_JNI_FileWrite;
rwops->close = Android_JNI_FileClose;
It is called from line 46 of music_ogg.c
/ Load an OGG stream from the given file /
*OGG_music *OGG_new(const char file)
{
-
SDL_RWops rw;
-
rw = SDL_RWFromFile(file, “rb”);*
-
if ( rw == NULL ) {*
-
SDL_SetError("Couldn't open file %s", file);*
-
return NULL;*
-
}*
-
return OGG_new_RW(rw);*
}
It would be handy if the JNI file operations were used only for filenames
in the working directory, so without the initial ‘/’. Hence
*SDL_RWFromFile(const
char *file, const char mode), if Android is defined, could check file[0]
== ‘/’ .
I’m not sure how to implement this though: I’d need to tell the RWOps
struct that in this case, it should use the standard C fread, fseek, etc
operations, which work for Android. Until this is done Mix_LoadMUS isn’t
going to work. I’m also had some problems with fread(magic, 4, 1, fp) on
Android (won’t read 4 bytes? why?), though *fread(moremagic, 8, 1, fp)*works.
Long story short, either I load from the filesystem and mixer redirects the
search to the wrong place because of rwops, or I load using rwops from the
apk archive, in which case streaming is unsafe and the app crashes after
about 5 seconds (potentially longer… if you’re Irish and wearing a vest
made of 4-leaf clovers).
William
PS - oh, another thing: must be included
in the manifest or you can’t use fopen in write mode