blob: 749ef9622d6a358448b41fe30c8b5ca749f278ce [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/* MidiFile.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MidiFile"
20#include "utils/Log.h"
21
22#include <stdio.h>
23#include <assert.h>
24#include <limits.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <sched.h>
28#include <utils/threads.h>
29#include <libsonivox/eas_reverb.h>
30#include <sys/types.h>
31#include <sys/stat.h>
Glenn Kasten0512ab52011-05-04 17:58:57 -070032#include <unistd.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080033
Dima Zavin64760242011-05-11 14:15:23 -070034#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070035
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080036#include "MidiFile.h"
37
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080038// ----------------------------------------------------------------------------
39
40namespace android {
41
42// ----------------------------------------------------------------------------
43
44// The midi engine buffers are a bit small (128 frames), so we batch them up
45static const int NUM_BUFFERS = 4;
46
47// TODO: Determine appropriate return codes
48static status_t ERROR_NOT_OPEN = -1;
49static status_t ERROR_OPEN_FAILED = -2;
50static status_t ERROR_EAS_FAILURE = -3;
51static status_t ERROR_ALLOCATE_FAILED = -4;
52
53static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
54
55MidiFile::MidiFile() :
56 mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
57 mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
Dima Zavinfce7a472011-04-19 22:30:36 -070058 mStreamType(AUDIO_STREAM_MUSIC), mLoop(false), mExit(false),
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080059 mPaused(false), mRender(false), mTid(-1)
60{
Steve Block3856b092011-10-20 11:56:00 +010061 ALOGV("constructor");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080062
63 mFileLocator.path = NULL;
64 mFileLocator.fd = -1;
65 mFileLocator.offset = 0;
66 mFileLocator.length = 0;
67
68 // get the library configuration and do sanity check
69 if (pLibConfig == NULL)
70 pLibConfig = EAS_Config();
71 if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
Steve Block29357bc2012-01-06 19:20:56 +000072 ALOGE("EAS library/header mismatch");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080073 goto Failed;
74 }
75
76 // initialize EAS library
77 if (EAS_Init(&mEasData) != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +000078 ALOGE("EAS_Init failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080079 goto Failed;
80 }
81
82 // select reverb preset and enable
83 EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
84 EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
85
86 // create playback thread
87 {
88 Mutex::Autolock l(mMutex);
Glenn Kasten90100b52011-06-23 17:11:35 -070089 mThread = new MidiFileThread(this);
90 mThread->run("midithread", ANDROID_PRIORITY_AUDIO);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080091 mCondition.wait(mMutex);
Steve Block3856b092011-10-20 11:56:00 +010092 ALOGV("thread started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080093 }
94
95 // indicate success
96 if (mTid > 0) {
Steve Block3856b092011-10-20 11:56:00 +010097 ALOGV(" render thread(%d) started", mTid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080098 mState = EAS_STATE_READY;
99 }
100
101Failed:
102 return;
103}
104
105status_t MidiFile::initCheck()
106{
107 if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE;
108 return NO_ERROR;
109}
110
111MidiFile::~MidiFile() {
Steve Block3856b092011-10-20 11:56:00 +0100112 ALOGV("MidiFile destructor");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800113 release();
114}
115
Andreas Huber2db84552010-01-28 11:19:57 -0800116status_t MidiFile::setDataSource(
Mark Salyzyn77342f72014-06-18 16:31:32 -0700117 const sp<IMediaHTTPService> & /*httpService*/,
Andreas Huber1b86fe02014-01-29 11:13:26 -0800118 const char* path,
119 const KeyedVector<String8, String8> *) {
Steve Block3856b092011-10-20 11:56:00 +0100120 ALOGV("MidiFile::setDataSource url=%s", path);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800121 Mutex::Autolock lock(mMutex);
122
123 // file still open?
124 if (mEasHandle) {
125 reset_nosync();
126 }
127
128 // open file and set paused state
129 mFileLocator.path = strdup(path);
130 mFileLocator.fd = -1;
131 mFileLocator.offset = 0;
132 mFileLocator.length = 0;
133 EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
134 if (result == EAS_SUCCESS) {
135 updateState();
136 }
137
138 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000139 ALOGE("EAS_OpenFile failed: [%d]", (int)result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800140 mState = EAS_STATE_ERROR;
141 return ERROR_OPEN_FAILED;
142 }
143
144 mState = EAS_STATE_OPEN;
145 mPlayTime = 0;
146 return NO_ERROR;
147}
148
149status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
150{
Steve Block3856b092011-10-20 11:56:00 +0100151 ALOGV("MidiFile::setDataSource fd=%d", fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800152 Mutex::Autolock lock(mMutex);
153
154 // file still open?
155 if (mEasHandle) {
156 reset_nosync();
157 }
158
159 // open file and set paused state
160 mFileLocator.fd = dup(fd);
161 mFileLocator.offset = offset;
162 mFileLocator.length = length;
163 EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
164 updateState();
165
166 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000167 ALOGE("EAS_OpenFile failed: [%d]", (int)result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800168 mState = EAS_STATE_ERROR;
169 return ERROR_OPEN_FAILED;
170 }
171
172 mState = EAS_STATE_OPEN;
173 mPlayTime = 0;
174 return NO_ERROR;
175}
176
177status_t MidiFile::prepare()
178{
Steve Block3856b092011-10-20 11:56:00 +0100179 ALOGV("MidiFile::prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800180 Mutex::Autolock lock(mMutex);
181 if (!mEasHandle) {
182 return ERROR_NOT_OPEN;
183 }
184 EAS_RESULT result;
185 if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000186 ALOGE("EAS_Prepare failed: [%ld]", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800187 return ERROR_EAS_FAILURE;
188 }
189 updateState();
190 return NO_ERROR;
191}
192
193status_t MidiFile::prepareAsync()
194{
Steve Block3856b092011-10-20 11:56:00 +0100195 ALOGV("MidiFile::prepareAsync");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800196 status_t ret = prepare();
197
198 // don't hold lock during callback
199 if (ret == NO_ERROR) {
200 sendEvent(MEDIA_PREPARED);
201 } else {
202 sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
203 }
204 return ret;
205}
206
207status_t MidiFile::start()
208{
Steve Block3856b092011-10-20 11:56:00 +0100209 ALOGV("MidiFile::start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800210 Mutex::Autolock lock(mMutex);
211 if (!mEasHandle) {
212 return ERROR_NOT_OPEN;
213 }
214
215 // resuming after pause?
216 if (mPaused) {
217 if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
218 return ERROR_EAS_FAILURE;
219 }
220 mPaused = false;
221 updateState();
222 }
223
224 mRender = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700225 if (mState == EAS_STATE_PLAY) {
226 sendEvent(MEDIA_STARTED);
227 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800228
229 // wake up render thread
Steve Block3856b092011-10-20 11:56:00 +0100230 ALOGV(" wakeup render thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800231 mCondition.signal();
232 return NO_ERROR;
233}
234
235status_t MidiFile::stop()
236{
Steve Block3856b092011-10-20 11:56:00 +0100237 ALOGV("MidiFile::stop");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800238 Mutex::Autolock lock(mMutex);
239 if (!mEasHandle) {
240 return ERROR_NOT_OPEN;
241 }
242 if (!mPaused && (mState != EAS_STATE_STOPPED)) {
243 EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
244 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000245 ALOGE("EAS_Pause returned error %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800246 return ERROR_EAS_FAILURE;
247 }
248 }
249 mPaused = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700250 sendEvent(MEDIA_STOPPED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800251 return NO_ERROR;
252}
253
254status_t MidiFile::seekTo(int position)
255{
Steve Block3856b092011-10-20 11:56:00 +0100256 ALOGV("MidiFile::seekTo %d", position);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800257 // hold lock during EAS calls
258 {
259 Mutex::Autolock lock(mMutex);
260 if (!mEasHandle) {
261 return ERROR_NOT_OPEN;
262 }
263 EAS_RESULT result;
264 if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
265 != EAS_SUCCESS)
266 {
Steve Block29357bc2012-01-06 19:20:56 +0000267 ALOGE("EAS_Locate returned %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800268 return ERROR_EAS_FAILURE;
269 }
270 EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
271 }
272 sendEvent(MEDIA_SEEK_COMPLETE);
273 return NO_ERROR;
274}
275
276status_t MidiFile::pause()
277{
Steve Block3856b092011-10-20 11:56:00 +0100278 ALOGV("MidiFile::pause");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800279 Mutex::Autolock lock(mMutex);
280 if (!mEasHandle) {
281 return ERROR_NOT_OPEN;
282 }
283 if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
284 if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
285 return ERROR_EAS_FAILURE;
286 }
287 mPaused = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700288 sendEvent(MEDIA_PAUSED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800289 return NO_ERROR;
290}
291
292bool MidiFile::isPlaying()
293{
Steve Block3856b092011-10-20 11:56:00 +0100294 ALOGV("MidiFile::isPlaying, mState=%d", int(mState));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800295 if (!mEasHandle || mPaused) return false;
296 return (mState == EAS_STATE_PLAY);
297}
298
299status_t MidiFile::getCurrentPosition(int* position)
300{
Steve Block3856b092011-10-20 11:56:00 +0100301 ALOGV("MidiFile::getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800302 if (!mEasHandle) {
Steve Block29357bc2012-01-06 19:20:56 +0000303 ALOGE("getCurrentPosition(): file not open");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800304 return ERROR_NOT_OPEN;
305 }
306 if (mPlayTime < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000307 ALOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800308 return ERROR_EAS_FAILURE;
309 }
310 *position = mPlayTime;
311 return NO_ERROR;
312}
313
314status_t MidiFile::getDuration(int* duration)
315{
316
Steve Block3856b092011-10-20 11:56:00 +0100317 ALOGV("MidiFile::getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800318 {
319 Mutex::Autolock lock(mMutex);
320 if (!mEasHandle) return ERROR_NOT_OPEN;
321 *duration = mDuration;
322 }
323
324 // if no duration cached, get the duration
325 // don't need a lock here because we spin up a new engine
326 if (*duration < 0) {
327 EAS_I32 temp;
328 EAS_DATA_HANDLE easData = NULL;
329 EAS_HANDLE easHandle = NULL;
330 EAS_RESULT result = EAS_Init(&easData);
331 if (result == EAS_SUCCESS) {
332 result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
333 }
334 if (result == EAS_SUCCESS) {
335 result = EAS_Prepare(easData, easHandle);
336 }
337 if (result == EAS_SUCCESS) {
338 result = EAS_ParseMetaData(easData, easHandle, &temp);
339 }
340 if (easHandle) {
341 EAS_CloseFile(easData, easHandle);
342 }
343 if (easData) {
344 EAS_Shutdown(easData);
345 }
346
347 if (result != EAS_SUCCESS) {
348 return ERROR_EAS_FAILURE;
349 }
350
351 // cache successful result
352 mDuration = *duration = int(temp);
353 }
354
355 return NO_ERROR;
356}
357
358status_t MidiFile::release()
359{
Steve Block3856b092011-10-20 11:56:00 +0100360 ALOGV("MidiFile::release");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800361 Mutex::Autolock l(mMutex);
362 reset_nosync();
363
364 // wait for render thread to exit
365 mExit = true;
366 mCondition.signal();
367
368 // wait for thread to exit
369 if (mAudioBuffer) {
370 mCondition.wait(mMutex);
371 }
372
373 // release resources
374 if (mEasData) {
375 EAS_Shutdown(mEasData);
376 mEasData = NULL;
377 }
378 return NO_ERROR;
379}
380
381status_t MidiFile::reset()
382{
Steve Block3856b092011-10-20 11:56:00 +0100383 ALOGV("MidiFile::reset");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800384 Mutex::Autolock lock(mMutex);
385 return reset_nosync();
386}
387
388// call only with mutex held
389status_t MidiFile::reset_nosync()
390{
Steve Block3856b092011-10-20 11:56:00 +0100391 ALOGV("MidiFile::reset_nosync");
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700392 sendEvent(MEDIA_STOPPED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800393 // close file
394 if (mEasHandle) {
395 EAS_CloseFile(mEasData, mEasHandle);
396 mEasHandle = NULL;
397 }
398 if (mFileLocator.path) {
399 free((void*)mFileLocator.path);
400 mFileLocator.path = NULL;
401 }
402 if (mFileLocator.fd >= 0) {
403 close(mFileLocator.fd);
404 }
405 mFileLocator.fd = -1;
406 mFileLocator.offset = 0;
407 mFileLocator.length = 0;
408
409 mPlayTime = -1;
410 mDuration = -1;
411 mLoop = false;
412 mPaused = false;
413 mRender = false;
414 return NO_ERROR;
415}
416
417status_t MidiFile::setLooping(int loop)
418{
Steve Block3856b092011-10-20 11:56:00 +0100419 ALOGV("MidiFile::setLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800420 Mutex::Autolock lock(mMutex);
421 if (!mEasHandle) {
422 return ERROR_NOT_OPEN;
423 }
424 loop = loop ? -1 : 0;
425 if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
426 return ERROR_EAS_FAILURE;
427 }
428 return NO_ERROR;
429}
430
431status_t MidiFile::createOutputTrack() {
Jean-Michel Trivi786618f2012-03-02 14:54:07 -0800432 if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels,
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700433 CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2 /*bufferCount*/) != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000434 ALOGE("mAudioSink open failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800435 return ERROR_OPEN_FAILED;
436 }
437 return NO_ERROR;
438}
439
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800440int MidiFile::render() {
441 EAS_RESULT result = EAS_FAILURE;
442 EAS_I32 count;
443 int temp;
444 bool audioStarted = false;
445
Steve Block3856b092011-10-20 11:56:00 +0100446 ALOGV("MidiFile::render");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800447
448 // allocate render buffer
449 mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
450 if (!mAudioBuffer) {
Steve Block29357bc2012-01-06 19:20:56 +0000451 ALOGE("mAudioBuffer allocate failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800452 goto threadExit;
453 }
454
455 // signal main thread that we started
456 {
457 Mutex::Autolock l(mMutex);
Glenn Kasten0512ab52011-05-04 17:58:57 -0700458 mTid = gettid();
Steve Block3856b092011-10-20 11:56:00 +0100459 ALOGV("render thread(%d) signal", mTid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800460 mCondition.signal();
461 }
462
463 while (1) {
464 mMutex.lock();
465
466 // nothing to render, wait for client thread to wake us up
467 while (!mRender && !mExit)
468 {
Steve Block3856b092011-10-20 11:56:00 +0100469 ALOGV("MidiFile::render - signal wait");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800470 mCondition.wait(mMutex);
Steve Block3856b092011-10-20 11:56:00 +0100471 ALOGV("MidiFile::render - signal rx'd");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800472 }
473 if (mExit) {
474 mMutex.unlock();
475 break;
476 }
477
478 // render midi data into the input buffer
Steve Block3856b092011-10-20 11:56:00 +0100479 //ALOGV("MidiFile::render - rendering audio");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800480 int num_output = 0;
481 EAS_PCM* p = mAudioBuffer;
482 for (int i = 0; i < NUM_BUFFERS; i++) {
483 result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
484 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000485 ALOGE("EAS_Render returned %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800486 }
487 p += count * pLibConfig->numChannels;
488 num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
489 }
490
491 // update playback state and position
Steve Block3856b092011-10-20 11:56:00 +0100492 // ALOGV("MidiFile::render - updating state");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800493 EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
494 EAS_State(mEasData, mEasHandle, &mState);
495 mMutex.unlock();
496
497 // create audio output track if necessary
498 if (!mAudioSink->ready()) {
Steve Block3856b092011-10-20 11:56:00 +0100499 ALOGV("MidiFile::render - create output track");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800500 if (createOutputTrack() != NO_ERROR)
501 goto threadExit;
502 }
503
504 // Write data to the audio hardware
Steve Block3856b092011-10-20 11:56:00 +0100505 // ALOGV("MidiFile::render - writing to audio output");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800506 if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000507 ALOGE("Error in writing:%d",temp);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800508 return temp;
509 }
510
511 // start audio output if necessary
512 if (!audioStarted) {
Steve Block3856b092011-10-20 11:56:00 +0100513 //ALOGV("MidiFile::render - starting audio");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800514 mAudioSink->start();
515 audioStarted = true;
516 }
517
518 // still playing?
519 if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
520 (mState == EAS_STATE_PAUSED))
521 {
522 switch(mState) {
523 case EAS_STATE_STOPPED:
524 {
Steve Block3856b092011-10-20 11:56:00 +0100525 ALOGV("MidiFile::render - stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800526 sendEvent(MEDIA_PLAYBACK_COMPLETE);
527 break;
528 }
529 case EAS_STATE_ERROR:
530 {
Steve Block29357bc2012-01-06 19:20:56 +0000531 ALOGE("MidiFile::render - error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800532 sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
533 break;
534 }
535 case EAS_STATE_PAUSED:
Steve Block3856b092011-10-20 11:56:00 +0100536 ALOGV("MidiFile::render - paused");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800537 break;
538 default:
539 break;
540 }
541 mAudioSink->stop();
542 audioStarted = false;
543 mRender = false;
544 }
545 }
546
547threadExit:
548 mAudioSink.clear();
549 if (mAudioBuffer) {
550 delete [] mAudioBuffer;
551 mAudioBuffer = NULL;
552 }
553 mMutex.lock();
554 mTid = -1;
555 mCondition.signal();
556 mMutex.unlock();
557 return result;
558}
559
560} // end namespace android