# Problem with SDL SDL\_RWops "magic" for Android

**URL:** <https://discourse.libsdl.org/t/problem-with-sdl-sdl-rwops-magic-for-android/18943>\
**Category:** SDL Development\
**Created:** [May 25, 2012, 11:12pm UTC](https://discourse.libsdl.org/t/problem-with-sdl-sdl-rwops-magic-for-android/18943 "2012-05-25T23:12:02Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![William\_Dyce](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/william_dyce/32/2381_2.png) [@William\_Dyce](https://discourse.libsdl.org/u/William_Dyce)\
**Post date:** [May 25, 2012, 11:12pm UTC](https://discourse.libsdl.org/t/problem-with-sdl-sdl-rwops-magic-for-android/18943/1 "2012-05-25T23:12:02Z")

</div>

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 😉

---

<div class="post-metadata">

**Author:** ![John5](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/j/7993a0/32.png) [@John5](https://discourse.libsdl.org/u/John5)\
**Post date:** [May 26, 2012, 4:08pm UTC](https://discourse.libsdl.org/t/problem-with-sdl-sdl-rwops-magic-for-android/18943/2 "2012-05-26T16:08:09Z")

</div>

Avoid the combination of SDL\_Mixer, SDL\_RWops, and assets on Android if  
possible. First problem: SDL seek is implemented as a close(), followed by a  
re-open, then repeatedly reading until it hits the offset. The reason has to do  
with the assets stream, it’s a forward-only, read-only decompression stream.  
Second problem: SDL\_mixer likes to seek() in certain cases as a kind of `probe`  
to see what the stream does. This wreaks havoc on the assets stream or any other  
non-trivial stream. Third problem: SDL’s seek will mask bad code by clamping to  
boundaries. SDL\_mixer appears to rely on this clamping, and in some cases will  
seek to extreme offsets such ((size\_t)-1). Fourth problem: SDL\_mixer triggers  
some fun reports from valgrind. Fifth problem: it’s pretty easy to crash SDL on  
Android by touching any of the streams after the app is restored from background  
or orientation has changed. If you are targeting platform 10 or above, you can  
directly access assets via the direct C api.On 05/25/2012 07:12 PM, William Dyce wrote:

> 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 😉
> 
> * * *
> 
> SDL mailing list  
> SDL at [lists.libsdl.org](http://lists.libsdl.org)  
> [http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org](http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)

---

<div class="post-metadata">

**Author:** ![Gabriel\_Jacobo](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/gabriel_jacobo/32/1968_2.png) [@Gabriel\_Jacobo](https://discourse.libsdl.org/u/Gabriel_Jacobo)\
**Post date:** [May 26, 2012, 4:24pm UTC](https://discourse.libsdl.org/t/problem-with-sdl-sdl-rwops-magic-for-android/18943/3 "2012-05-26T16:24:53Z")

</div>

2012/5/26 John

> Avoid the combination of SDL\_Mixer, SDL\_RWops, and assets on Android if  
> possible. First problem: SDL seek is implemented as a close(), followed by  
> a re-open, then repeatedly reading until it hits the offset. The reason has  
> to do with the assets stream, it’s a forward-only, read-only decompression  
> stream.

We actually had a more gracious system but we had to remove it and replace  
it by the current hack due to an Android bug.  
[http://bugzilla.libsdl.org/show\_bug.cgi?id=1301--](http://bugzilla.libsdl.org/show_bug.cgi?id=1301--)  
Gabriel.
