17e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi/*
27e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
37e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi *
47e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
57e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * you may not use this file except in compliance with the License.
67e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * You may obtain a copy of the License at
77e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi *
87e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
97e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi *
107e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
117e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
127e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * See the License for the specific language governing permissions and
147e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi * limitations under the License.
157e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi */
167e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
177e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi/* \file COutputMix.c OutputMix class */
187e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
197e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi#include "sles_allinclusive.h"
207e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
217e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
227e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi/** \brief Hook called by Object::Realize when an output mix is realized */
237e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
247e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel TriviSLresult COutputMix_Realize(void *self, SLboolean async)
257e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi{
267e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi    SLresult result = SL_RESULT_SUCCESS;
277e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
287e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi#ifdef ANDROID
29bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    COutputMix *thiz = (COutputMix *) self;
30bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    result = android_outputMix_realize(thiz, async);
317e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi#endif
327e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
337e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi    return result;
347e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi}
357e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
367e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
377e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi/** \brief Hook called by Object::Resume when an output mix is resumed */
38928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
397e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel TriviSLresult COutputMix_Resume(void *self, SLboolean async)
407e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi{
41928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    return SL_RESULT_SUCCESS;
427e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi}
437e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
447e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
457e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi/** \brief Hook called by Object::Destroy when an output mix is destroyed */
467e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
477e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivivoid COutputMix_Destroy(void *self)
487e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi{
497e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi#ifdef ANDROID
50bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    COutputMix *thiz = (COutputMix *) self;
51bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    android_outputMix_destroy(thiz);
527e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi#endif
537e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi}
54928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
55928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
56928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Hook called by Object::Destroy before an output mix is about to be destroyed */
57928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
581d081e49a10543018e1ae33792bd3d30504719baGlenn Kastenpredestroy_t COutputMix_PreDestroy(void *self)
59928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
60f51dba65751107c930759938775b75531ec1f330Glenn Kasten    // Ignore destroy requests if there are any players attached to this output mix
61f51dba65751107c930759938775b75531ec1f330Glenn Kasten    COutputMix *outputMix = (COutputMix *) self;
62f51dba65751107c930759938775b75531ec1f330Glenn Kasten    // See design document for explanation
63f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (0 == outputMix->mObject.mStrongRefCount) {
64a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifdef USE_OUTPUTMIXEXT
65b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        // We only support a single active output mix per engine, so check if this is the active mix
66b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten        IEngine *thisEngine = &outputMix->mObject.mEngine->mEngine;
67b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        interface_lock_exclusive(thisEngine);
68b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        bool thisIsTheActiveOutputMix = false;
69b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        if (outputMix == thisEngine->mOutputMix) {
70b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            thisIsTheActiveOutputMix = true;
71f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
72b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        interface_unlock_exclusive(thisEngine);
73b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        if (thisIsTheActiveOutputMix) {
74b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            // Tell the asynchronous mixer callback that we want to destroy the output mix
75b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            outputMix->mOutputMixExt.mDestroyRequested = true;
76b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            while (outputMix->mOutputMixExt.mDestroyRequested) {
77b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten                object_cond_wait(&outputMix->mObject);
78b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            }
79a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifdef USE_SDL
80b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            // Mixer callback has acknowledged our request and unlinked output mix from engine.
81b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            // Disable SDL_callback from being called periodically by SDL's internal thread.
82b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            SDL_PauseAudio(1);
83b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten#endif
84b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        }
85f51dba65751107c930759938775b75531ec1f330Glenn Kasten#endif
861d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        return predestroy_ok;
87f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
88f51dba65751107c930759938775b75531ec1f330Glenn Kasten    SL_LOGE("Object::Destroy(%p) for OutputMix ignored; %u players attached", outputMix,
89f51dba65751107c930759938775b75531ec1f330Glenn Kasten        outputMix->mObject.mStrongRefCount);
901d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten    return predestroy_error;
91928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
92