| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #include "embedders/openglui/android/android_sound_handler.h" | |
| 6 | |
| 7 #include "embedders/openglui/android/android_resource.h" | |
| 8 #include "embedders/openglui/common/log.h" | |
| 9 | |
| 10 AndroidSoundHandler::AndroidSoundHandler(android_app* application) | |
| 11 : SoundHandler(), | |
| 12 application_(application), | |
| 13 engine_(NULL), | |
| 14 engine_if_(NULL), | |
| 15 output_mix_(NULL), | |
| 16 background_player_(NULL), | |
| 17 background_player_if_(NULL), | |
| 18 background_player_seek_if_(NULL), | |
| 19 sample_player_(NULL), | |
| 20 sample_player_if_(NULL), | |
| 21 sample_player_queue_(NULL) { | |
| 22 } | |
| 23 | |
| 24 int32_t AndroidSoundHandler::Start() { | |
| 25 LOGI("Starting SoundService"); | |
| 26 | |
| 27 const SLInterfaceID k_engine_mix_IIDs[] = { SL_IID_ENGINE }; | |
| 28 const SLboolean k_engine_mix_reqs[] = { SL_BOOLEAN_TRUE }; | |
| 29 const SLInterfaceID k_output_mix_IIDs[] = {}; | |
| 30 const SLboolean k_output_mix_reqs[] = {}; | |
| 31 int32_t res = slCreateEngine(&engine_, 0, NULL, 1, | |
| 32 k_engine_mix_IIDs, k_engine_mix_reqs); | |
| 33 if (res == SL_RESULT_SUCCESS) { | |
| 34 res = (*engine_)->Realize(engine_, SL_BOOLEAN_FALSE); | |
| 35 if (res == SL_RESULT_SUCCESS) { | |
| 36 res = (*engine_)->GetInterface(engine_, SL_IID_ENGINE, &engine_if_); | |
| 37 if (res == SL_RESULT_SUCCESS) { | |
| 38 res = (*engine_if_)->CreateOutputMix(engine_if_, &output_mix_, 0, | |
| 39 k_output_mix_IIDs, k_output_mix_reqs); | |
| 40 if (res == SL_RESULT_SUCCESS) { | |
| 41 res = (*output_mix_)->Realize(output_mix_, SL_BOOLEAN_FALSE); | |
| 42 if (res == SL_RESULT_SUCCESS) { | |
| 43 if (StartSamplePlayer() == 0) { | |
| 44 return 0; | |
| 45 } | |
| 46 } | |
| 47 } | |
| 48 } | |
| 49 } | |
| 50 } | |
| 51 LOGI("Failed to start SoundService"); | |
| 52 Stop(); | |
| 53 return -1; | |
| 54 } | |
| 55 | |
| 56 void AndroidSoundHandler::Stop() { | |
| 57 LOGI("Stopping SoundService"); | |
| 58 if (sample_player_ != NULL) { | |
| 59 LOGI("Destroying sample player"); | |
| 60 (*sample_player_)->Destroy(sample_player_); | |
| 61 sample_player_ = NULL; | |
| 62 sample_player_if_ = NULL; | |
| 63 sample_player_queue_ = NULL; | |
| 64 } | |
| 65 samples_.clear(); | |
| 66 if (output_mix_ != NULL) { | |
| 67 LOGI("Destroying output mix"); | |
| 68 (*output_mix_)->Destroy(output_mix_); | |
| 69 output_mix_ = NULL; | |
| 70 } | |
| 71 if (engine_ != NULL) { | |
| 72 LOGI("Destroying engine"); | |
| 73 (*engine_)->Destroy(engine_); | |
| 74 engine_ = NULL; | |
| 75 engine_if_ = NULL; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 int32_t AndroidSoundHandler::SetBackgroundPlayerState(int state) { | |
| 80 if (background_player_if_ != NULL) { | |
| 81 SLuint32 state; | |
| 82 (*background_player_)->GetState(background_player_, &state); | |
| 83 if (state == SL_OBJECT_STATE_REALIZED) { | |
| 84 (*background_player_if_)->SetPlayState(background_player_if_, | |
| 85 state); | |
| 86 return 0; | |
| 87 } | |
| 88 } | |
| 89 return -1; | |
| 90 } | |
| 91 | |
| 92 int32_t AndroidSoundHandler::Pause() { | |
| 93 return SetBackgroundPlayerState(SL_PLAYSTATE_PAUSED); | |
| 94 } | |
| 95 | |
| 96 | |
| 97 int32_t AndroidSoundHandler::Resume() { | |
| 98 return SetBackgroundPlayerState(SL_PLAYSTATE_PLAYING); | |
| 99 } | |
| 100 | |
| 101 int32_t AndroidSoundHandler::CreateAudioPlayer(SLEngineItf engine_if, | |
| 102 const SLInterfaceID extra_if, | |
| 103 SLDataSource data_source, | |
| 104 SLDataSink data_sink, | |
| 105 SLObjectItf& player_out, | |
| 106 SLPlayItf& player_if_out) { | |
| 107 const SLuint32 SoundPlayerIIDCount = 2; | |
| 108 const SLInterfaceID SoundPlayerIIDs[] = { SL_IID_PLAY, extra_if }; | |
| 109 const SLboolean SoundPlayerReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; | |
| 110 int32_t res = (*engine_if)->CreateAudioPlayer(engine_if, | |
| 111 &player_out, | |
| 112 &data_source, | |
| 113 &data_sink, | |
| 114 SoundPlayerIIDCount, | |
| 115 SoundPlayerIIDs, | |
| 116 SoundPlayerReqs); | |
| 117 | |
| 118 if (res == SL_RESULT_SUCCESS) { | |
| 119 res = (*player_out)->Realize(player_out, SL_BOOLEAN_FALSE); | |
| 120 if (res == SL_RESULT_SUCCESS) { | |
| 121 res = (*player_out)->GetInterface(sample_player_, | |
| 122 SL_IID_PLAY, | |
| 123 &player_if_out); | |
| 124 if (res == SL_RESULT_SUCCESS) { | |
| 125 return 0; | |
| 126 } | |
| 127 } | |
| 128 } | |
| 129 return -1; | |
| 130 } | |
| 131 | |
| 132 int32_t AndroidSoundHandler::PlayBackground(const char* path) { | |
| 133 LOGI("Creating audio player"); | |
| 134 | |
| 135 Resource resource(path); | |
| 136 int fd = resource.descriptor(); | |
| 137 if (fd < 0) { | |
| 138 LOGI("Could not open file %s", path); | |
| 139 return -1; | |
| 140 } | |
| 141 | |
| 142 SLDataLocator_AndroidFD data_locator_in = { | |
| 143 SL_DATALOCATOR_ANDROIDFD, | |
| 144 fd, | |
| 145 resource.start(), | |
| 146 resource.length() | |
| 147 }; | |
| 148 SLDataFormat_MIME data_format = { | |
| 149 SL_DATAFORMAT_MIME, | |
| 150 NULL, | |
| 151 SL_CONTAINERTYPE_UNSPECIFIED | |
| 152 }; | |
| 153 SLDataSource data_source = { &data_locator_in, &data_format }; | |
| 154 | |
| 155 resource.Close(); | |
| 156 | |
| 157 SLDataLocator_OutputMix data_locator_out = | |
| 158 { SL_DATALOCATOR_OUTPUTMIX, output_mix_ }; | |
| 159 SLDataSink data_sink = { &data_locator_out, NULL }; | |
| 160 | |
| 161 int32_t res = CreateAudioPlayer(engine_if_, | |
| 162 SL_IID_SEEK, | |
| 163 data_source, | |
| 164 data_sink, | |
| 165 background_player_, | |
| 166 background_player_if_); | |
| 167 | |
| 168 if (res != SL_RESULT_SUCCESS) { | |
| 169 LOGE("Couldn't create audio player"); | |
| 170 return -1; | |
| 171 } | |
| 172 | |
| 173 if ((*background_player_)-> | |
| 174 GetInterface(background_player_, SL_IID_SEEK, | |
| 175 &background_player_seek_if_) != SL_RESULT_SUCCESS) { | |
| 176 LOGE("Couldn't get seek interface"); | |
| 177 return -1; | |
| 178 } | |
| 179 LOGI("Got seek interface"); | |
| 180 if ((*background_player_seek_if_)-> | |
| 181 SetLoop(background_player_seek_if_, SL_BOOLEAN_TRUE, 0, | |
| 182 SL_TIME_UNKNOWN) != SL_RESULT_SUCCESS) { | |
| 183 LOGE("Couldn't set loop"); | |
| 184 return -1; | |
| 185 } | |
| 186 LOGI("Set loop"); | |
| 187 if ((*background_player_if_)-> | |
| 188 SetPlayState(background_player_if_, SL_PLAYSTATE_PLAYING) != | |
| 189 SL_RESULT_SUCCESS) { | |
| 190 LOGE("Couldn't start playing"); | |
| 191 return -1; | |
| 192 } | |
| 193 LOGI("Started playing"); | |
| 194 return 0; | |
| 195 } | |
| 196 | |
| 197 void AndroidSoundHandler::StopBackground() { | |
| 198 if (Pause() == 0) { | |
| 199 (*background_player_)->Destroy(background_player_); | |
| 200 background_player_ = NULL; | |
| 201 background_player_if_ = NULL; | |
| 202 background_player_seek_if_ = NULL; | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 int32_t AndroidSoundHandler::StartSamplePlayer() { | |
| 207 SLDataLocator_AndroidSimpleBufferQueue data_locator_in = { | |
| 208 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, | |
| 209 1 | |
| 210 }; | |
| 211 | |
| 212 SLDataFormat_PCM data_format= { | |
| 213 SL_DATAFORMAT_PCM, | |
| 214 1, | |
| 215 SL_SAMPLINGRATE_44_1, | |
| 216 SL_PCMSAMPLEFORMAT_FIXED_16, | |
| 217 SL_PCMSAMPLEFORMAT_FIXED_16, | |
| 218 SL_SPEAKER_FRONT_CENTER, | |
| 219 SL_BYTEORDER_LITTLEENDIAN | |
| 220 }; | |
| 221 | |
| 222 SLDataSource data_source = { &data_locator_in, &data_format }; | |
| 223 | |
| 224 SLDataLocator_OutputMix data_locator_out = | |
| 225 { SL_DATALOCATOR_OUTPUTMIX, output_mix_ }; | |
| 226 SLDataSink data_sink = { &data_locator_out, NULL }; | |
| 227 | |
| 228 int32_t res = CreateAudioPlayer(engine_if_, SL_IID_BUFFERQUEUE, | |
| 229 data_source, | |
| 230 data_sink, | |
| 231 sample_player_, sample_player_if_); | |
| 232 | |
| 233 if (res == SL_RESULT_SUCCESS) { | |
| 234 res = (*sample_player_)->GetInterface(sample_player_, | |
| 235 SL_IID_BUFFERQUEUE, | |
| 236 &sample_player_queue_); | |
| 237 if (res == SL_RESULT_SUCCESS) { | |
| 238 res = (*sample_player_if_)->SetPlayState(sample_player_if_, | |
| 239 SL_PLAYSTATE_PLAYING); | |
| 240 if (res == SL_RESULT_SUCCESS) { | |
| 241 return 0; | |
| 242 } | |
| 243 } | |
| 244 } | |
| 245 LOGE("Error while starting sample player"); | |
| 246 return -1; | |
| 247 } | |
| 248 | |
| 249 int32_t AndroidSoundHandler::PlaySample(const char* path) { | |
| 250 SLuint32 state; | |
| 251 (*sample_player_)->GetState(sample_player_, &state); | |
| 252 if (state != SL_OBJECT_STATE_REALIZED) { | |
| 253 LOGE("Sample player has not been realized"); | |
| 254 } else { | |
| 255 Sample* sample = GetSample(path); | |
| 256 if (sample != NULL) { | |
| 257 int16_t* buffer = reinterpret_cast<int16_t*>(sample->buffer()); | |
| 258 off_t len = sample->length(); | |
| 259 | |
| 260 // Remove any current sample. | |
| 261 int32_t res = (*sample_player_queue_)->Clear(sample_player_queue_); | |
| 262 if (res == SL_RESULT_SUCCESS) { | |
| 263 res = (*sample_player_queue_)->Enqueue(sample_player_queue_, | |
| 264 buffer, len); | |
| 265 if (res == SL_RESULT_SUCCESS) { | |
| 266 LOGE("Enqueued sample %s of length %d", path, | |
| 267 static_cast<int>(len)); | |
| 268 return 0; | |
| 269 } | |
| 270 LOGE("Enqueueing sample failed"); | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 return -1; | |
| 275 } | |
| 276 | |
| 277 | |
| OLD | NEW |