diff --git a/recipes/android/src/android_mixer.py b/recipes/android/src/android_mixer.py index 9b2de14747..df2c15e870 100644 --- a/recipes/android/src/android_mixer.py +++ b/recipes/android/src/android_mixer.py @@ -113,6 +113,8 @@ def play(self, s, loops=0, maxtime=0, fade_ms=0): with condition: condition.notify() + def seek(self, position): + sound.seek(self.id, position) def stop(self): self.loop = None @@ -159,6 +161,12 @@ def queue(self, s): def get_queue(self): return self.queued + def get_pos(self): + return sound.get_pos(self.id)/1000. + + def get_length(self): + return sound.get_length(self.id)/1000. + def Channel(n): """ @@ -205,6 +213,7 @@ def play(self, loops=0, maxtime=0, fade_ms=0): channel.play(self, loops=loops) return channel + def stop(self): for i in range(0, num_channels): if Channel(i).get_sound() is self: @@ -254,6 +263,10 @@ def play(loops=0, start=0.0): def rewind(): music_channel.play(music_sound) + @staticmethod + def seek(position): + music_channel.seek(position) + @staticmethod def stop(): music_channel.stop() @@ -284,7 +297,7 @@ def get_busy(): @staticmethod def get_pos(): - return 0 + return music_channel.get_pos() @staticmethod def queue(filename): diff --git a/recipes/android/src/android_sound.pyx b/recipes/android/src/android_sound.pyx index a817f1cf3b..2ecd50777f 100644 --- a/recipes/android/src/android_sound.pyx +++ b/recipes/android/src/android_sound.pyx @@ -1,6 +1,7 @@ cdef extern void android_sound_queue(int, char *, char *, long long, long long) cdef extern void android_sound_play(int, char *, char *, long long, long long) cdef extern void android_sound_stop(int) +cdef extern void android_sound_seek(int, float) cdef extern void android_sound_dequeue(int) cdef extern void android_sound_playing_name(int, char *, int) cdef extern void android_sound_pause(int) @@ -11,6 +12,8 @@ cdef extern void android_sound_set_secondary_volume(int, float) cdef extern void android_sound_set_pan(int, float) cdef extern int android_sound_queue_depth(int) +cdef extern int android_sound_get_pos(int) +cdef extern int android_sound_get_length(int) channels = set() volumes = { } @@ -18,8 +21,8 @@ volumes = { } def queue(channel, file, name, fadein=0, tight=False): channels.add(channel) - - real_fn = file.name + + real_fn = file.name base = getattr(file, "base", -1) length = getattr(file, "length", -1) @@ -28,13 +31,16 @@ def queue(channel, file, name, fadein=0, tight=False): def play(channel, file, name, paused=False, fadein=0, tight=False): channels.add(channel) - + real_fn = file.name base = getattr(file, "base", -1) length = getattr(file, "length", -1) android_sound_play(channel, name, real_fn, base, length) +def seek(channel, position): + android_sound_seek(channel, position) + def stop(channel): android_sound_stop(channel) @@ -70,7 +76,7 @@ def unpause_all(): def pause_all(): for i in channels: pause(i) - + def fadeout(channel, ms): stop(channel) @@ -78,12 +84,15 @@ def busy(channel): return playing_name(channel) != None def get_pos(channel): - return 0 + return android_sound_get_pos(channel) + +def get_length(channel): + return android_sound_get_length(channel) def set_volume(channel, volume): android_sound_set_volume(channel, volume) volumes[channel] = volume - + def set_secondary_volume(channel, volume): android_sound_set_secondary_volume(channel, volume) diff --git a/recipes/android/src/android_sound_jni.c b/recipes/android/src/android_sound_jni.c index e4f607d8b8..1bcf6425b3 100644 --- a/recipes/android/src/android_sound_jni.c +++ b/recipes/android/src/android_sound_jni.c @@ -25,14 +25,14 @@ void android_sound_queue(int channel, char *filename, char *real_fn, long long b } PUSH_FRAME; - + (*env)->CallStaticVoidMethod( env, cls, mid, channel, (*env)->NewStringUTF(env, filename), (*env)->NewStringUTF(env, real_fn), (jlong) base, - (jlong) length); + (jlong) length); POP_FRAME; } @@ -41,7 +41,7 @@ void android_sound_play(int channel, char *filename, char *real_fn, long long ba static JNIEnv *env = NULL; static jclass *cls = NULL; static jmethodID mid = NULL; - + if (env == NULL) { env = SDL_ANDROID_GetJNIEnv(); aassert(env); @@ -52,7 +52,7 @@ void android_sound_play(int channel, char *filename, char *real_fn, long long ba } PUSH_FRAME; - + (*env)->CallStaticVoidMethod( env, cls, mid, channel, @@ -64,6 +64,26 @@ void android_sound_play(int channel, char *filename, char *real_fn, long long ba POP_FRAME; } +void android_sound_seek(int channel, float position){ + static JNIEnv *env = NULL; + static jclass *cls = NULL; + static jmethodID mid = NULL; + + if (env == NULL) { + env = SDL_ANDROID_GetJNIEnv(); + aassert(env); + cls = (*env)->FindClass(env, "org/renpy/android/RenPySound"); + aassert(cls); + mid = (*env)->GetStaticMethodID(env, cls, "seek", "(IF)V"); + aassert(mid); + } + + (*env)->CallStaticVoidMethod( + env, cls, mid, + channel, + (jfloat) position); +} + void android_sound_stop(int channel) { static JNIEnv *env = NULL; static jclass *cls = NULL; @@ -128,7 +148,7 @@ void android_sound_playing_name(int channel, char *buf, int buflen) { jobject s = NULL; char *jbuf; - + if (env == NULL) { env = SDL_ANDROID_GetJNIEnv(); aassert(env); @@ -139,7 +159,7 @@ void android_sound_playing_name(int channel, char *buf, int buflen) { } PUSH_FRAME; - + s = (*env)->CallStaticObjectMethod( env, cls, mid, channel); @@ -248,3 +268,41 @@ void android_sound_unpause(int channel) { env, cls, mid, channel); } + +int android_sound_get_pos(int channel) { + static JNIEnv *env = NULL; + static jclass *cls = NULL; + static jmethodID mid = NULL; + + if (env == NULL) { + env = SDL_ANDROID_GetJNIEnv(); + aassert(env); + cls = (*env)->FindClass(env, "org/renpy/android/RenPySound"); + aassert(cls); + mid = (*env)->GetStaticMethodID(env, cls, "get_pos", "(I)I"); + aassert(mid); + } + + (*env)->CallStaticIntMethod( + env, cls, mid, + channel); +} + +int android_sound_get_length(int channel) { + static JNIEnv *env = NULL; + static jclass *cls = NULL; + static jmethodID mid = NULL; + + if (env == NULL) { + env = SDL_ANDROID_GetJNIEnv(); + aassert(env); + cls = (*env)->FindClass(env, "org/renpy/android/RenPySound"); + aassert(cls); + mid = (*env)->GetStaticMethodID(env, cls, "get_length", "(I)I"); + aassert(mid); + } + + (*env)->CallStaticIntMethod( + env, cls, mid, + channel); +} diff --git a/src/src/org/renpy/android/RenPySound.java b/src/src/org/renpy/android/RenPySound.java index 4b3734af85..35ef3bbebd 100644 --- a/src/src/org/renpy/android/RenPySound.java +++ b/src/src/org/renpy/android/RenPySound.java @@ -7,37 +7,37 @@ import java.util.HashMap; public class RenPySound { - + private static class Channel implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener { // MediaPlayers for the currently playing and queued up // sounds. MediaPlayer player[]; - + // Filenames for the currently playing and queued up sounds. String filename[]; // Is the corresponding player prepareD? boolean prepared[]; - + // The volume for the left and right channel. double volume; double secondary_volume; double left_volume; double right_volume; - + Channel() { player = new MediaPlayer[2]; filename = new String[2]; prepared = new boolean[2]; - + player[0] = new MediaPlayer(); player[1] = new MediaPlayer(); volume = 1.0; secondary_volume = 1.0; left_volume = 1.0; - right_volume = 1.0; + right_volume = 1.0; } /** @@ -50,7 +50,7 @@ synchronized void queue(String fn, String real_fn, long base, long length) { try { FileInputStream f = new FileInputStream(real_fn); - + if (length >= 0) { mp.setDataSource(f.getFD(), base, length); } else { @@ -59,18 +59,18 @@ synchronized void queue(String fn, String real_fn, long base, long length) { mp.setOnCompletionListener(this); mp.setOnPreparedListener(this); - + mp.prepareAsync(); - + f.close(); } catch (IOException e) { Log.w("RenPySound", e); return; } - - filename[1] = fn; - + + filename[1] = fn; + } /** @@ -80,26 +80,36 @@ synchronized void play() { MediaPlayer tmp; player[0].reset(); - + tmp = player[0]; player[0] = player[1]; player[1] = tmp; - + filename[0] = filename[1]; filename[1] = null; prepared[0] = prepared[1]; prepared[1] = false; - + if (filename[0] != null) { updateVolume(); - if (prepared[0]) { + if (prepared[0]) { player[0].start(); } } } - + + /** + * Seek to the position specified on this channel + */ + + synchronized void seek(float position) { + if (prepared[0]){ + player[0].seekTo((int)position*1000); + } + } + /** * Stop playback on this channel. */ @@ -161,7 +171,7 @@ synchronized void set_pan(float pan) { left_volume = 1.0 - pan; right_volume = 1.0; } - + updateVolume(); } @@ -177,6 +187,17 @@ synchronized void unpause() { } } + synchronized int get_pos(){ + return player[0].getCurrentPosition(); + } + + synchronized int get_length(){ + if (prepared[0]) { + return player[0].getDuration(); + } + return 1; + } + synchronized public void onPrepared(MediaPlayer mp) { if (mp == player[0]) { prepared[0] = true; @@ -187,7 +208,7 @@ synchronized public void onPrepared(MediaPlayer mp) { prepared[1] = true; } } - + /** * Called on completion. */ @@ -197,7 +218,7 @@ synchronized public void onCompletion(MediaPlayer mp) { } } - + } // A map from channel number to channel object. @@ -224,7 +245,7 @@ static void queue(int channel, String filename, String real_fn, long base, long if (c.filename[0] == null) { c.play(); } - + } static void play(int channel, @@ -238,6 +259,11 @@ static void play(int channel, c.play(); } + static void seek(int channel, float position){ + Channel c = getChannel(channel); + c.seek(position); + } + static void stop(int channel) { Channel c = getChannel(channel); c.stop(); @@ -291,8 +317,18 @@ static void unpause(int channel) { c.unpause(); } + static int get_pos(int channel){ + Channel c = getChannel(channel); + return c.get_pos(); + } + + static int get_length(int channel){ + Channel c = getChannel(channel); + return c.get_length(); + } + static { new MediaPlayer(); } - -} \ No newline at end of file + +}