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