diff --git a/JGE/include/JSoundSystem.h b/JGE/include/JSoundSystem.h index 240e9c594..0da8ab626 100644 --- a/JGE/include/JSoundSystem.h +++ b/JGE/include/JSoundSystem.h @@ -18,31 +18,32 @@ #include "JTypes.h" -#ifdef USE_PHONON -#include -#include +#ifdef ANDROID +#include +#include "SLES/OpenSLES_Android.h" +#elif defined USE_PHONON + #include + #include #else #ifdef WIN32 - - #include + #include #define WITH_FMOD #elif defined (PSP) - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #include "JAudio.h" - #include "JMP3.h" + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "JAudio.h" + #include "JMP3.h" #endif #ifdef WITH_FMOD - #include "../Dependencies/include/fmod.h" + #include "../Dependencies/include/fmod.h" #endif #endif @@ -50,29 +51,32 @@ #ifdef USE_PHONON class JMusic : public QObject { - Q_OBJECT + Q_OBJECT #else class JMusic { #endif public: - JMusic(); - ~JMusic(); - void Update(); - int getPlayTime(); + JMusic(); + ~JMusic(); + void Update(); + int getPlayTime(); #ifdef USE_PHONON - Phonon::AudioOutput* mOutput; - Phonon::MediaObject* mMediaObject; - public slots: - void seekAtTheBegining(); - + Phonon::AudioOutput* mOutput; + Phonon::MediaObject* mMediaObject; + public slots: + void seekAtTheBegining(); #elif defined (PSP) - JMP3* mTrack; + JMP3* mTrack; #elif defined WITH_FMOD - FSOUND_SAMPLE* mTrack; // MP3 needed to be of "sample" type for FMOD, FMUSIC_MODULE is for MODs + FSOUND_SAMPLE* mTrack; // MP3 needed to be of "sample" type for FMOD, FMUSIC_MODULE is for MODs +#elif defined ANDROID + SLObjectItf playerObject; + SLPlayItf playInterface; + SLSeekItf seekInterface; #else - void* mTrack; + void* mTrack; #endif //WITH_FMOD }; @@ -82,21 +86,25 @@ public: class JSample { public: - JSample(); - ~JSample(); + JSample(); + ~JSample(); - unsigned long fileSize(); + unsigned long fileSize(); #if defined (PSP) - WAVDATA *mSample; + WAVDATA *mSample; #elif defined (WITH_FMOD) - FSOUND_SAMPLE *mSample; + FSOUND_SAMPLE *mSample; #elif defined (USE_PHONON) - Phonon::AudioOutput* mOutput; - Phonon::MediaObject* mMediaObject; - void* mSample; + Phonon::AudioOutput* mOutput; + Phonon::MediaObject* mMediaObject; + void* mSample; +#elif defined ANDROID + SLObjectItf playerObject; + SLPlayItf playInterface; + void* mSample; #else - void* mSample; + void* mSample; #endif }; @@ -214,9 +222,7 @@ protected: private: #ifdef WIN32 - JMusic *mCurrentMusic; - #endif int mVolume; diff --git a/JGE/src/android/JSfx.cpp b/JGE/src/android/JSfx.cpp new file mode 100644 index 000000000..4611566de --- /dev/null +++ b/JGE/src/android/JSfx.cpp @@ -0,0 +1,306 @@ +#include "DebugRoutines.h" + +// for native audio +#include +#include "SLES/OpenSLES_Android.h" + +#include "../../include/JSoundSystem.h" +#include "../../include/JFileSystem.h" + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// + +// engine interfaces +static SLObjectItf engineObject = NULL; +static SLEngineItf engineEngine; + +// output mix interfaces +static SLObjectItf outputMixObject = NULL; +////////////////////////////////////////////////////////////////////////// + +JMusic::JMusic() + : playerObject(0), playInterface(0), seekInterface(0) +{ +} + +void JMusic::Update(){ + +} + +int JMusic::getPlayTime(){ + return 0; +} + +JMusic::~JMusic() +{ + // destroy file descriptor audio player object, and invalidate all associated interfaces + if (playerObject != NULL) { + (*playerObject)->Destroy(playerObject); + playerObject = NULL; + playInterface = NULL; + seekInterface = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +JSample::JSample() + : playerObject(0), playInterface(0) +{ + +} + +JSample::~JSample() +{ + // destroy file descriptor audio player object, and invalidate all associated interfaces + if (playerObject != NULL) { + (*playerObject)->Destroy(playerObject); + playerObject = NULL; + playInterface = NULL; + } +} + +unsigned long JSample::fileSize() +{ + return 0; +} + +////////////////////////////////////////////////////////////////////////// +JSoundSystem* JSoundSystem::mInstance = NULL; + +JSoundSystem* JSoundSystem::GetInstance() +{ + if (mInstance == NULL) + { + mInstance = new JSoundSystem(); + mInstance->InitSoundSystem(); + } + return mInstance; +} + + +void JSoundSystem::Destroy() +{ + if (mInstance) + { + mInstance->DestroySoundSystem(); + delete mInstance; + mInstance = NULL; + } +} + + +JSoundSystem::JSoundSystem() +{ + mVolume = 0; + mSampleVolume = 0; +} + +JSoundSystem::~JSoundSystem() +{ +} + +void JSoundSystem::InitSoundSystem() +{ + DebugTrace("InitSoundSystem enter"); + SLresult result; + + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + DebugTrace("result " << result); + + // realize the engine + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + DebugTrace("result " << result); + + // get the engine interface, which is needed in order to create other objects + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + DebugTrace("result " << result); + + // create output mix + const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; + const SLboolean req[1] = {SL_BOOLEAN_FALSE}; + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req); + DebugTrace("result " << result); + + // realize the output mix + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + DebugTrace("result " << result); + + DebugTrace("InitSoundSystem leave"); +} + + +void JSoundSystem::DestroySoundSystem() +{ + // destroy output mix object, and invalidate all associated interfaces + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + } + + // destroy engine object, and invalidate all associated interfaces + if (engineObject != NULL) { + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } +} + + +JMusic *JSoundSystem::LoadMusic(const char *fileName) +{ + JMusic* music = new JMusic(); + if (music) + { + // we should use the native asset manager instead + string fullpath = JFileSystem::GetInstance()->GetResourceFile(fileName); + int fd = open(fullpath.c_str(), O_RDONLY); + FILE* file = fdopen(fd, "r"); + off_t start = 0; + off_t length; + fseek(file, 0, SEEK_END); + length = ftell(file); + SLresult result; + + // configure audio source + SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length}; + SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; + SLDataSource audioSrc = {&loc_fd, &format_mime}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[2] = {SL_IID_SEEK, SL_IID_VOLUME}; + const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &music->playerObject, &audioSrc, &audioSnk, + 2, ids, req); + DebugTrace("result " << result); + + // realize the player + result = (*music->playerObject)->Realize(music->playerObject, SL_BOOLEAN_FALSE); + DebugTrace("result " << result); + + // get the play interface + result = (*music->playerObject)->GetInterface(music->playerObject, SL_IID_PLAY, &music->playInterface); + DebugTrace("result " << result); + + // get the seek interface + result = (*music->playerObject)->GetInterface(music->playerObject, SL_IID_SEEK, &music->seekInterface); + DebugTrace("result " << result); + + // get the volume interface + //result = (*music->playerObject)->GetInterface(music->playerObject, SL_IID_VOLUME, &musicVolumeInterface); + DebugTrace("result " << result); + } + return music; +} + + +void JSoundSystem::PlayMusic(JMusic *music, bool looping) +{ + if(music && music->playerObject && music->playInterface && music->seekInterface) + { + SLresult result; + + // enable whole file looping + result = (*music->seekInterface)->SetLoop(music->seekInterface, + looping?SL_BOOLEAN_TRUE:SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN); + assert(SL_RESULT_SUCCESS == result); + + result = (*music->playInterface)->SetPlayState(music->playInterface, + SL_PLAYSTATE_PLAYING); + assert(SL_RESULT_SUCCESS == result); + } +} + + +void JSoundSystem::StopMusic(JMusic *music) +{ + if(music && music->playerObject && music->playInterface && music->seekInterface) + { + SLresult result; + + result = (*music->playInterface)->SetPlayState(music->playInterface, + SL_PLAYSTATE_STOPPED); + assert(SL_RESULT_SUCCESS == result); + } +} + + +void JSoundSystem::SetVolume(int volume) +{ + SetMusicVolume(volume); + SetSfxVolume(volume); +} + +void JSoundSystem::SetMusicVolume(int volume) +{ + mVolume = volume; +} + +void JSoundSystem::SetSfxVolume(int volume){ + mSampleVolume = volume; + SetMusicVolume(mVolume); +} + +JSample *JSoundSystem::LoadSample(const char *fileName) +{ + JSample* sample = new JSample(); + if (sample) + { + string fullpath = JFileSystem::GetInstance()->GetResourceFile(fileName); + int fd = open(fullpath.c_str(), O_RDONLY); + FILE* file = fdopen(fd, "r"); + off_t start = 0; + off_t length; + fseek(file, 0, SEEK_END); + length = ftell(file); + SLresult result; + + // configure audio source + SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length}; + SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; + SLDataSource audioSrc = {&loc_fd, &format_mime}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[1] = {SL_IID_VOLUME}; + const SLboolean req[1] = {SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &sample->playerObject, &audioSrc, &audioSnk, + 1, ids, req); + DebugTrace("result " << result); + + // realize the player + result = (*sample->playerObject)->Realize(sample->playerObject, SL_BOOLEAN_FALSE); + DebugTrace("result " << result); + + // get the play interface + result = (*sample->playerObject)->GetInterface(sample->playerObject, SL_IID_PLAY, &sample->playInterface); + DebugTrace("result " << result); + + // get the volume interface + //result = (*sample->playerObject)->GetInterface(sample->playerObject, SL_IID_VOLUME, &sampleVolumeInterface); + } + return sample; +} + + +void JSoundSystem::PlaySample(JSample *sample) +{ + if(sample && sample->playerObject && sample->playInterface) + { + SLresult result; + + result = (*sample->playInterface)->SetPlayState(sample->playInterface, + SL_PLAYSTATE_PLAYING); + } +} + diff --git a/projects/mtg/Android/AndroidManifest.xml b/projects/mtg/Android/AndroidManifest.xml index f8e3a0aef..b38a3765f 100644 --- a/projects/mtg/Android/AndroidManifest.xml +++ b/projects/mtg/Android/AndroidManifest.xml @@ -3,10 +3,10 @@ package="org.libsdl.app" android:versionCode="1" android:versionName="1.0"> + - - - + + - + diff --git a/projects/mtg/Android/default.properties b/projects/mtg/Android/default.properties index 0b9250e02..9a2c9f6c8 100644 --- a/projects/mtg/Android/default.properties +++ b/projects/mtg/Android/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-8 +target=android-9 diff --git a/projects/mtg/Android/jni/Android.mk b/projects/mtg/Android/jni/Android.mk index 88c31c9cf..504992ed4 100644 --- a/projects/mtg/Android/jni/Android.mk +++ b/projects/mtg/Android/jni/Android.mk @@ -31,7 +31,7 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \ $(MTG_PATH)/src/ActionElement.cpp \ $(MTG_PATH)/src/ActionLayer.cpp \ $(MTG_PATH)/src/ActionStack.cpp \ - $(MTG_PATH)/src/AIHints.cpp \ + $(MTG_PATH)/src/AIHints.cpp \ $(MTG_PATH)/src/AIMomirPlayer.cpp \ $(MTG_PATH)/src/AIPlayer.cpp \ $(MTG_PATH)/src/AIStats.cpp \ @@ -81,11 +81,11 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \ $(MTG_PATH)/src/GuiPhaseBar.cpp \ $(MTG_PATH)/src/GuiPlay.cpp \ $(MTG_PATH)/src/GuiStatic.cpp \ - $(MTG_PATH)/src/IconButton.cpp \ + $(MTG_PATH)/src/IconButton.cpp \ $(MTG_PATH)/src/ManaCost.cpp \ $(MTG_PATH)/src/ManaCostHybrid.cpp \ $(MTG_PATH)/src/MenuItem.cpp \ - $(MTG_PATH)/src/ModRules.cpp \ + $(MTG_PATH)/src/ModRules.cpp \ $(MTG_PATH)/src/MTGAbility.cpp \ $(MTG_PATH)/src/MTGCard.cpp \ $(MTG_PATH)/src/MTGCardInstance.cpp \ @@ -164,17 +164,17 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \ $(JGE_PATH)/src/hge/hgeparticle.cpp \ $(JGE_PATH)/src/hge/hgerect.cpp \ $(JGE_PATH)/src/hge/hgevector.cpp \ - $(JGE_PATH)/src/zipFS/zfsystem.cpp \ - $(JGE_PATH)/src/zipFS/ziphdr.cpp \ - $(JGE_PATH)/src/zipFS/zstream.cpp \ - $(JGE_PATH)/src/pc/JSfx.cpp \ + $(JGE_PATH)/src/zipFS/zfsystem.cpp \ + $(JGE_PATH)/src/zipFS/ziphdr.cpp \ + $(JGE_PATH)/src/zipFS/zstream.cpp \ + $(JGE_PATH)/src/android/JSfx.cpp \ $(JGE_PATH)/src/pc/JGfx.cpp \ $(JGE_PATH)/src/JNetwork.cpp \ $(JGE_PATH)/src/pc/JSocket.cpp \ $(BOOST_PATH)/lib/pthread/thread.cpp \ $(BOOST_PATH)/lib/pthread/once.cpp -LOCAL_LDLIBS := -lGLESv1_CM -llog -lz +LOCAL_LDLIBS := -lGLESv1_CM -llog -lz -lOpenSLES include $(BUILD_SHARED_LIBRARY)