1437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten/* 2437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * Copyright (C) 2010 The Android Open Source Project 3437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * 4437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * you may not use this file except in compliance with the License. 6437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * You may obtain a copy of the License at 7437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * 8437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * 10437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * Unless required by applicable law or agreed to in writing, software 11437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * See the License for the specific language governing permissions and 14437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * limitations under the License. 15437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten */ 16437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 1710ee2bc6119445f4339ecef998c40c9cc95057cdGlenn Kasten/** \file CEngine.c Engine class */ 18437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 19437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten#include "sles_allinclusive.h" 20437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 21437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 22b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten/* This implementation supports at most one engine, identical for both OpenSL ES and OpenMAX AL */ 23a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 24a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn KastenCEngine *theOneTrueEngine = NULL; 25a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kastenpthread_mutex_t theOneTrueMutex = PTHREAD_MUTEX_INITIALIZER; 26b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kastenunsigned theOneTrueRefCount = 0; 27b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten// incremented by slCreateEngine or xaCreateEngine, decremented by Object::Destroy on engine 28a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 29a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 30a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten/** \brief Called by dlopen when .so is loaded */ 31a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 32a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten__attribute__((constructor)) static void onDlOpen(void) 33a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten{ 34a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten} 35a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 36a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 37a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten/** \brief Called by dlclose when .so is unloaded */ 38a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 39a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten__attribute__((destructor)) static void onDlClose(void) 40a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten{ 4199fe0d68ddc198a532cb1fa71bea2c809fa94c59Glenn Kasten // a memory barrier would be sufficient, but the mutex is easier 4299fe0d68ddc198a532cb1fa71bea2c809fa94c59Glenn Kasten (void) pthread_mutex_lock(&theOneTrueMutex); 43b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten if ((NULL != theOneTrueEngine) || (0 < theOneTrueRefCount)) { 44a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten SL_LOGE("Object::Destroy omitted for engine %p", theOneTrueEngine); 45a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten } 4699fe0d68ddc198a532cb1fa71bea2c809fa94c59Glenn Kasten (void) pthread_mutex_unlock(&theOneTrueMutex); 47a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten} 48a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 49a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 5010ee2bc6119445f4339ecef998c40c9cc95057cdGlenn Kasten/** \brief Hook called by Object::Realize when an engine is realized */ 51158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten 52437f9ab9914ea61112aa496a047162a0d22194cdGlenn KastenSLresult CEngine_Realize(void *self, SLboolean async) 53437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten{ 5450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten CEngine *thiz = (CEngine *) self; 55227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten SLresult result; 56227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten#ifndef ANDROID 5751cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten // create the sync thread 5850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten int err = pthread_create(&thiz->mSyncThread, (const pthread_attr_t *) NULL, sync_start, thiz); 59227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten result = err_to_result(err); 60437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten if (SL_RESULT_SUCCESS != result) 61437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten return result; 62227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten#endif 6351cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten // initialize the thread pool for asynchronous operations 6450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten result = ThreadPool_init(&thiz->mThreadPool, 0, 0); 65437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten if (SL_RESULT_SUCCESS != result) { 6650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; 6750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten (void) pthread_join(thiz->mSyncThread, (void **) NULL); 68437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten return result; 69437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten } 70437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten#ifdef USE_SDL 7150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten SDL_open(&thiz->mEngine); 72437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten#endif 73437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten return SL_RESULT_SUCCESS; 74437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten} 75437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 76158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten 774f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Hook called by Object::Resume when an engine is resumed */ 784f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 794f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn KastenSLresult CEngine_Resume(void *self, SLboolean async) 804f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten{ 814f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten return SL_RESULT_SUCCESS; 824f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten} 834f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 844f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 8510ee2bc6119445f4339ecef998c40c9cc95057cdGlenn Kasten/** \brief Hook called by Object::Destroy when an engine is destroyed */ 86158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten 87437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kastenvoid CEngine_Destroy(void *self) 88437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten{ 8950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten CEngine *thiz = (CEngine *) self; 90b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 91b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten // Verify that there are no extant objects 9250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten unsigned instanceCount = thiz->mEngine.mInstanceCount; 9350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten unsigned instanceMask = thiz->mEngine.mInstanceMask; 94b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten if ((0 < instanceCount) || (0 != instanceMask)) { 9551cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects", 9650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz, instanceCount); 97b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten while (0 != instanceMask) { 98b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten unsigned i = ctz(instanceMask); 99b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten assert(MAX_INSTANCE > i); 10051cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p", 10150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz, i + 1, thiz->mEngine.mInstances[i]); 102b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten instanceMask &= ~(1 << i); 103b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten } 104b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten } 105b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 106cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // If engine was created but not realized, there will be no sync thread yet 107cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten pthread_t zero; 108cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten memset(&zero, 0, sizeof(pthread_t)); 10950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten if (0 != memcmp(&zero, &thiz->mSyncThread, sizeof(pthread_t))) { 110cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten 111cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // Announce to the sync thread that engine is shutting down; it polls so should see it soon 11250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; 113cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // Wait for the sync thread to acknowledge the shutdown 11450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten while (!thiz->mEngine.mShutdownAck) { 11550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten object_cond_wait(&thiz->mObject); 116cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten } 117cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // The sync thread should have exited by now, so collect it by joining 11850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten (void) pthread_join(thiz->mSyncThread, (void **) NULL); 119cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten 120b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten } 121b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 122b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten // Shutdown the thread pool used for asynchronous operations (there should not be any) 12350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten ThreadPool_deinit(&thiz->mThreadPool); 1243be625f40588941aa23e35fed5cb693ddc9718daGlenn Kasten 1250b718abd78bd3e4022008fe0492fb76b265d26d1Glenn Kasten#if defined(ANDROID) 1263be625f40588941aa23e35fed5cb693ddc9718daGlenn Kasten // free equalizer preset names 12750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten if (NULL != thiz->mEqPresetNames) { 12850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten for (unsigned i = 0; i < thiz->mEqNumPresets; ++i) { 12950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten if (NULL != thiz->mEqPresetNames[i]) { 13050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten delete[] thiz->mEqPresetNames[i]; 13150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz->mEqPresetNames[i] = NULL; 1323be625f40588941aa23e35fed5cb693ddc9718daGlenn Kasten } 1333be625f40588941aa23e35fed5cb693ddc9718daGlenn Kasten } 13450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten delete[] thiz->mEqPresetNames; 13550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz->mEqPresetNames = NULL; 1363be625f40588941aa23e35fed5cb693ddc9718daGlenn Kasten } 13750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten thiz->mEqNumPresets = 0; 1383be625f40588941aa23e35fed5cb693ddc9718daGlenn Kasten#endif 139b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 140b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten#ifdef USE_SDL 141b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten SDL_close(); 142b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten#endif 1431f5702ed2239c79b701aa8cc3c675798b34a9656Jean-Michel Trivi 144437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten} 1454f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 1464f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 1474f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Hook called by Object::Destroy before an engine is about to be destroyed */ 1484f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 149b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kastenpredestroy_t CEngine_PreDestroy(void *self) 1504f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten{ 151b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten predestroy_t ret; 152b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten (void) pthread_mutex_lock(&theOneTrueMutex); 153b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten assert(self == theOneTrueEngine); 154b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten switch (theOneTrueRefCount) { 155b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten case 0: 156b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten assert(false); 157b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten ret = predestroy_error; 158b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten break; 159b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten case 1: 160b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten ret = predestroy_ok; 161b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten break; 162b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten default: 163b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten --theOneTrueRefCount; 164b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten ret = predestroy_again; 165b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten break; 166b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten } 167b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten (void) pthread_mutex_unlock(&theOneTrueMutex); 168b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten return ret; 1694f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten} 170a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 171a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 172a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten/** \brief Called by IObject::Destroy after engine is destroyed. The parameter refers to the 173a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten * previous engine, which is now undefined memory. 174a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten */ 175a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten 176a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kastenvoid CEngine_Destroyed(CEngine *self) 177a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten{ 178a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten int ok; 179a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten ok = pthread_mutex_lock(&theOneTrueMutex); 180a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten assert(0 == ok); 181a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten assert(self == theOneTrueEngine); 182a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten theOneTrueEngine = NULL; 183b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten assert(1 == theOneTrueRefCount); 184b11def0293629d4d44ddbcd8a27c63504fd80ce1Glenn Kasten theOneTrueRefCount = 0; 185a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten ok = pthread_mutex_unlock(&theOneTrueMutex); 186a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten assert(0 == ok); 187a930d729ff2249eaa0b45a5e61c70bebad45f698Glenn Kasten} 188