| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* sync */ |
| |
| #include "sles_allinclusive.h" |
| |
| |
| /** \brief Sync thread. |
| * The sync thread runs periodically to synchronize audio state between |
| * the application and platform-specific device driver; for best results |
| * it should run about every graphics frame (e.g. 20 Hz to 50 Hz). |
| */ |
| |
| void *sync_start(void *arg) |
| { |
| CEngine *thiz = (CEngine *) arg; |
| for (;;) { |
| |
| // FIXME should be driven by cond_signal rather than polling, |
| // or at least make the poll interval longer or configurable |
| usleep(20000*5); |
| |
| object_lock_exclusive(&thiz->mObject); |
| if (thiz->mEngine.mShutdown) { |
| thiz->mEngine.mShutdownAck = SL_BOOLEAN_TRUE; |
| // broadcast not signal, because this condition is also used for other purposes |
| object_cond_broadcast(&thiz->mObject); |
| object_unlock_exclusive(&thiz->mObject); |
| break; |
| } |
| if (thiz->m3DCommit.mWaiting) { |
| thiz->m3DCommit.mWaiting = 0; |
| ++thiz->m3DCommit.mGeneration; |
| // There might be more than one thread blocked in Commit, so wake them all |
| object_cond_broadcast(&thiz->mObject); |
| // here is where we would process the enqueued 3D commands |
| } |
| // unsigned instanceMask = thiz->mEngine.mInstanceMask; // for debugger |
| unsigned changedMask = thiz->mEngine.mChangedMask; |
| thiz->mEngine.mChangedMask = 0; |
| object_unlock_exclusive(&thiz->mObject); |
| |
| // now we know which objects exist, and which of those have changes |
| |
| unsigned combinedMask = changedMask /* | instanceMask for debugger */; |
| while (combinedMask) { |
| unsigned i = ctz(combinedMask); |
| assert(MAX_INSTANCE > i); |
| combinedMask &= ~(1 << i); |
| IObject *instance = (IObject *) thiz->mEngine.mInstances[i]; |
| // Could be NULL during construct or destroy |
| if (NULL == instance) { |
| continue; |
| } |
| |
| object_lock_exclusive(instance); |
| unsigned attributesMask = instance->mAttributesMask; |
| instance->mAttributesMask = 0; |
| |
| switch (IObjectToObjectID(instance)) { |
| case SL_OBJECTID_AUDIOPLAYER: |
| // do something here |
| object_unlock_exclusive(instance); |
| #ifdef USE_SNDFILE |
| if (attributesMask & (ATTR_POSITION | ATTR_TRANSPORT)) { |
| CAudioPlayer *audioPlayer = (CAudioPlayer *) instance; |
| audioPlayerTransportUpdate(audioPlayer); |
| } |
| #endif |
| break; |
| |
| default: |
| object_unlock_exclusive(instance); |
| break; |
| } |
| } |
| } |
| return NULL; |
| } |