Example #1
0
bool COutputMix_PreDestroy(void *self)
{
    // Ignore destroy requests if there are any players attached to this output mix
    COutputMix *outputMix = (COutputMix *) self;
    // See design document for explanation
    if (0 == outputMix->mObject.mStrongRefCount) {
#ifdef USE_OUTPUTMIXEXT
        // We only support a single active output mix per engine, so check if this is the active mix
        IEngine *thisEngine = outputMix->mObject.mEngine;
        interface_lock_exclusive(thisEngine);
        bool thisIsTheActiveOutputMix = false;
        if (outputMix == thisEngine->mOutputMix) {
            thisIsTheActiveOutputMix = true;
        }
        interface_unlock_exclusive(thisEngine);
        if (thisIsTheActiveOutputMix) {
            // Tell the asynchronous mixer callback that we want to destroy the output mix
            outputMix->mOutputMixExt.mDestroyRequested = true;
            while (outputMix->mOutputMixExt.mDestroyRequested) {
                object_cond_wait(&outputMix->mObject);
            }
#ifdef USE_SDL
            // Mixer callback has acknowledged our request and unlinked output mix from engine.
            // Disable SDL_callback from being called periodically by SDL's internal thread.
            SDL_PauseAudio(1);
#endif
        }
#endif
        return true;
    }
    SL_LOGE("Object::Destroy(%p) for OutputMix ignored; %u players attached", outputMix,
        outputMix->mObject.mStrongRefCount);
    return false;
}
Example #2
0
void CEngine_Destroy(void *self)
{
    CEngine *thiz = (CEngine *) self;

    // Verify that there are no extant objects
    unsigned instanceCount = thiz->mEngine.mInstanceCount;
    unsigned instanceMask = thiz->mEngine.mInstanceMask;
    if ((0 < instanceCount) || (0 != instanceMask)) {
        SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects",
            thiz, instanceCount);
        while (0 != instanceMask) {
            unsigned i = ctz(instanceMask);
            assert(MAX_INSTANCE > i);
            SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p",
                thiz, i + 1, thiz->mEngine.mInstances[i]);
            instanceMask &= ~(1 << i);
        }
    }

    // If engine was created but not realized, there will be no sync thread yet
    pthread_t zero;
    memset(&zero, 0, sizeof(pthread_t));
    if (0 != memcmp(&zero, &thiz->mSyncThread, sizeof(pthread_t))) {

        // Announce to the sync thread that engine is shutting down; it polls so should see it soon
        thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE;
        // Wait for the sync thread to acknowledge the shutdown
        while (!thiz->mEngine.mShutdownAck) {
            object_cond_wait(&thiz->mObject);
        }
        // The sync thread should have exited by now, so collect it by joining
        (void) pthread_join(thiz->mSyncThread, (void **) NULL);

    }

    // Shutdown the thread pool used for asynchronous operations (there should not be any)
    ThreadPool_deinit(&thiz->mThreadPool);

#if defined(ANDROID)
    // free equalizer preset names
    if (NULL != thiz->mEqPresetNames) {
        for (unsigned i = 0; i < thiz->mEqNumPresets; ++i) {
            if (NULL != thiz->mEqPresetNames[i]) {
                delete[] thiz->mEqPresetNames[i];
                thiz->mEqPresetNames[i] = NULL;
            }
        }
        delete[] thiz->mEqPresetNames;
        thiz->mEqPresetNames = NULL;
    }
    thiz->mEqNumPresets = 0;
#endif

#ifdef USE_SDL
    SDL_close();
#endif

}