blob: 0a6aa902e3d4d8f0ef7d946d7065410782435014 [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(
117 const char* path, const KeyedVector<String8, String8> *) {
Steve Block3856b092011-10-20 11:56:00 +0100118 ALOGV("MidiFile::setDataSource url=%s", path);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800119 Mutex::Autolock lock(mMutex);
120
121 // file still open?
122 if (mEasHandle) {
123 reset_nosync();
124 }
125
126 // open file and set paused state
127 mFileLocator.path = strdup(path);
128 mFileLocator.fd = -1;
129 mFileLocator.offset = 0;
130 mFileLocator.length = 0;
131 EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
132 if (result == EAS_SUCCESS) {
133 updateState();
134 }
135
136 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000137 ALOGE("EAS_OpenFile failed: [%d]", (int)result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800138 mState = EAS_STATE_ERROR;
139 return ERROR_OPEN_FAILED;
140 }
141
142 mState = EAS_STATE_OPEN;
143 mPlayTime = 0;
144 return NO_ERROR;
145}
146
147status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
148{
Steve Block3856b092011-10-20 11:56:00 +0100149 ALOGV("MidiFile::setDataSource fd=%d", fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800150 Mutex::Autolock lock(mMutex);
151
152 // file still open?
153 if (mEasHandle) {
154 reset_nosync();
155 }
156
157 // open file and set paused state
158 mFileLocator.fd = dup(fd);
159 mFileLocator.offset = offset;
160 mFileLocator.length = length;
161 EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
162 updateState();
163
164 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000165 ALOGE("EAS_OpenFile failed: [%d]", (int)result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800166 mState = EAS_STATE_ERROR;
167 return ERROR_OPEN_FAILED;
168 }
169
170 mState = EAS_STATE_OPEN;
171 mPlayTime = 0;
172 return NO_ERROR;
173}
174
175status_t MidiFile::prepare()
176{
Steve Block3856b092011-10-20 11:56:00 +0100177 ALOGV("MidiFile::prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800178 Mutex::Autolock lock(mMutex);
179 if (!mEasHandle) {
180 return ERROR_NOT_OPEN;
181 }
182 EAS_RESULT result;
183 if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000184 ALOGE("EAS_Prepare failed: [%ld]", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800185 return ERROR_EAS_FAILURE;
186 }
187 updateState();
188 return NO_ERROR;
189}
190
191status_t MidiFile::prepareAsync()
192{
Steve Block3856b092011-10-20 11:56:00 +0100193 ALOGV("MidiFile::prepareAsync");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800194 status_t ret = prepare();
195
196 // don't hold lock during callback
197 if (ret == NO_ERROR) {
198 sendEvent(MEDIA_PREPARED);
199 } else {
200 sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
201 }
202 return ret;
203}
204
205status_t MidiFile::start()
206{
Steve Block3856b092011-10-20 11:56:00 +0100207 ALOGV("MidiFile::start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800208 Mutex::Autolock lock(mMutex);
209 if (!mEasHandle) {
210 return ERROR_NOT_OPEN;
211 }
212
213 // resuming after pause?
214 if (mPaused) {
215 if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
216 return ERROR_EAS_FAILURE;
217 }
218 mPaused = false;
219 updateState();
220 }
221
222 mRender = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700223 if (mState == EAS_STATE_PLAY) {
224 sendEvent(MEDIA_STARTED);
225 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800226
227 // wake up render thread
Steve Block3856b092011-10-20 11:56:00 +0100228 ALOGV(" wakeup render thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800229 mCondition.signal();
230 return NO_ERROR;
231}
232
233status_t MidiFile::stop()
234{
Steve Block3856b092011-10-20 11:56:00 +0100235 ALOGV("MidiFile::stop");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800236 Mutex::Autolock lock(mMutex);
237 if (!mEasHandle) {
238 return ERROR_NOT_OPEN;
239 }
240 if (!mPaused && (mState != EAS_STATE_STOPPED)) {
241 EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
242 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000243 ALOGE("EAS_Pause returned error %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800244 return ERROR_EAS_FAILURE;
245 }
246 }
247 mPaused = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700248 sendEvent(MEDIA_STOPPED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800249 return NO_ERROR;
250}
251
252status_t MidiFile::seekTo(int position)
253{
Steve Block3856b092011-10-20 11:56:00 +0100254 ALOGV("MidiFile::seekTo %d", position);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800255 // hold lock during EAS calls
256 {
257 Mutex::Autolock lock(mMutex);
258 if (!mEasHandle) {
259 return ERROR_NOT_OPEN;
260 }
261 EAS_RESULT result;
262 if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
263 != EAS_SUCCESS)
264 {
Steve Block29357bc2012-01-06 19:20:56 +0000265 ALOGE("EAS_Locate returned %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800266 return ERROR_EAS_FAILURE;
267 }
268 EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
269 }
270 sendEvent(MEDIA_SEEK_COMPLETE);
271 return NO_ERROR;
272}
273
274status_t MidiFile::pause()
275{
Steve Block3856b092011-10-20 11:56:00 +0100276 ALOGV("MidiFile::pause");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800277 Mutex::Autolock lock(mMutex);
278 if (!mEasHandle) {
279 return ERROR_NOT_OPEN;
280 }
281 if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
282 if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
283 return ERROR_EAS_FAILURE;
284 }
285 mPaused = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700286 sendEvent(MEDIA_PAUSED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800287 return NO_ERROR;
288}
289
290bool MidiFile::isPlaying()
291{
Steve Block3856b092011-10-20 11:56:00 +0100292 ALOGV("MidiFile::isPlaying, mState=%d", int(mState));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800293 if (!mEasHandle || mPaused) return false;
294 return (mState == EAS_STATE_PLAY);
295}
296
297status_t MidiFile::getCurrentPosition(int* position)
298{
Steve Block3856b092011-10-20 11:56:00 +0100299 ALOGV("MidiFile::getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800300 if (!mEasHandle) {
Steve Block29357bc2012-01-06 19:20:56 +0000301 ALOGE("getCurrentPosition(): file not open");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800302 return ERROR_NOT_OPEN;
303 }
304 if (mPlayTime < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000305 ALOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800306 return ERROR_EAS_FAILURE;
307 }
308 *position = mPlayTime;
309 return NO_ERROR;
310}
311
312status_t MidiFile::getDuration(int* duration)
313{
314
Steve Block3856b092011-10-20 11:56:00 +0100315 ALOGV("MidiFile::getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800316 {
317 Mutex::Autolock lock(mMutex);
318 if (!mEasHandle) return ERROR_NOT_OPEN;
319 *duration = mDuration;
320 }
321
322 // if no duration cached, get the duration
323 // don't need a lock here because we spin up a new engine
324 if (*duration < 0) {
325 EAS_I32 temp;
326 EAS_DATA_HANDLE easData = NULL;
327 EAS_HANDLE easHandle = NULL;
328 EAS_RESULT result = EAS_Init(&easData);
329 if (result == EAS_SUCCESS) {
330 result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
331 }
332 if (result == EAS_SUCCESS) {
333 result = EAS_Prepare(easData, easHandle);
334 }
335 if (result == EAS_SUCCESS) {
336 result = EAS_ParseMetaData(easData, easHandle, &temp);
337 }
338 if (easHandle) {
339 EAS_CloseFile(easData, easHandle);
340 }
341 if (easData) {
342 EAS_Shutdown(easData);
343 }
344
345 if (result != EAS_SUCCESS) {
346 return ERROR_EAS_FAILURE;
347 }
348
349 // cache successful result
350 mDuration = *duration = int(temp);
351 }
352
353 return NO_ERROR;
354}
355
356status_t MidiFile::release()
357{
Steve Block3856b092011-10-20 11:56:00 +0100358 ALOGV("MidiFile::release");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800359 Mutex::Autolock l(mMutex);
360 reset_nosync();
361
362 // wait for render thread to exit
363 mExit = true;
364 mCondition.signal();
365
366 // wait for thread to exit
367 if (mAudioBuffer) {
368 mCondition.wait(mMutex);
369 }
370
371 // release resources
372 if (mEasData) {
373 EAS_Shutdown(mEasData);
374 mEasData = NULL;
375 }
376 return NO_ERROR;
377}
378
379status_t MidiFile::reset()
380{
Steve Block3856b092011-10-20 11:56:00 +0100381 ALOGV("MidiFile::reset");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800382 Mutex::Autolock lock(mMutex);
383 return reset_nosync();
384}
385
386// call only with mutex held
387status_t MidiFile::reset_nosync()
388{
Steve Block3856b092011-10-20 11:56:00 +0100389 ALOGV("MidiFile::reset_nosync");
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700390 sendEvent(MEDIA_STOPPED);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800391 // close file
392 if (mEasHandle) {
393 EAS_CloseFile(mEasData, mEasHandle);
394 mEasHandle = NULL;
395 }
396 if (mFileLocator.path) {
397 free((void*)mFileLocator.path);
398 mFileLocator.path = NULL;
399 }
400 if (mFileLocator.fd >= 0) {
401 close(mFileLocator.fd);
402 }
403 mFileLocator.fd = -1;
404 mFileLocator.offset = 0;
405 mFileLocator.length = 0;
406
407 mPlayTime = -1;
408 mDuration = -1;
409 mLoop = false;
410 mPaused = false;
411 mRender = false;
412 return NO_ERROR;
413}
414
415status_t MidiFile::setLooping(int loop)
416{
Steve Block3856b092011-10-20 11:56:00 +0100417 ALOGV("MidiFile::setLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800418 Mutex::Autolock lock(mMutex);
419 if (!mEasHandle) {
420 return ERROR_NOT_OPEN;
421 }
422 loop = loop ? -1 : 0;
423 if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
424 return ERROR_EAS_FAILURE;
425 }
426 return NO_ERROR;
427}
428
429status_t MidiFile::createOutputTrack() {
Jean-Michel Trivi786618f2012-03-02 14:54:07 -0800430 if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels,
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700431 CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2 /*bufferCount*/) != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000432 ALOGE("mAudioSink open failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800433 return ERROR_OPEN_FAILED;
434 }
435 return NO_ERROR;
436}
437
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800438int MidiFile::render() {
439 EAS_RESULT result = EAS_FAILURE;
440 EAS_I32 count;
441 int temp;
442 bool audioStarted = false;
443
Steve Block3856b092011-10-20 11:56:00 +0100444 ALOGV("MidiFile::render");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800445
446 // allocate render buffer
447 mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
448 if (!mAudioBuffer) {
Steve Block29357bc2012-01-06 19:20:56 +0000449 ALOGE("mAudioBuffer allocate failed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800450 goto threadExit;
451 }
452
453 // signal main thread that we started
454 {
455 Mutex::Autolock l(mMutex);
Glenn Kasten0512ab52011-05-04 17:58:57 -0700456 mTid = gettid();
Steve Block3856b092011-10-20 11:56:00 +0100457 ALOGV("render thread(%d) signal", mTid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800458 mCondition.signal();
459 }
460
461 while (1) {
462 mMutex.lock();
463
464 // nothing to render, wait for client thread to wake us up
465 while (!mRender && !mExit)
466 {
Steve Block3856b092011-10-20 11:56:00 +0100467 ALOGV("MidiFile::render - signal wait");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800468 mCondition.wait(mMutex);
Steve Block3856b092011-10-20 11:56:00 +0100469 ALOGV("MidiFile::render - signal rx'd");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800470 }
471 if (mExit) {
472 mMutex.unlock();
473 break;
474 }
475
476 // render midi data into the input buffer
Steve Block3856b092011-10-20 11:56:00 +0100477 //ALOGV("MidiFile::render - rendering audio");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800478 int num_output = 0;
479 EAS_PCM* p = mAudioBuffer;
480 for (int i = 0; i < NUM_BUFFERS; i++) {
481 result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
482 if (result != EAS_SUCCESS) {
Steve Block29357bc2012-01-06 19:20:56 +0000483 ALOGE("EAS_Render returned %ld", result);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800484 }
485 p += count * pLibConfig->numChannels;
486 num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
487 }
488
489 // update playback state and position
Steve Block3856b092011-10-20 11:56:00 +0100490 // ALOGV("MidiFile::render - updating state");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800491 EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
492 EAS_State(mEasData, mEasHandle, &mState);
493 mMutex.unlock();
494
495 // create audio output track if necessary
496 if (!mAudioSink->ready()) {
Steve Block3856b092011-10-20 11:56:00 +0100497 ALOGV("MidiFile::render - create output track");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800498 if (createOutputTrack() != NO_ERROR)
499 goto threadExit;
500 }
501
502 // Write data to the audio hardware
Steve Block3856b092011-10-20 11:56:00 +0100503 // ALOGV("MidiFile::render - writing to audio output");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800504 if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000505 ALOGE("Error in writing:%d",temp);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800506 return temp;
507 }
508
509 // start audio output if necessary
510 if (!audioStarted) {
Steve Block3856b092011-10-20 11:56:00 +0100511 //ALOGV("MidiFile::render - starting audio");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800512 mAudioSink->start();
513 audioStarted = true;
514 }
515
516 // still playing?
517 if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
518 (mState == EAS_STATE_PAUSED))
519 {
520 switch(mState) {
521 case EAS_STATE_STOPPED:
522 {
Steve Block3856b092011-10-20 11:56:00 +0100523 ALOGV("MidiFile::render - stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800524 sendEvent(MEDIA_PLAYBACK_COMPLETE);
525 break;
526 }
527 case EAS_STATE_ERROR:
528 {
Steve Block29357bc2012-01-06 19:20:56 +0000529 ALOGE("MidiFile::render - error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800530 sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
531 break;
532 }
533 case EAS_STATE_PAUSED:
Steve Block3856b092011-10-20 11:56:00 +0100534 ALOGV("MidiFile::render - paused");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800535 break;
536 default:
537 break;
538 }
539 mAudioSink->stop();
540 audioStarted = false;
541 mRender = false;
542 }
543 }
544
545threadExit:
546 mAudioSink.clear();
547 if (mAudioBuffer) {
548 delete [] mAudioBuffer;
549 mAudioBuffer = NULL;
550 }
551 mMutex.lock();
552 mTid = -1;
553 mCondition.signal();
554 mMutex.unlock();
555 return result;
556}
557
558} // end namespace android