Skip to content

Commit

Permalink
Mixer abstraction. Fixes #39
Browse files Browse the repository at this point in the history
Most modules ported, some still missing
  • Loading branch information
thp committed Mar 26, 2014
1 parent 2a578f9 commit 1794cc4
Show file tree
Hide file tree
Showing 14 changed files with 534 additions and 167 deletions.
2 changes: 1 addition & 1 deletion audio/audio.c
Expand Up @@ -47,7 +47,7 @@ apkenv_audio_open(int frequency, enum AudioFormat format, int channels,
g_audio->config.format = format;
g_audio->config.channels = channels;
g_audio->config.buffer = buffer;
g_audio->config.callback = (void (*)(void *, Uint8 *, int))callback;
g_audio->config.callback = (void (*)(void *, void *, int))callback;
g_audio->config.user_data = user_data;
return g_audio->open(g_audio);
}
Expand Down
1 change: 1 addition & 0 deletions makefile
Expand Up @@ -16,6 +16,7 @@ SOURCES += $(wildcard debug/*.c)
SOURCES += $(wildcard debug/wrappers/*.c)
SOURCES += $(wildcard accelerometer/*.c)
SOURCES += $(wildcard audio/*.c)
SOURCES += $(wildcard mixer/*.c)

# Platform-specific targets and configuration
PLATFORM_INSTALL_TARGETS :=
Expand Down
163 changes: 163 additions & 0 deletions mixer/mixer.c
@@ -0,0 +1,163 @@
/**
* apkenv Mixer
* Copyright (c) 2014, Thomas Perl <m@thp.io>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#include "mixer.h"


struct Mixer *
g_mixer = 0;

void apkenv_mixer_register(struct Mixer *mixer)
{
g_mixer = mixer;
}

int
apkenv_mixer_open(int frequency, enum AudioFormat format, int channels, int buffer)
{
if (g_mixer) {
g_mixer->config.frequency = frequency;
g_mixer->config.format = format;
g_mixer->config.channels = channels;
g_mixer->config.buffer = buffer;
g_mixer->open(g_mixer);
}
}

void
apkenv_mixer_close()
{
if (g_mixer) {
g_mixer->close(g_mixer);
}
}

struct MixerMusic *
apkenv_mixer_load_music(const char *filename)
{
if (g_mixer) {
return g_mixer->load_music(g_mixer, filename);
}

return 0;
}

struct MixerMusic *
apkenv_mixer_load_music_buffer(const char *buffer, size_t size)
{
if (g_mixer) {
return g_mixer->load_music_buffer(g_mixer, buffer, size);
}

return 0;
}

struct MixerSound *
apkenv_mixer_load_sound(const char *filename)
{
if (g_mixer) {
return g_mixer->load_sound(g_mixer, filename);
}

return 0;
}

struct MixerSound *
apkenv_mixer_load_sound_buffer(const char *buffer, size_t size)
{
if (g_mixer) {
return g_mixer->load_sound_buffer(g_mixer, buffer, size);
}

return 0;
}

void
apkenv_mixer_free_music(struct MixerMusic *music)
{
if (g_mixer) {
g_mixer->free_music(g_mixer, music);
}
}

void
apkenv_mixer_free_sound(struct MixerSound *sound)
{
if (g_mixer) {
g_mixer->free_sound(g_mixer, sound);
}
}

void
apkenv_mixer_play_music(struct MixerMusic *music, int do_loop)
{
if (g_mixer) {
g_mixer->play_music(g_mixer, music, do_loop);
}
}

void
apkenv_mixer_play_sound(struct MixerSound *sound, int do_loop)
{
if (g_mixer) {
g_mixer->play_sound(g_mixer, sound, do_loop);
}
}

void
apkenv_mixer_stop_music(struct MixerMusic *music)
{
if (g_mixer) {
g_mixer->stop_music(g_mixer, music);
}
}

void
apkenv_mixer_stop_sound(struct MixerSound *sound)
{
if (g_mixer) {
g_mixer->stop_sound(g_mixer, sound);
}
}

void
apkenv_mixer_volume_music(struct MixerMusic *music, float volume)
{
if (g_mixer) {
g_mixer->volume_music(g_mixer, music, volume);
}
}

void
apkenv_mixer_volume_sound(struct MixerSound *sound, float volume)
{
if (g_mixer) {
g_mixer->volume_sound(g_mixer, sound, volume);
}
}
97 changes: 97 additions & 0 deletions mixer/mixer.h
@@ -0,0 +1,97 @@
/**
* apkenv Mixer
* Copyright (c) 2014, Thomas Perl <m@thp.io>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#ifndef APKENV_MIXER_H
#define APKENV_MIXER_H

#include "../audio/audio.h"

#include <stdlib.h>

struct MixerMusic;
struct MixerSound;

struct Mixer {
// Initialize the mixer
int (*open)(struct Mixer *mixer);

// Close the mixer
void (*close)(struct Mixer *mixer);

// Loading of data
struct MixerMusic *(*load_music)(struct Mixer *mixer,
const char *filename);
struct MixerMusic *(*load_music_buffer)(struct Mixer *mixer,
const char *buffer, size_t size);
struct MixerSound *(*load_sound)(struct Mixer *mixer,
const char *filename);
struct MixerSound *(*load_sound_buffer)(struct Mixer *mixer,
const char *buffer, size_t size);

// Freeing of data
void (*free_music)(struct Mixer *mixer, struct MixerMusic *music);
void (*free_sound)(struct Mixer *mixer, struct MixerSound *sound);

// Playback
void (*play_music)(struct Mixer *mixer, struct MixerMusic *music,
int do_loop);
void (*play_sound)(struct Mixer *mixer, struct MixerSound *sound,
int do_loop);
void (*stop_music)(struct Mixer *mixer, struct MixerMusic *music);
void (*stop_sound)(struct Mixer *mixer, struct MixerSound *sound);

// Volume control
void (*volume_music)(struct Mixer *mixer, struct MixerMusic *music,
float volume);
void (*volume_sound)(struct Mixer *mixer, struct MixerSound *sound,
float volume);

// Internal structure to store the config from init
struct AudioConfig config;
};


void apkenv_mixer_register(struct Mixer *mixer);

int apkenv_mixer_open(int frequency, enum AudioFormat format, int channels, int buffer);
void apkenv_mixer_close();
struct MixerMusic *apkenv_mixer_load_music(const char *filename);
struct MixerMusic *apkenv_mixer_load_music_buffer(const char *buffer, size_t size);
struct MixerSound *apkenv_mixer_load_sound(const char *filename);
struct MixerSound *apkenv_mixer_load_sound_buffer(const char *buffer, size_t size);
void apkenv_mixer_free_music(struct MixerMusic *music);
void apkenv_mixer_free_sound(struct MixerSound *sound);
void apkenv_mixer_play_music(struct MixerMusic *music, int do_loop);
void apkenv_mixer_play_sound(struct MixerSound *sound, int do_loop);
void apkenv_mixer_stop_music(struct MixerMusic *music);
void apkenv_mixer_stop_sound(struct MixerSound *sound);
void apkenv_mixer_volume_music(struct MixerMusic *music, float volume);
void apkenv_mixer_volume_sound(struct MixerSound *sound, float volume);

#endif /* APKENV_MIXER_H */
8 changes: 0 additions & 8 deletions modules/common.h
Expand Up @@ -92,12 +92,4 @@ enum {
typedef void (*jni_onload_t)(JavaVM *vm, void *reserved) SOFTFP;
typedef void (*jni_onunload_t)(JavaVM *vm, void *reserved) SOFTFP;

/* older SDL_mixer compatibility */
#ifdef MIX_MAJOR_VERSION
#if ((MIX_MAJOR_VERSION << 16) | (MIX_MINOR_VERSION << 8) | MIX_PATCHLEVEL) < 0x1020a
#define Mix_Init(x)
#define Mix_Quit()
#endif
#endif

#endif /* APKENV_MODULES_COMMON_H */
41 changes: 13 additions & 28 deletions modules/cuttherope.c
Expand Up @@ -36,11 +36,10 @@
#include <linux/limits.h>
#include <sys/stat.h>
#include <unistd.h>

#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include <string.h>

#include "common.h"
#include "../mixer/mixer.h"

typedef void (*cuttherope_init_t)(JNIEnv *env, jobject obj, jobject resourceLoader, jobject soundManager, jobject preferences,
jobject saveManager, jobject flurry, jobject videoPlayer, jobject scorer,
Expand All @@ -61,7 +60,7 @@ typedef void (*cuttherope_nativeplaybackfinished_t)(JNIEnv *env, jobject p0, jin
#define MAX_SOUNDS 256
typedef struct {
char* name;
Mix_Chunk* sound;
struct MixerSound *sound;
} Sound;

#define MAX_IMAGES 200
Expand Down Expand Up @@ -99,7 +98,7 @@ struct SupportModulePriv {
const char* home;
Sound sounds[MAX_SOUNDS];
Image images[MAX_IMAGES];
Mix_Music* music;
struct MixerMusic *music;
char musicpath[PATH_MAX];
KeyValue keyvalues[MAX_KEYVALUES];
int want_exit;
Expand Down Expand Up @@ -330,8 +329,7 @@ cuttherope_CallVoidMethodV(JNIEnv* env, jobject p1, jmethodID p2, va_list p3)
char* buffer;
size_t size;
if (GLOBAL_J(env)->read_file(filepath,&buffer,&size)) {
SDL_RWops *rw = SDL_RWFromMem(buffer, size);
Mix_Chunk *sound = Mix_LoadWAV_RW(rw, 1);
struct MixerSound *sound = apkenv_mixer_load_sound_buffer(buffer, size);
cuttherope_priv.sounds[soundId].sound = sound;
MODULE_DEBUG_PRINTF("loadSound id=%d %s.\n",soundId,sound?"ok":"failed");
}
Expand Down Expand Up @@ -362,7 +360,7 @@ cuttherope_CallVoidMethodV(JNIEnv* env, jobject p1, jmethodID p2, va_list p3)
if (soundId>=0 && soundId<MAX_SOUNDS && cuttherope_priv.sounds[soundId].sound!=0) {
MODULE_DEBUG_PRINTF("playSoundLooped id=%d loop=%d\n",soundId,loop);

Mix_PlayChannel(-1,cuttherope_priv.sounds[soundId].sound,loop);
apkenv_mixer_play_sound(cuttherope_priv.sounds[soundId].sound, loop);
}
}
else
Expand All @@ -376,17 +374,17 @@ cuttherope_CallVoidMethodV(JNIEnv* env, jobject p1, jmethodID p2, va_list p3)

if (strcmp(cuttherope_priv.musicpath,musicpath)!=0) {
if (cuttherope_priv.music!=NULL) {
Mix_HaltMusic();
Mix_FreeMusic(cuttherope_priv.music);
apkenv_mixer_stop_music(cuttherope_priv.music);
apkenv_mixer_free_music(cuttherope_priv.music);
}
cuttherope_priv.music = Mix_LoadMUS(musicpath);
Mix_PlayMusic(cuttherope_priv.music,-1);
cuttherope_priv.music = apkenv_mixer_load_music(musicpath);
apkenv_mixer_play_music(cuttherope_priv.music, 1);
}
}
else
if (strcmp(p2->name,"stopMusic")==0) {
if(cuttherope_priv.music!=NULL) {
Mix_HaltMusic();
apkenv_mixer_stop_music(cuttherope_priv.music);
}
}
else
Expand Down Expand Up @@ -599,20 +597,7 @@ cuttherope_init(struct SupportModule *self, int width, int height, const char *h
self->priv->home = strdup(home);

// init sound stuff
Mix_Init(MIX_INIT_OGG);

int audio_rate = 22050;
uint16_t audio_format = AUDIO_S16SYS;
int audio_channels = 2;
int audio_buffers = 1024;

if(Mix_OpenAudio(audio_rate,audio_format,audio_channels,audio_buffers)<0)
{
printf("Mix_OpenAudio failed %s.\n",Mix_GetError());
exit(-1);
}

Mix_AllocateChannels(16);
apkenv_mixer_open(22050, AudioFormat_S16SYS, 2, 1024);

memset(self->priv->sounds,0,sizeof(self->priv->sounds));
self->priv->music = NULL;
Expand Down Expand Up @@ -703,7 +688,7 @@ cuttherope_update(struct SupportModule *self)
static void
cuttherope_deinit(struct SupportModule *self)
{
Mix_CloseAudio();
apkenv_mixer_close();

save_preferences(); //not saving here in harmattan
}
Expand Down

0 comments on commit 1794cc4

Please sign in to comment.