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 
sync_start(void * arg)28 void *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