1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* sync */
18
19#include "sles_allinclusive.h"
20
21
22/** \brief Sync thread.
23 *  The sync thread runs periodically to synchronize audio state between
24 *  the application and platform-specific device driver; for best results
25 *  it should run about every graphics frame (e.g. 20 Hz to 50 Hz).
26 */
27
28void *sync_start(void *arg)
29{
30    CEngine *thiz = (CEngine *) arg;
31    for (;;) {
32
33        // FIXME should be driven by cond_signal rather than polling,
34        // or at least make the poll interval longer or configurable
35        usleep(20000*5);
36
37        object_lock_exclusive(&thiz->mObject);
38        if (thiz->mEngine.mShutdown) {
39            thiz->mEngine.mShutdownAck = SL_BOOLEAN_TRUE;
40            // broadcast not signal, because this condition is also used for other purposes
41            object_cond_broadcast(&thiz->mObject);
42            object_unlock_exclusive(&thiz->mObject);
43            break;
44        }
45        if (thiz->m3DCommit.mWaiting) {
46            thiz->m3DCommit.mWaiting = 0;
47            ++thiz->m3DCommit.mGeneration;
48            // There might be more than one thread blocked in Commit, so wake them all
49            object_cond_broadcast(&thiz->mObject);
50            // here is where we would process the enqueued 3D commands
51        }
52        // unsigned instanceMask = thiz->mEngine.mInstanceMask; // for debugger
53        unsigned changedMask = thiz->mEngine.mChangedMask;
54        thiz->mEngine.mChangedMask = 0;
55        object_unlock_exclusive(&thiz->mObject);
56
57        // now we know which objects exist, and which of those have changes
58
59        unsigned combinedMask = changedMask /* | instanceMask for debugger */;
60        while (combinedMask) {
61            unsigned i = ctz(combinedMask);
62            assert(MAX_INSTANCE > i);
63            combinedMask &= ~(1 << i);
64            IObject *instance = (IObject *) thiz->mEngine.mInstances[i];
65            // Could be NULL during construct or destroy
66            if (NULL == instance) {
67                continue;
68            }
69
70            object_lock_exclusive(instance);
71            unsigned attributesMask = instance->mAttributesMask;
72            instance->mAttributesMask = 0;
73
74            switch (IObjectToObjectID(instance)) {
75            case SL_OBJECTID_AUDIOPLAYER:
76                // do something here
77                object_unlock_exclusive(instance);
78#ifdef USE_SNDFILE
79                if (attributesMask & (ATTR_POSITION | ATTR_TRANSPORT)) {
80                    CAudioPlayer *audioPlayer = (CAudioPlayer *) instance;
81                    audioPlayerTransportUpdate(audioPlayer);
82                }
83#endif
84                break;
85
86            default:
87                object_unlock_exclusive(instance);
88                break;
89            }
90        }
91    }
92    return NULL;
93}
94