blob: 205d44f4dd416d7a0efc8689acdb2eb33b954e8a [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
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080063 // get the library configuration and do sanity check
64 if (pLibConfig == NULL)
65 pLibConfig = EAS_Config();
66 if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
Steve Block29357bc2012-01-06 19:20:56 +000067 ALOGE("EAS library/header mismatch");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080068 goto Failed;
69 }
70
71 // initialize EAS library
72 if (EAS_Init(&mEasData) != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +000073 ALOGE("EAS_Init failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080074 goto Failed;
75 }
76
77 // select reverb preset and enable
78 EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
79 EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
80
81 // create playback thread
82 {
83 Mutex::Autolock l(mMutex);
Glenn Kasten90100b52011-06-23 17:11:35 -070084 mThread = new MidiFileThread(this);
85 mThread->run("midithread", ANDROID_PRIORITY_AUDIO);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080086 mCondition.wait(mMutex);
Steve Block3856b092011-10-20 11:56:00 +010087 ALOGV("thread started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080088 }
89
90 // indicate success
91 if (mTid > 0) {
Steve Block3856b092011-10-20 11:56:00 +010092 ALOGV(" render thread(%d) started", mTid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080093 mState = EAS_STATE_READY;
94 }
95
96Failed:
97 return;
98}
99
100status_t MidiFile::initCheck()
101{
102 if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE;
103 return NO_ERROR;
104}
105
106MidiFile::~MidiFile() {
Steve Block3856b092011-10-20 11:56:00 +0100107 ALOGV("MidiFile destructor");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800108 release();
109}
110
Andreas Huber2db84552010-01-28 11:19:57 -0800111status_t MidiFile::setDataSource(
Mark Salyzyn77342f72014-06-18 16:31:32 -0700112 const sp<IMediaHTTPService> & /*httpService*/,
Andreas Huber1b86fe02014-01-29 11:13:26 -0800113 const char* path,
114 const KeyedVector<String8, String8> *) {
Steve Block3856b092011-10-20 11:56:00 +0100115 ALOGV("MidiFile::setDataSource url=%s", path);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800116 Mutex::Autolock lock(mMutex);
117
118 // file still open?
119 if (mEasHandle) {
120 reset_nosync();
121 }
122
123 // open file and set paused state
Marco Nelissenbc11e712015-01-08 12:26:36 -0800124 mIoWrapper = new MidiIoWrapper(path);
125 EAS_RESULT result = EAS_OpenFile(mEasData, mIoWrapper->getLocator(), &mEasHandle);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800126 if (result == EAS_SUCCESS) {
127 updateState();
128 }
129
130 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000131 ALOGE("EAS_OpenFile failed: [%d]", (int)result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800132 mState = EAS_STATE_ERROR;
133 return ERROR_OPEN_FAILED;
134 }
135
136 mState = EAS_STATE_OPEN;
137 mPlayTime = 0;
138 return NO_ERROR;
139}
140
141status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
142{
Steve Block3856b092011-10-20 11:56:00 +0100143 ALOGV("MidiFile::setDataSource fd=%d", fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800144 Mutex::Autolock lock(mMutex);
145
146 // file still open?
147 if (mEasHandle) {
148 reset_nosync();
149 }
150
151 // open file and set paused state
Marco Nelissenbc11e712015-01-08 12:26:36 -0800152 mIoWrapper = new MidiIoWrapper(fd, offset, length);
153 EAS_RESULT result = EAS_OpenFile(mEasData, mIoWrapper->getLocator(), &mEasHandle);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800154 updateState();
155
156 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000157 ALOGE("EAS_OpenFile failed: [%d]", (int)result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800158 mState = EAS_STATE_ERROR;
159 return ERROR_OPEN_FAILED;
160 }
161
162 mState = EAS_STATE_OPEN;
163 mPlayTime = 0;
164 return NO_ERROR;
165}
166
167status_t MidiFile::prepare()
168{
Steve Block3856b092011-10-20 11:56:00 +0100169 ALOGV("MidiFile::prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800170 Mutex::Autolock lock(mMutex);
171 if (!mEasHandle) {
172 return ERROR_NOT_OPEN;
173 }
174 EAS_RESULT result;
175 if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000176 ALOGE("EAS_Prepare failed: [%ld]", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800177 return ERROR_EAS_FAILURE;
178 }
179 updateState();
180 return NO_ERROR;
181}
182
183status_t MidiFile::prepareAsync()
184{
Steve Block3856b092011-10-20 11:56:00 +0100185 ALOGV("MidiFile::prepareAsync");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800186 status_t ret = prepare();
187
188 // don't hold lock during callback
189 if (ret == NO_ERROR) {
190 sendEvent(MEDIA_PREPARED);
191 } else {
192 sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
193 }
194 return ret;
195}
196
197status_t MidiFile::start()
198{
Steve Block3856b092011-10-20 11:56:00 +0100199 ALOGV("MidiFile::start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800200 Mutex::Autolock lock(mMutex);
201 if (!mEasHandle) {
202 return ERROR_NOT_OPEN;
203 }
204
205 // resuming after pause?
206 if (mPaused) {
207 if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
208 return ERROR_EAS_FAILURE;
209 }
210 mPaused = false;
211 updateState();
212 }
213
214 mRender = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700215 if (mState == EAS_STATE_PLAY) {
216 sendEvent(MEDIA_STARTED);
217 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800218
219 // wake up render thread
Steve Block3856b092011-10-20 11:56:00 +0100220 ALOGV(" wakeup render thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800221 mCondition.signal();
222 return NO_ERROR;
223}
224
225status_t MidiFile::stop()
226{
Steve Block3856b092011-10-20 11:56:00 +0100227 ALOGV("MidiFile::stop");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800228 Mutex::Autolock lock(mMutex);
229 if (!mEasHandle) {
230 return ERROR_NOT_OPEN;
231 }
232 if (!mPaused && (mState != EAS_STATE_STOPPED)) {
233 EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
234 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000235 ALOGE("EAS_Pause returned error %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800236 return ERROR_EAS_FAILURE;
237 }
238 }
239 mPaused = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700240 sendEvent(MEDIA_STOPPED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800241 return NO_ERROR;
242}
243
244status_t MidiFile::seekTo(int position)
245{
Steve Block3856b092011-10-20 11:56:00 +0100246 ALOGV("MidiFile::seekTo %d", position);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800247 // hold lock during EAS calls
248 {
249 Mutex::Autolock lock(mMutex);
250 if (!mEasHandle) {
251 return ERROR_NOT_OPEN;
252 }
253 EAS_RESULT result;
254 if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
255 != EAS_SUCCESS)
256 {
Steve Block29357bc2012-01-06 19:20:56 +0000257 ALOGE("EAS_Locate returned %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800258 return ERROR_EAS_FAILURE;
259 }
260 EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
261 }
262 sendEvent(MEDIA_SEEK_COMPLETE);
263 return NO_ERROR;
264}
265
266status_t MidiFile::pause()
267{
Steve Block3856b092011-10-20 11:56:00 +0100268 ALOGV("MidiFile::pause");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800269 Mutex::Autolock lock(mMutex);
270 if (!mEasHandle) {
271 return ERROR_NOT_OPEN;
272 }
273 if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
274 if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
275 return ERROR_EAS_FAILURE;
276 }
277 mPaused = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700278 sendEvent(MEDIA_PAUSED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800279 return NO_ERROR;
280}
281
282bool MidiFile::isPlaying()
283{
Steve Block3856b092011-10-20 11:56:00 +0100284 ALOGV("MidiFile::isPlaying, mState=%d", int(mState));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800285 if (!mEasHandle || mPaused) return false;
286 return (mState == EAS_STATE_PLAY);
287}
288
289status_t MidiFile::getCurrentPosition(int* position)
290{
Steve Block3856b092011-10-20 11:56:00 +0100291 ALOGV("MidiFile::getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800292 if (!mEasHandle) {
Steve Block29357bc2012-01-06 19:20:56 +0000293 ALOGE("getCurrentPosition(): file not open");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800294 return ERROR_NOT_OPEN;
295 }
296 if (mPlayTime < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000297 ALOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800298 return ERROR_EAS_FAILURE;
299 }
300 *position = mPlayTime;
301 return NO_ERROR;
302}
303
304status_t MidiFile::getDuration(int* duration)
305{
306
Steve Block3856b092011-10-20 11:56:00 +0100307 ALOGV("MidiFile::getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800308 {
309 Mutex::Autolock lock(mMutex);
310 if (!mEasHandle) return ERROR_NOT_OPEN;
311 *duration = mDuration;
312 }
313
314 // if no duration cached, get the duration
315 // don't need a lock here because we spin up a new engine
316 if (*duration < 0) {
317 EAS_I32 temp;
318 EAS_DATA_HANDLE easData = NULL;
319 EAS_HANDLE easHandle = NULL;
320 EAS_RESULT result = EAS_Init(&easData);
321 if (result == EAS_SUCCESS) {
Marco Nelissenbc11e712015-01-08 12:26:36 -0800322 result = EAS_OpenFile(easData, mIoWrapper->getLocator(), &easHandle);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800323 }
324 if (result == EAS_SUCCESS) {
325 result = EAS_Prepare(easData, easHandle);
326 }
327 if (result == EAS_SUCCESS) {
328 result = EAS_ParseMetaData(easData, easHandle, &temp);
329 }
330 if (easHandle) {
331 EAS_CloseFile(easData, easHandle);
332 }
333 if (easData) {
334 EAS_Shutdown(easData);
335 }
336
337 if (result != EAS_SUCCESS) {
338 return ERROR_EAS_FAILURE;
339 }
340
341 // cache successful result
342 mDuration = *duration = int(temp);
343 }
344
345 return NO_ERROR;
346}
347
348status_t MidiFile::release()
349{
Steve Block3856b092011-10-20 11:56:00 +0100350 ALOGV("MidiFile::release");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800351 Mutex::Autolock l(mMutex);
352 reset_nosync();
353
354 // wait for render thread to exit
355 mExit = true;
356 mCondition.signal();
357
358 // wait for thread to exit
359 if (mAudioBuffer) {
360 mCondition.wait(mMutex);
361 }
362
363 // release resources
364 if (mEasData) {
365 EAS_Shutdown(mEasData);
366 mEasData = NULL;
367 }
368 return NO_ERROR;
369}
370
371status_t MidiFile::reset()
372{
Steve Block3856b092011-10-20 11:56:00 +0100373 ALOGV("MidiFile::reset");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800374 Mutex::Autolock lock(mMutex);
375 return reset_nosync();
376}
377
378// call only with mutex held
379status_t MidiFile::reset_nosync()
380{
Steve Block3856b092011-10-20 11:56:00 +0100381 ALOGV("MidiFile::reset_nosync");
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700382 sendEvent(MEDIA_STOPPED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800383 // close file
384 if (mEasHandle) {
385 EAS_CloseFile(mEasData, mEasHandle);
386 mEasHandle = NULL;
387 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800388
Marco Nelissenbc11e712015-01-08 12:26:36 -0800389 mIoWrapper.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800390 mPlayTime = -1;
391 mDuration = -1;
392 mLoop = false;
393 mPaused = false;
394 mRender = false;
395 return NO_ERROR;
396}
397
398status_t MidiFile::setLooping(int loop)
399{
Steve Block3856b092011-10-20 11:56:00 +0100400 ALOGV("MidiFile::setLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800401 Mutex::Autolock lock(mMutex);
402 if (!mEasHandle) {
403 return ERROR_NOT_OPEN;
404 }
405 loop = loop ? -1 : 0;
406 if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
407 return ERROR_EAS_FAILURE;
408 }
409 return NO_ERROR;
410}
411
412status_t MidiFile::createOutputTrack() {
Jean-Michel Trivi786618f2012-03-02 14:54:07 -0800413 if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels,
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700414 CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2 /*bufferCount*/) != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000415 ALOGE("mAudioSink open failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800416 return ERROR_OPEN_FAILED;
417 }
418 return NO_ERROR;
419}
420
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800421int MidiFile::render() {
422 EAS_RESULT result = EAS_FAILURE;
423 EAS_I32 count;
424 int temp;
425 bool audioStarted = false;
426
Steve Block3856b092011-10-20 11:56:00 +0100427 ALOGV("MidiFile::render");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800428
429 // allocate render buffer
430 mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
431 if (!mAudioBuffer) {
Steve Block29357bc2012-01-06 19:20:56 +0000432 ALOGE("mAudioBuffer allocate failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800433 goto threadExit;
434 }
435
436 // signal main thread that we started
437 {
438 Mutex::Autolock l(mMutex);
Glenn Kasten0512ab52011-05-04 17:58:57 -0700439 mTid = gettid();
Steve Block3856b092011-10-20 11:56:00 +0100440 ALOGV("render thread(%d) signal", mTid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800441 mCondition.signal();
442 }
443
444 while (1) {
445 mMutex.lock();
446
447 // nothing to render, wait for client thread to wake us up
448 while (!mRender && !mExit)
449 {
Steve Block3856b092011-10-20 11:56:00 +0100450 ALOGV("MidiFile::render - signal wait");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800451 mCondition.wait(mMutex);
Steve Block3856b092011-10-20 11:56:00 +0100452 ALOGV("MidiFile::render - signal rx'd");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800453 }
454 if (mExit) {
455 mMutex.unlock();
456 break;
457 }
458
459 // render midi data into the input buffer
Steve Block3856b092011-10-20 11:56:00 +0100460 //ALOGV("MidiFile::render - rendering audio");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800461 int num_output = 0;
462 EAS_PCM* p = mAudioBuffer;
463 for (int i = 0; i < NUM_BUFFERS; i++) {
464 result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
465 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000466 ALOGE("EAS_Render returned %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800467 }
468 p += count * pLibConfig->numChannels;
469 num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
470 }
471
472 // update playback state and position
Steve Block3856b092011-10-20 11:56:00 +0100473 // ALOGV("MidiFile::render - updating state");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800474 EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
475 EAS_State(mEasData, mEasHandle, &mState);
476 mMutex.unlock();
477
478 // create audio output track if necessary
479 if (!mAudioSink->ready()) {
Steve Block3856b092011-10-20 11:56:00 +0100480 ALOGV("MidiFile::render - create output track");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800481 if (createOutputTrack() != NO_ERROR)
482 goto threadExit;
483 }
484
485 // Write data to the audio hardware
Steve Block3856b092011-10-20 11:56:00 +0100486 // ALOGV("MidiFile::render - writing to audio output");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800487 if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000488 ALOGE("Error in writing:%d",temp);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800489 return temp;
490 }
491
492 // start audio output if necessary
493 if (!audioStarted) {
Steve Block3856b092011-10-20 11:56:00 +0100494 //ALOGV("MidiFile::render - starting audio");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800495 mAudioSink->start();
496 audioStarted = true;
497 }
498
499 // still playing?
500 if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
501 (mState == EAS_STATE_PAUSED))
502 {
503 switch(mState) {
504 case EAS_STATE_STOPPED:
505 {
Steve Block3856b092011-10-20 11:56:00 +0100506 ALOGV("MidiFile::render - stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800507 sendEvent(MEDIA_PLAYBACK_COMPLETE);
508 break;
509 }
510 case EAS_STATE_ERROR:
511 {
Steve Block29357bc2012-01-06 19:20:56 +0000512 ALOGE("MidiFile::render - error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800513 sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
514 break;
515 }
516 case EAS_STATE_PAUSED:
Steve Block3856b092011-10-20 11:56:00 +0100517 ALOGV("MidiFile::render - paused");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800518 break;
519 default:
520 break;
521 }
522 mAudioSink->stop();
523 audioStarted = false;
524 mRender = false;
525 }
526 }
527
528threadExit:
529 mAudioSink.clear();
530 if (mAudioBuffer) {
531 delete [] mAudioBuffer;
532 mAudioBuffer = NULL;
533 }
534 mMutex.lock();
535 mTid = -1;
536 mCondition.signal();
537 mMutex.unlock();
538 return result;
539}
540
541} // end namespace android