1d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten/* 2d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * Copyright (C) 2010 The Android Open Source Project 3d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * 4d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * you may not use this file except in compliance with the License. 6d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * You may obtain a copy of the License at 7d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * 8d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * 10d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * See the License for the specific language governing permissions and 14d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * limitations under the License. 15d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten */ 16d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 17369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \file CEngine.c Engine class */ 18d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 19d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#include "sles_allinclusive.h" 20d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 21d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 221d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten/* This implementation supports at most one engine, identical for both OpenSL ES and OpenMAX AL */ 238db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 248db0b106cdce5f5216b1535492de7930ad738aedGlenn KastenCEngine *theOneTrueEngine = NULL; 258db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenpthread_mutex_t theOneTrueMutex = PTHREAD_MUTEX_INITIALIZER; 261d081e49a10543018e1ae33792bd3d30504719baGlenn Kastenunsigned theOneTrueRefCount = 0; 271d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten// incremented by slCreateEngine or xaCreateEngine, decremented by Object::Destroy on engine 288db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 298db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 308db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Called by dlopen when .so is loaded */ 318db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten__attribute__((constructor)) static void onDlOpen(void) 338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{ 348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten} 358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 368db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 378db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Called by dlclose when .so is unloaded */ 388db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 398db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten__attribute__((destructor)) static void onDlClose(void) 408db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{ 415c8bd83295b2752bb7ac34f83dfb19dcdb1be5e5Glenn Kasten // a memory barrier would be sufficient, but the mutex is easier 425c8bd83295b2752bb7ac34f83dfb19dcdb1be5e5Glenn Kasten (void) pthread_mutex_lock(&theOneTrueMutex); 431d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten if ((NULL != theOneTrueEngine) || (0 < theOneTrueRefCount)) { 448db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten SL_LOGE("Object::Destroy omitted for engine %p", theOneTrueEngine); 458db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten } 465c8bd83295b2752bb7ac34f83dfb19dcdb1be5e5Glenn Kasten (void) pthread_mutex_unlock(&theOneTrueMutex); 478db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten} 488db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 498db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 50369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief Hook called by Object::Realize when an engine is realized */ 510b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 52d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult CEngine_Realize(void *self, SLboolean async) 53d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 54bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CEngine *thiz = (CEngine *) self; 55b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten SLresult result; 56b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten#ifndef ANDROID 57a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // create the sync thread 58bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten int err = pthread_create(&thiz->mSyncThread, (const pthread_attr_t *) NULL, sync_start, thiz); 59b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten result = err_to_result(err); 60d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_RESULT_SUCCESS != result) 61d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return result; 62b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten#endif 63a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // initialize the thread pool for asynchronous operations 64bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten result = ThreadPool_init(&thiz->mThreadPool, 0, 0); 65d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_RESULT_SUCCESS != result) { 66bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; 67bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (void) pthread_join(thiz->mSyncThread, (void **) NULL); 68d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return result; 69d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 70d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#ifdef USE_SDL 71bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SDL_open(&thiz->mEngine); 72d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#endif 73d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return SL_RESULT_SUCCESS; 74d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 75d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 760b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 77928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Hook called by Object::Resume when an engine is resumed */ 78928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 79928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn KastenSLresult CEngine_Resume(void *self, SLboolean async) 80928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{ 81928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten return SL_RESULT_SUCCESS; 82928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten} 83928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 84928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 85369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief Hook called by Object::Destroy when an engine is destroyed */ 860b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 87d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenvoid CEngine_Destroy(void *self) 88d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 89bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CEngine *thiz = (CEngine *) self; 90d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten 91d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten // Verify that there are no extant objects 92bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten unsigned instanceCount = thiz->mEngine.mInstanceCount; 93bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten unsigned instanceMask = thiz->mEngine.mInstanceMask; 94d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten if ((0 < instanceCount) || (0 != instanceMask)) { 95a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects", 96bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz, instanceCount); 97d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten while (0 != instanceMask) { 98d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten unsigned i = ctz(instanceMask); 99d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten assert(MAX_INSTANCE > i); 100a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p", 101bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz, i + 1, thiz->mEngine.mInstances[i]); 102d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten instanceMask &= ~(1 << i); 103d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten } 104d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten } 105d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten 106fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten // If engine was created but not realized, there will be no sync thread yet 107fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten pthread_t zero; 108fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten memset(&zero, 0, sizeof(pthread_t)); 109bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (0 != memcmp(&zero, &thiz->mSyncThread, sizeof(pthread_t))) { 110fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten 111fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten // Announce to the sync thread that engine is shutting down; it polls so should see it soon 112bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; 113fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten // Wait for the sync thread to acknowledge the shutdown 114bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten while (!thiz->mEngine.mShutdownAck) { 115bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_cond_wait(&thiz->mObject); 116fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten } 117fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten // The sync thread should have exited by now, so collect it by joining 118bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (void) pthread_join(thiz->mSyncThread, (void **) NULL); 119fff44558a7fdbe741607b25fbd4344fe9ab94c17Glenn Kasten 120d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten } 121d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten 122d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten // Shutdown the thread pool used for asynchronous operations (there should not be any) 123bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ThreadPool_deinit(&thiz->mThreadPool); 124b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten 125faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID) 126b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten // free equalizer preset names 127bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (NULL != thiz->mEqPresetNames) { 128bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten for (unsigned i = 0; i < thiz->mEqNumPresets; ++i) { 129bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (NULL != thiz->mEqPresetNames[i]) { 130bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten delete[] thiz->mEqPresetNames[i]; 131bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mEqPresetNames[i] = NULL; 132b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten } 133b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten } 134bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten delete[] thiz->mEqPresetNames; 135bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mEqPresetNames = NULL; 136b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten } 137bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mEqNumPresets = 0; 138b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten#endif 139d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten 140d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten#ifdef USE_SDL 141d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten SDL_close(); 142d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten#endif 1434be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi 144d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 145928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 146928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 147928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Hook called by Object::Destroy before an engine is about to be destroyed */ 148928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 1491d081e49a10543018e1ae33792bd3d30504719baGlenn Kastenpredestroy_t CEngine_PreDestroy(void *self) 150928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{ 1511d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten predestroy_t ret; 1521d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten (void) pthread_mutex_lock(&theOneTrueMutex); 1531d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten assert(self == theOneTrueEngine); 1541d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten switch (theOneTrueRefCount) { 1551d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten case 0: 1561d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten assert(false); 1571d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten ret = predestroy_error; 1581d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten break; 1591d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten case 1: 1601d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten ret = predestroy_ok; 1611d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten break; 1621d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten default: 1631d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten --theOneTrueRefCount; 1641d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten ret = predestroy_again; 1651d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten break; 1661d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten } 1671d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten (void) pthread_mutex_unlock(&theOneTrueMutex); 1681d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten return ret; 169928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten} 1708db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 1718db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 1728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Called by IObject::Destroy after engine is destroyed. The parameter refers to the 1738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * previous engine, which is now undefined memory. 1748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten */ 1758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten 1768db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenvoid CEngine_Destroyed(CEngine *self) 1778db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{ 1788db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten int ok; 1798db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten ok = pthread_mutex_lock(&theOneTrueMutex); 1808db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten assert(0 == ok); 1818db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten assert(self == theOneTrueEngine); 1828db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten theOneTrueEngine = NULL; 1831d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten assert(1 == theOneTrueRefCount); 1841d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten theOneTrueRefCount = 0; 1858db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten ok = pthread_mutex_unlock(&theOneTrueMutex); 1868db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten assert(0 == ok); 1878db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten} 188