sles.c revision 72a04d8e9e059dad969d166a6a70491fe1e65970
1773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi/*
2773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
3773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
4773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * you may not use this file except in compliance with the License.
6773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * You may obtain a copy of the License at
7773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
8773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
10773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * See the License for the specific language governing permissions and
14773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * limitations under the License.
15773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi */
16d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
17d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* OpenSL ES prototype */
18d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
19773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi#include "sles_allinclusive.h"
20c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi#include "sles_check_audioplayer_ext.h"
21bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
22d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten#ifdef USE_ANDROID
23773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi#include "sles_to_android_ext.h"
242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#endif
25d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
26d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* Forward declarations */
27d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
28bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenextern const struct SLInterfaceID_ SL_IID_array[MPH_MAX];
29bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
30bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef __cplusplus
31bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#define this this_
32bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
33d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
34d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* Private types */
35d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* Device table (change this when you port!) */
372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kastenstatic const SLAudioInputDescriptor AudioInputDescriptor_mic = {
397754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    (SLchar *) "mic",            // deviceName
407754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_DEVCONNECTION_INTEGRATED, // deviceConnection
417754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_DEVSCOPE_ENVIRONMENT,     // deviceScope
427754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_DEVLOCATION_HANDSET,      // deviceLocation
437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_BOOLEAN_TRUE,             // isForTelephony
447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_SAMPLINGRATE_44_1,        // minSampleRate
457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_SAMPLINGRATE_44_1,        // maxSampleRate
467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_BOOLEAN_TRUE,             // isFreqRangeContinuous
477754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    NULL,                        // samplingRatesSupported
487754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    0,                           // numOfSamplingRatesSupported
497754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    1                            // maxChannels
507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten};
517754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten
527754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kastenstatic const struct AudioInput_id_descriptor {
537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 id;
547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    const SLAudioInputDescriptor *descriptor;
557754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten} AudioInput_id_descriptors[] = {
567754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    {SL_DEFAULTDEVICEID_AUDIOINPUT, &AudioInputDescriptor_mic}
577754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten};
587754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten
597754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kastenstatic const SLAudioOutputDescriptor AudioOutputDescriptor_speaker = {
607754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    (SLchar *) "speaker",        // deviceName
617754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_DEVCONNECTION_INTEGRATED, // deviceConnection
627754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_DEVSCOPE_USER,            // deviceScope
637754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_DEVLOCATION_HEADSET,      // deviceLocation
647754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_BOOLEAN_TRUE,             // isForTelephony
657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_SAMPLINGRATE_44_1,        // minSamplingRate
667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_SAMPLINGRATE_44_1,        // maxSamplingRate
677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SL_BOOLEAN_TRUE,             // isFreqRangeContinuous
687754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    NULL,                        // samplingRatesSupported
697754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    0,                           // numOfSamplingRatesSupported
707754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    2                            // maxChannels
717754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten};
727754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten
732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#define DEVICE_ID_HEADSET 1
742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic const SLAudioOutputDescriptor AudioOutputDescriptor_headset = {
762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    (SLchar *) "headset",
772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_DEVCONNECTION_ATTACHED_WIRED,
782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_DEVSCOPE_USER,
792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_DEVLOCATION_HEADSET,
802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_BOOLEAN_FALSE,
812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_44_1,
822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_44_1,
832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_BOOLEAN_TRUE,
842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    NULL,
852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    0,
862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    2
872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#define DEVICE_ID_HANDSFREE 2
902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic const SLAudioOutputDescriptor AudioOutputDescriptor_handsfree = {
922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    (SLchar *) "handsfree",
932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_DEVCONNECTION_INTEGRATED,
942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_DEVSCOPE_ENVIRONMENT,
952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_DEVLOCATION_HANDSET,
962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_BOOLEAN_FALSE,
972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_44_1,
982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_44_1,
992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_BOOLEAN_TRUE,
1002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    NULL,
1012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    0,
1022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    2
1032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
1042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
1057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kastenstatic const struct AudioOutput_id_descriptor {
1067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 id;
1077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    const SLAudioOutputDescriptor *descriptor;
1087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten} AudioOutput_id_descriptors[] = {
1097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    {SL_DEFAULTDEVICEID_AUDIOOUTPUT, &AudioOutputDescriptor_speaker},
1107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    {DEVICE_ID_HEADSET, &AudioOutputDescriptor_headset},
1117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    {DEVICE_ID_HANDSFREE, &AudioOutputDescriptor_handsfree}
1127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten};
1137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten
11429b9008a17cae003590a5ff361e98809f02e3025Glenn Kastenstatic const SLLEDDescriptor SLLEDDescriptor_default = {
11583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    32, // ledCount
11683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    0,  // primaryLED
11783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    ~0  // colorMask
11829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten};
11929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
12083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kastenstatic const struct LED_id_descriptor {
12183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLuint32 id;
12283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    const SLLEDDescriptor *descriptor;
12383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten} LED_id_descriptors[] = {
12483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    {SL_DEFAULTDEVICEID_LED, &SLLEDDescriptor_default}
12583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten};
12683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten
12783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kastenstatic const SLVibraDescriptor SLVibraDescriptor_default = {
12883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SL_BOOLEAN_TRUE, // supportsFrequency
12983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SL_BOOLEAN_TRUE, // supportsIntensity
13083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    20000,           // minFrequency
13183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    100000           // maxFrequency
13283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten};
13383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten
13483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kastenstatic const struct Vibra_id_descriptor {
13583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLuint32 id;
13683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    const SLVibraDescriptor *descriptor;
13783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten} Vibra_id_descriptors[] = {
13883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    {SL_DEFAULTDEVICEID_VIBRA, &SLVibraDescriptor_default}
13983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten};
14029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
141bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
142bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Private functions */
143bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
14472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic void object_lock_exclusive(IObject *this)
14529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten{
14629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    int ok;
14729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    ok = pthread_mutex_lock(&this->mMutex);
14829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    assert(0 == ok);
14929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten}
15029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
15172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic void object_unlock_exclusive(IObject *this)
15229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten{
15329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    int ok;
15429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
15529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    assert(0 == ok);
15629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten}
15729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
15872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic void object_cond_wait(IObject *this)
159e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten{
160e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    int ok;
161e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    ok = pthread_cond_wait(&this->mCond, &this->mMutex);
162e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    assert(0 == ok);
163e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten}
164e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten
16572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic void object_cond_signal(IObject *this)
166e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten{
167e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    int ok;
168e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    ok = pthread_cond_signal(&this->mCond);
169e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    assert(0 == ok);
170e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten}
171e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten
17229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Currently shared locks are implemented as exclusive, but don't count on it
17329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
17429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define object_lock_shared(this)   object_lock_exclusive(this)
17529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define object_unlock_shared(this) object_unlock_exclusive(this)
17629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
17729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Currently interface locks are actually on whole object, but don't count on it
17829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
17929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_lock_exclusive(this)   object_lock_exclusive((this)->mThis)
18029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_unlock_exclusive(this) object_unlock_exclusive((this)->mThis)
18129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_lock_shared(this)      object_lock_shared((this)->mThis)
18229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_unlock_shared(this)    object_unlock_shared((this)->mThis)
183e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define interface_cond_wait(this)        object_cond_wait((this)->mThis)
184e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define interface_cond_signal(this)      object_cond_signal((this)->mThis)
18529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
18629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Peek and poke are an optimization for small atomic fields that don't "matter"
18729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
18829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_lock_poke(this)   /* interface_lock_exclusive(this) */
18929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_unlock_poke(this) /* interface_unlock_exclusive(this) */
19029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_lock_peek(this)   /* interface_lock_shared(this) */
19129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#define interface_unlock_peek(this) /* interface_unlock_shared(this) */
19229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
193bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Map SLInterfaceID to its minimal perfect hash (MPH), or -1 if unknown
194bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
195bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic int IID_to_MPH(const SLInterfaceID iid)
196d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
197bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (&SL_IID_array[0] <= iid && &SL_IID_array[MPH_MAX] > iid)
198bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return iid - &SL_IID_array[0];
199bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != iid) {
200bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        // FIXME Replace this linear search by a good MPH algorithm
201bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct SLInterfaceID_ *srch = &SL_IID_array[0];
202bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        unsigned MPH;
203bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        for (MPH = 0; MPH < MPH_MAX; ++MPH, ++srch)
204bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (!memcmp(iid, srch, sizeof(struct SLInterfaceID_)))
205bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return MPH;
206bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
207bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return -1;
208bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
209bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
21029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Check the interface IDs passed into a Create operation
21129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
21272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic SLresult checkInterfaces(const ClassTable *class__,
213bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
214bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const SLboolean *pInterfaceRequired, unsigned *pExposedMask)
215bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
216bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    assert(NULL != class__ && NULL != pExposedMask);
217bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask = 0;
218bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *interfaces = class__->mInterfaces;
219bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 interfaceCount = class__->mInterfaceCount;
220bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 i;
221bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME This section could be pre-computed per class
222bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < interfaceCount; ++i) {
223bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        switch (interfaces[i].mInterface) {
224bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        case INTERFACE_IMPLICIT:
225bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            exposedMask |= 1 << i;
226bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
227bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        default:
228bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
229bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
230bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
231d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (0 < numInterfaces) {
232d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        if (NULL == pInterfaceIds || NULL == pInterfaceRequired)
233d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
234d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        for (i = 0; i < numInterfaces; ++i) {
235bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLInterfaceID iid = pInterfaceIds[i];
236bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (NULL == iid)
237bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
23829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
23929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) ||
24029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                (0 > (index = class__->mMPH_to_index[MPH]))) {
241bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                if (pInterfaceRequired[i])
242bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    return SL_RESULT_FEATURE_UNSUPPORTED;
243bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                continue;
244bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
24529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // FIXME this seems a bit strong? what is correct logic?
24629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // we are requesting a duplicate explicit interface,
24729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // or we are requesting one which is already implicit ?
24829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // if (exposedMask & (1 << index))
24929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            //    return SL_RESULT_PARAMETER_INVALID;
25029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            exposedMask |= (1 << index);
251d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
252d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
253bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pExposedMask = exposedMask;
254d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
255d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
256d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
257bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Interface initialization hooks */
258d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
259d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SL3DCommitItf_ _3DCommit_3DCommitItf;
260d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
261bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void _3DCommit_init(void *self)
262bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
26372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DCommit *this = (I3DCommit *) self;
264bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &_3DCommit_3DCommitItf;
265bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
266bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mDeferred = SL_BOOLEAN_FALSE;
26732918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    this->mGeneration = 0;
268bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
269bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
270d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
271ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SL3DDopplerItf_ _3DDoppler_3DDopplerItf;
272ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
273bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void _3DDoppler_init(void *self)
274bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
27572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DDoppler *this = (I3DDoppler *) self;
276ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &_3DDoppler_3DDopplerItf;
277ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
2787754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityCartesian.x = 0;
2797754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityCartesian.y = 0;
2807754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityCartesian.z = 0;
2817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    memset(&this->mVelocitySpherical, 0x55, sizeof(this->mVelocitySpherical));
282ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
283ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDopplerFactor = 1000;
2847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
285bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
286d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
287ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SL3DGroupingItf_ _3DGrouping_3DGroupingItf;
288ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
289bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void _3DGrouping_init(void *self)
290bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
29172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DGrouping *this = (I3DGrouping *) self;
292ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &_3DGrouping_3DGroupingItf;
293ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
294ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mGroup = NULL;
295ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
2967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // FIXME initialize the bag here
297bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
298d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
299ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SL3DLocationItf_ _3DLocation_3DLocationItf;
300ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
301bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void _3DLocation_init(void *self)
302bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
30372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
304ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &_3DLocation_3DLocationItf;
305ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
3067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationCartesian.x = 0;
3077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationCartesian.y = 0;
3087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationCartesian.z = 0;
3097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    memset(&this->mLocationSpherical, 0x55, sizeof(this->mLocationSpherical));
3107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mHeading = 0;
3117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mPitch = 0;
3127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mRoll = 0;
3137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mFront.x = 0;
3147754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mFront.y = 0;
3157754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mAbove.x = 0;
3167754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mAbove.y = 0;
3177754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mUp.x = 0;
3187754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mUp.z = 0;
3197754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mTheta = 0x55555555;
3207754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis.x = 0x55555555;
3217754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis.y = 0x55555555;
3227754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis.z = 0x55555555;
3237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_FALSE;
324ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
3257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mFront.z = -1000;
3267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mUp.y = 1000;
3277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mAbove.z = -1000;
3287754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
3297754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
330bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
331d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
332ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SL3DMacroscopicItf_ _3DMacroscopic_3DMacroscopicItf;
333ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
334bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void _3DMacroscopic_init(void *self)
335bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
33672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
337ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &_3DMacroscopic_3DMacroscopicItf;
338ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
339ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mSize.mWidth = 0;
340ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mSize.mHeight = 0;
341ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mSize.mDepth = 0;
3427754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mHeading = 0;
3437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mPitch = 0;
3447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mRoll = 0;
345ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mFront.x = 0;
346ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mFront.y = 0;
347ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mUp.x = 0;
348ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mUp.z = 0;
3497754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // this->mGeneration = 0;
3507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mTheta = 0x55555555;
3517754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis.x = 0x55555555;
3527754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis.y = 0x55555555;
3537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis.z = 0x55555555;
3547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_FALSE;
355ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
356ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mFront.z = -1000;
357ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mUp.y = 1000;
3587754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
359bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
360d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
361ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SL3DSourceItf_ _3DSource_3DSourceItf;
362ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
363bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void _3DSource_init(void *self)
364bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
36572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
366ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &_3DSource_3DSourceItf;
3677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten#ifndef NDEBUG
368ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mHeadRelative = SL_BOOLEAN_FALSE;
369ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRolloffMaxDistanceMute = SL_BOOLEAN_FALSE;
3707754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mConeOuterLevel = 0;
3717754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRoomRolloffFactor = 0;
3727754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten#endif
373ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMaxDistance = SL_MILLIMETER_MAX;
374ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMinDistance = 1000;
3757754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mConeInnerAngle = 360000;
3767754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mConeOuterAngle = 360000;
377ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRolloffFactor = 1000;
378ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDistanceModel = SL_ROLLOFFMODEL_EXPONENTIAL;
379bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
380d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
381d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLAudioDecoderCapabilitiesItf_
382d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten    AudioDecoderCapabilities_AudioDecoderCapabilitiesItf;
383d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
384bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void AudioDecoderCapabilities_init(void *self)
385bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
38672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioDecoderCapabilities *this =
38772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioDecoderCapabilities *) self;
388bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &AudioDecoderCapabilities_AudioDecoderCapabilitiesItf;
389bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
3902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
391ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLAudioEncoderItf_ AudioEncoder_AudioEncoderItf;
392ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
393ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic void AudioEncoder_init(void *self)
394ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
39572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioEncoder *this = (IAudioEncoder *) self;
396ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &AudioEncoder_AudioEncoderItf;
397ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
398ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    memset(&this->mSettings, 0, sizeof(SLAudioEncoderSettings));
399ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
400ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
401ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
402d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLAudioEncoderCapabilitiesItf_
403d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten    AudioEncoderCapabilities_AudioEncoderCapabilitiesItf;
404d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
405bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void AudioEncoderCapabilities_init(void *self)
406bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
40772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioEncoderCapabilities *this =
40872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioEncoderCapabilities *) self;
409bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &AudioEncoderCapabilities_AudioEncoderCapabilitiesItf;
410bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
412d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLAudioIODeviceCapabilitiesItf_
413d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten    AudioIODeviceCapabilities_AudioIODeviceCapabilitiesItf;
414d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
415bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void AudioIODeviceCapabilities_init(void *self)
416bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
41772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioIODeviceCapabilities *this =
41872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioIODeviceCapabilities *) self;
419bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &AudioIODeviceCapabilities_AudioIODeviceCapabilitiesItf;
4207754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten#ifndef NDEBUG
4217754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioInputsChangedCallback = NULL;
4227754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioInputsChangedContext = NULL;
4237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioOutputsChangedCallback = NULL;
4247754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioOutputsChangedContext = NULL;
4257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mDefaultDeviceIDMapChangedCallback = NULL;
4267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mDefaultDeviceIDMapChangedContext = NULL;
4277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten#endif
428bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
430ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLBassBoostItf_ BassBoost_BassBoostItf;
431ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
432bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void BassBoost_init(void *self)
433bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
43472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBassBoost *this = (IBassBoost *) self;
435ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &BassBoost_BassBoostItf;
436ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
437ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnabled = SL_BOOLEAN_FALSE;
438ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
439ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mStrength = 1000;
440bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
442d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLBufferQueueItf_ BufferQueue_BufferQueueItf;
443d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
444bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void BufferQueue_init(void *self)
445bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
44672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
447bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &BufferQueue_BufferQueueItf;
448bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
449bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mState.count = 0;
450bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mState.playIndex = 0;
451bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = NULL;
452bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = NULL;
453bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mNumBuffers = 0;
454bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mArray = NULL;
455bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mFront = NULL;
456bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mRear = NULL;
457ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    struct BufferHeader *bufferHeader = this->mTypical;
458ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    unsigned i;
459ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    for (i = 0; i < BUFFER_HEADER_TYPICAL+1; ++i, ++bufferHeader) {
460ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        bufferHeader->mBuffer = NULL;
461ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        bufferHeader->mSize = 0;
462ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    }
463bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
464bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
466d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLDeviceVolumeItf_ DeviceVolume_DeviceVolumeItf;
467d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
468bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void DeviceVolume_init(void *self)
469bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
47072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDeviceVolume *this =
47172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDeviceVolume *) self;
472bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &DeviceVolume_DeviceVolumeItf;
473ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mVolume[0] = 10;
474ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mVolume[1] = 10;
475bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
476d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
477d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLDynamicInterfaceManagementItf_
478d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten    DynamicInterfaceManagement_DynamicInterfaceManagementItf;
479d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
480bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void DynamicInterfaceManagement_init(void *self)
481d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
48272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicInterfaceManagement *this =
48372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDynamicInterfaceManagement *) self;
484bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf =
485bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        &DynamicInterfaceManagement_DynamicInterfaceManagementItf;
486bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
487bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mAddedMask = 0;
488bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = NULL;
489bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = NULL;
490bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
491d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
492d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
493ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLDynamicSourceItf_ DynamicSource_DynamicSourceItf;
494ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
495bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void DynamicSource_init(void *self)
496d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
49772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicSource *this = (IDynamicSource *) self;
498ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &DynamicSource_DynamicSourceItf;
499ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // mDataSource will be initialized later in CreateAudioPlayer etc.
500d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
501d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
502ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLEffectSendItf_ EffectSend_EffectSendItf;
503ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
504bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void EffectSend_init(void *self)
505d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
50672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
507ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &EffectSend_EffectSendItf;
508ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
509ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOutputMix = NULL; // FIXME wrong
510ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDirectLevel = 0;
511ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnableLevels[AUX_ENVIRONMENTALREVERB].mEnable = SL_BOOLEAN_FALSE;
512ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnableLevels[AUX_ENVIRONMENTALREVERB].mSendLevel = 0;
513ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnableLevels[AUX_PRESETREVERB].mEnable = SL_BOOLEAN_FALSE;
514ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnableLevels[AUX_PRESETREVERB].mSendLevel = 0;
515ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
516d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
517d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
518d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLEngineItf_ Engine_EngineItf;
519d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
520bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Engine_init(void *self)
521d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
52272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEngine *this = (IEngine *) self;
523bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Engine_EngineItf;
524ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // mLossOfControlGlobal is initialized in CreateEngine
52572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten#ifndef NDEBUG
52672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this->mInstanceCount = 0;
52772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    unsigned i;
52872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    for (i = 0; i < INSTANCE_MAX; ++i)
52972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mInstances[i] = NULL;
53072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten#endif
531d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
532d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
533d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLEngineCapabilitiesItf_
534d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten    EngineCapabilities_EngineCapabilitiesItf;
535d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
536bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void EngineCapabilities_init(void *self)
537d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
53872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEngineCapabilities *this =
53972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IEngineCapabilities *) self;
540bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &EngineCapabilities_EngineCapabilitiesItf;
541d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
542d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
543ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten// FIXME move
544ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic const SLEnvironmentalReverbSettings EnvironmentalReverb_default = {
545ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SL_MILLIBEL_MIN, // roomLevel
546ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    0,               // roomHFLevel
547ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    1000,            // decayTime
548ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    500,             // decayHFRatio
549ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SL_MILLIBEL_MIN, // reflectionsLevel
550ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    20,              // reflectionsDelay
551ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SL_MILLIBEL_MIN, // reverbLevel
552ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    40,              // reverbDelay
553ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    1000,            // diffusion
554ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    1000             // density
555ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten};
556ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
557ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLEnvironmentalReverbItf_ EnvironmentalReverb_EnvironmentalReverbItf;
558ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
559bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void EnvironmentalReverb_init(void *self)
560d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
56172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
562ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &EnvironmentalReverb_EnvironmentalReverbItf;
563ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties = EnvironmentalReverb_default;
564d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
565d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
566ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLEqualizerItf_ Equalizer_EqualizerItf;
567ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
568bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Equalizer_init(void *self)
569d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
57072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
571ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &Equalizer_EqualizerItf;
572ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnabled = SL_BOOLEAN_FALSE;
573ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mNumBands = 4;
574ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mBandLevelRangeMin = 0;
575ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mBandLevelRangeMax = 1000;
576ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    struct EqualizerBand *band = this->mBands;
577ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    unsigned i;
578ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    for (i = 0; i < this->mNumBands; ++i, ++band) {
579ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mBands[i].mLevel = 0;
580ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mBands[i].mCenter = 0;
581ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mBands[i].mMin = 0;
582ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mBands[i].mMax = 0;
583ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    }
584ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mPreset = 0;
585bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
586bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
587d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLLEDArrayItf_ LEDArray_LEDArrayItf;
588d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
589bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void LEDArray_init(void *self)
590bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
59172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ILEDArray *this = (ILEDArray *) self;
592bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &LEDArray_LEDArrayItf;
593ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
594ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mLightMask = 0;
595ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mColor = NULL;
596ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
597ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mCount = 8;   // FIXME wrong place
598bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
599bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
600ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMetadataExtractionItf_ MetadataExtraction_MetadataExtractionItf;
601ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
602ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic void MetadataExtraction_init(void *self)
603bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
60472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataExtraction *this = (IMetadataExtraction *) self;
605ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MetadataExtraction_MetadataExtractionItf;
606ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKeySize = 0;
607ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKey = NULL;
608ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKeyEncoding = 0 /*TBD*/;
609ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mValueLangCountry = 0 /*TBD*/;
610ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mValueEncoding = 0 /*TBD*/;
611ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mFilterMask = 0 /*TBD*/;
612bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
613bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
614ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMetadataTraversalItf_ MetadataTraversal_MetadataTraversalItf;
615ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
616ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic void MetadataTraversal_init(void *self)
617bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
61872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataTraversal *this = (IMetadataTraversal *) self;
619ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MetadataTraversal_MetadataTraversalItf;
620ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
621ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mIndex = 0;
622ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
623bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
624bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
625ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMIDIMessageItf_ MIDIMessage_MIDIMessageItf;
626ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
627bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void MIDIMessage_init(void *self)
628bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
62972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMessage *this = (IMIDIMessage *) self;
630ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MIDIMessage_MIDIMessageItf;
631ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#ifndef NDEBUG
632ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMetaEventCallback = NULL;
633ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMetaEventContext = NULL;
634ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMessageCallback = NULL;
635ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMessageContext = NULL;
636ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMessageTypes = 0 /*TBD*/;
637ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten#endif
638bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
639bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
640ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMIDIMuteSoloItf_ MIDIMuteSolo_MIDIMuteSoloItf;
641ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
642bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void MIDIMuteSolo_init(void *self)
643bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
64472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
645ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MIDIMuteSolo_MIDIMuteSoloItf;
646bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
647bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
648ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMIDITempoItf_ MIDITempo_MIDITempoItf;
649ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
650bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void MIDITempo_init(void *self)
651bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
65272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITempo *this = (IMIDITempo *) self;
653ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MIDITempo_MIDITempoItf;
654bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
655bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
656ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMIDITimeItf_ MIDITime_MIDITimeItf;
657ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
658bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void MIDITime_init(void *self)
659bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
66072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITime *this = (IMIDITime *) self;
661ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MIDITime_MIDITimeItf;
662bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
663bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
664ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLMuteSoloItf_ MuteSolo_MuteSoloItf;
665ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
666bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void MuteSolo_init(void *self)
667bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
66872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMuteSolo *this = (IMuteSolo *) self;
669ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &MuteSolo_MuteSoloItf;
670bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
671bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
672ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLPrefetchStatusItf_ PrefetchStatus_PrefetchStatusItf;
673ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
674bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void PrefetchStatus_init(void *self)
675bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
67672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
677ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &PrefetchStatus_PrefetchStatusItf;
678bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
679bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
680d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLObjectItf_ Object_ObjectItf;
681d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
682bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Object_init(void *self)
683bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
68472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
685bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Object_ObjectItf;
686d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    this->mState = SL_OBJECT_STATE_UNREALIZED;
687bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
688bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = NULL;
689bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = NULL;
690bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPriority = 0;
691bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPreemptable = SL_BOOLEAN_FALSE;
692bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
69329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    int ok;
69429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL);
69529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    assert(0 == ok);
696e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL);
697e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    assert(0 == ok);
698d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
699d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
700d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLOutputMixItf_ OutputMix_OutputMixItf;
701d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
702bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void OutputMix_init(void *self)
703d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
70472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IOutputMix *this = (IOutputMix *) self;
705bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &OutputMix_OutputMixItf;
7067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten#ifndef NDEBUG
7077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mCallback = NULL;
7087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mContext = NULL;
7097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten#endif
71029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#ifdef USE_OUTPUTMIXEXT
711bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
712bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mActiveMask = 0;
713bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    struct Track *track = &this->mTracks[0];
714bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME O(n)
715bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME magic number
716bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned i;
717bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < 32; ++i, ++track)
718bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        track->mPlay = NULL;
719bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
72029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#endif
721d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
722d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
723bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT
724d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLOutputMixExtItf_ OutputMixExt_OutputMixExtItf;
725d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
726bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void OutputMixExt_init(void *self)
727d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
72872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IOutputMixExt *this =
72972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IOutputMixExt *) self;
730bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &OutputMixExt_OutputMixExtItf;
731d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
732bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_OUTPUTMIXEXT
733d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
734ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLPitchItf_ Pitch_PitchItf;
735ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
736bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Pitch_init(void *self)
737d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
73872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPitch *this = (IPitch *) self;
739ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &Pitch_PitchItf;
740d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
741d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
742d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLPlayItf_ Play_PlayItf;
743d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
744bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Play_init(void *self)
745bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
74672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
747bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Play_PlayItf;
748bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mState = SL_PLAYSTATE_STOPPED;
749bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mDuration = SL_TIME_UNKNOWN;
750bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
751bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPosition = (SLmillisecond) 0;
752bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // this->mPlay.mPositionSamples = 0;
753bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = NULL;
754bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = NULL;
755bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mEventFlags = 0;
756bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mMarkerPosition = 0;
757bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPositionUpdatePeriod = 0;
758bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
759bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
760bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
761ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLPlaybackRateItf_ PlaybackRate_PlaybackRateItf;
762ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
763bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void PlaybackRate_init(void *self)
764bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
76572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlaybackRate *this = (IPlaybackRate *) self;
766ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &PlaybackRate_PlaybackRateItf;
767bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
768bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
769ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLPresetReverbItf_ PresetReverb_PresetReverbItf;
770ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
771bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void PresetReverb_init(void *self)
772bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
77372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPresetReverb *this = (IPresetReverb *) self;
774ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &PresetReverb_PresetReverbItf;
775bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
776bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
777ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLRatePitchItf_ RatePitch_RatePitchItf;
778ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
779bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void RatePitch_init(void *self)
780bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
78172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRatePitch *this = (IRatePitch *) self;
782ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &RatePitch_RatePitchItf;
783bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
784bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
785ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenextern const struct SLRecordItf_ Record_RecordItf;
786ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
787bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Record_init(void *self)
788bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
78972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
790ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mItf = &Record_RecordItf;
791bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
792bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
793d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLSeekItf_ Seek_SeekItf;
794d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
795bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Seek_init(void *self)
796bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
79772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ISeek *this = (ISeek *) self;
798bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Seek_SeekItf;
799bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPos = (SLmillisecond) -1;
800bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mStartPos = (SLmillisecond) -1;
801bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mEndPos = (SLmillisecond) -1;
802bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
803bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mLoopEnabled = SL_BOOLEAN_FALSE;
804bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
805bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
806bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
807d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLThreadSyncItf_ ThreadSync_ThreadSyncItf;
808d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
809bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void ThreadSync_init(void *self)
810bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
81172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IThreadSync *this =
81272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IThreadSync *) self;
813bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &ThreadSync_ThreadSyncItf;
814e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#ifndef NDEBUG
815e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mInCriticalSection = SL_BOOLEAN_FALSE;
816e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mWaiting = SL_BOOLEAN_FALSE;
817e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mOwner = (pthread_t) NULL;
818e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#endif
819bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
820bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
821e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenextern const struct SLVirtualizerItf_ Virtualizer_VirtualizerItf;
822e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten
823bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Virtualizer_init(void *self)
824bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
82572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVirtualizer *this = (IVirtualizer *) self;
826e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mItf = &Virtualizer_VirtualizerItf;
827e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#ifndef NDEBUG
828e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mEnabled = SL_BOOLEAN_FALSE;
829e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mStrength = 0;
830e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#endif
831bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
832bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
833d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLVibraItf_ Vibra_VibraItf;
834d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
835bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Vibra_init(void *self)
836bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
83772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
838bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Vibra_VibraItf;
839e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#ifndef NDEBUG
840e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mVibrate = SL_BOOLEAN_FALSE;
841e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#endif
842ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mFrequency = SLVibraDescriptor_default.minFrequency;
843ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mIntensity = 1000;
844bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
845bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
846d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLVisualizationItf_ Visualization_VisualizationItf;
847d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
848bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Visualization_init(void *self)
849bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
85072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVisualization *this =
85172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IVisualization *) self;
852bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Visualization_VisualizationItf;
853bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
854bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = NULL;
855bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = NULL;
856bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
857ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRate = 20000;
858bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
859bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
860d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLVolumeItf_ Volume_VolumeItf;
861d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
862bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Volume_init(void *self)
863bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
86472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
865bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mItf = &Volume_VolumeItf;
866bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
867ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mLevel = 0;
868bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mMute = SL_BOOLEAN_FALSE;
869bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mEnableStereoPosition = SL_BOOLEAN_FALSE;
870bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mStereoPosition = 0;
871bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
872bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
873bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
874bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct MPH_init {
875bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // unsigned char mMPH;
876bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    VoidHook mInit;
877bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    VoidHook mDeinit;
878bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} MPH_init_table[MPH_MAX] = {
879bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_3DCOMMIT, */ _3DCommit_init, NULL },
880bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_3DDOPPLER, */ _3DDoppler_init, NULL },
881bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_3DGROUPING, */ _3DGrouping_init, NULL },
882bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_3DLOCATION, */ _3DLocation_init, NULL },
883bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ _3DMacroscopic_init, NULL },
884bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_3DSOURCE, */ _3DSource_init, NULL },
885bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ AudioDecoderCapabilities_init, NULL },
886bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_AUDIOENCODER, */ AudioEncoder_init, NULL },
887bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ AudioEncoderCapabilities_init, NULL },
888bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ AudioIODeviceCapabilities_init,
889bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        NULL },
890bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_BASSBOOST, */ BassBoost_init, NULL },
891bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_BUFFERQUEUE, */ BufferQueue_init, NULL },
892bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_DEVICEVOLUME, */ DeviceVolume_init, NULL },
893bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ DynamicInterfaceManagement_init,
894bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        NULL },
895bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ DynamicSource_init, NULL },
896bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_EFFECTSEND, */ EffectSend_init, NULL },
897bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_ENGINE, */ Engine_init, NULL },
898bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ EngineCapabilities_init, NULL },
899bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ EnvironmentalReverb_init, NULL },
900bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_EQUALIZER, */ Equalizer_init, NULL },
901bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_LED, */ LEDArray_init, NULL },
902ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ MetadataExtraction_init, NULL },
903ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ MetadataTraversal_init, NULL },
904bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_MIDIMESSAGE, */ MIDIMessage_init, NULL },
905bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_MIDITIME, */ MIDITime_init, NULL },
906bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_MIDITEMPO, */ MIDITempo_init, NULL },
907bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ MIDIMuteSolo_init, NULL },
908bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_MUTESOLO, */ MuteSolo_init, NULL },
909bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_NULL, */ NULL, NULL },
910bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_OBJECT, */ Object_init, NULL },
911bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_OUTPUTMIX, */ OutputMix_init, NULL },
912bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_PITCH, */ Pitch_init, NULL },
913bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_PLAY, */ Play_init, NULL },
914bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_PLAYBACKRATE, */ PlaybackRate_init, NULL },
915bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ PrefetchStatus_init, NULL },
916bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_PRESETREVERB, */ PresetReverb_init, NULL },
917bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_RATEPITCH, */ RatePitch_init, NULL },
918bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_RECORD, */ Record_init, NULL },
919bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_SEEK, */ Seek_init, NULL },
920bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_THREADSYNC, */ ThreadSync_init, NULL },
921bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_VIBRA, */ Vibra_init, NULL },
922bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_VIRTUALIZER, */ Virtualizer_init, NULL },
923bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_VISUALIZATION, */ Visualization_init, NULL },
924bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_VOLUME, */ Volume_init, NULL },
925bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */
926bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT
927bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        OutputMixExt_init, NULL
928bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
929bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        NULL, NULL
930bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
931bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
932bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
933bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
934bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Classes vs. interfaces */
935bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
936bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// 3DGroup class
937bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
938bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable _3DGroup_interfaces[] = {
939bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
94072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, mObject)},
941bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
94272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, mDynamicInterfaceManagement)},
943bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DLOCATION, INTERFACE_IMPLICIT,
94472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DLocation)},
945bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME,
94672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DDoppler)},
947bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DSOURCE, INTERFACE_GAME,
94872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DSource)},
949bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DMACROSCOPIC, INTERFACE_OPTIONAL,
95072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DMacroscopic)},
951bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
952bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
95372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable _3DGroup_class = {
954bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DGroup_interfaces,
955bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(_3DGroup_interfaces)/sizeof(_3DGroup_interfaces[0]),
956bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_3DGroup,
957bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"3DGroup",
95872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(C3DGroup),
959bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_3DGROUP,
960bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
96172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    NULL,
962bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
963d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten};
964d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
965bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// AudioPlayer class
966bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
967bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* AudioPlayer private functions */
9682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
9692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SNDFILE
9702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
9712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten// FIXME should run this asynchronously esp. for socket fd, not on mix thread
9722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic void SLAPIENTRY SndFile_Callback(SLBufferQueueItf caller, void *pContext)
9732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
9742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    struct SndFile *this = (struct SndFile *) pContext;
9752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLresult result;
9762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != this->mRetryBuffer && 0 < this->mRetrySize) {
977bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        result = (*caller)->Enqueue(caller, this->mRetryBuffer,
978bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            this->mRetrySize);
9792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result)
9802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return;     // what, again?
9812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
9822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        this->mRetryBuffer = NULL;
9832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        this->mRetrySize = 0;
9842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return;
9852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
9862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    short *pBuffer = this->mIs0 ? this->mBuffer0 : this->mBuffer1;
9872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mIs0 ^= SL_BOOLEAN_TRUE;
9882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    sf_count_t count;
9892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // FIXME magic number
9902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    count = sf_read_short(this->mSNDFILE, pBuffer, (sf_count_t) 512);
9912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (0 < count) {
9922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLuint32 size = count * sizeof(short);
9932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // FIXME if we had an internal API, could call this directly
9942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        result = (*caller)->Enqueue(caller, pBuffer, size);
9952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result) {
9962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            this->mRetryBuffer = pBuffer;
9972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            this->mRetrySize = size;
9982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return;
9992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
10002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
10012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
10022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
10032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
10042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLboolean SndFile_IsSupported(const SF_INFO *sfinfo)
10052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
10062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (sfinfo->format & SF_FORMAT_TYPEMASK) {
10072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SF_FORMAT_WAV:
10082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
10092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
10102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_BOOLEAN_FALSE;
10112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
10122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (sfinfo->format & SF_FORMAT_SUBMASK) {
10132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SF_FORMAT_PCM_16:
10142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
10152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
10162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_BOOLEAN_FALSE;
10172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
10182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (sfinfo->samplerate) {
10192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case 44100:
10202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
10212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
10222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_BOOLEAN_FALSE;
10232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
10242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (sfinfo->channels) {
10252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case 2:
10262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
10272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
10282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_BOOLEAN_FALSE;
10292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
10302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_BOOLEAN_TRUE;
10312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
10322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
1033bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE
10342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
1035a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
1036a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#ifdef USE_ANDROID
1037a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivistatic void *thread_body(void *arg)
1038a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi{
103972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CAudioPlayer *this = (CAudioPlayer *) arg;
1040a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    android::AudioTrack *at = this->mAudioTrack;
1041a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#if 1
1042a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    at->start();
1043a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#endif
104472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBufferQueue *bufferQueue = &this->mBufferQueue;
1045a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    for (;;) {
1046a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        // FIXME replace unsafe polling by a mutex and condition variable
1047a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        struct BufferHeader *oldFront = bufferQueue->mFront;
1048a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        struct BufferHeader *rear = bufferQueue->mRear;
1049a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        if (oldFront == rear) {
1050a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi            usleep(10000);
1051a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi            continue;
1052a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        }
1053a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        struct BufferHeader *newFront = &oldFront[1];
1054a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        if (newFront == &bufferQueue->mArray[bufferQueue->mNumBuffers])
1055a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi            newFront = bufferQueue->mArray;
1056a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        at->write(oldFront->mBuffer, oldFront->mSize);
1057a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        assert(mState.count > 0);
1058a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        --bufferQueue->mState.count;
1059a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        ++bufferQueue->mState.playIndex;
1060a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        bufferQueue->mFront = newFront;
1061a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        slBufferQueueCallback callback = bufferQueue->mCallback;
1062a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        if (NULL != callback) {
1063a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi            (*callback)((SLBufferQueueItf) bufferQueue,
1064a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                bufferQueue->mContext);
1065a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        }
1066a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    }
1067a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    // unreachable
1068a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    return NULL;
1069a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi}
1070a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#endif
1071a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
1072bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult AudioPlayer_Realize(void *self)
1073bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
107472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CAudioPlayer *this = (CAudioPlayer *) self;
1075bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
107648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi
1077a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#ifdef USE_ANDROID
1078a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    // FIXME move this to android specific files
107948913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    result = sles_to_android_realizeAudioPlayer(this);
1080a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    int ok;
1081a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    ok = pthread_create(&this->mThread, (const pthread_attr_t *) NULL, thread_body, this);
1082a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    assert(ok == 0);
1083a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#endif
1084a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
1085bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_SNDFILE
10862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != this->mSndFile.mPathname) {
10872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SF_INFO sfinfo;
10882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        sfinfo.format = 0;
10892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        this->mSndFile.mSNDFILE = sf_open(
10902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            (const char *) this->mSndFile.mPathname, SFM_READ, &sfinfo);
10912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (NULL == this->mSndFile.mSNDFILE) {
10922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            result = SL_RESULT_CONTENT_NOT_FOUND;
10932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        } else if (!SndFile_IsSupported(&sfinfo)) {
10942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            sf_close(this->mSndFile.mSNDFILE);
10952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            this->mSndFile.mSNDFILE = NULL;
10962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            result = SL_RESULT_CONTENT_UNSUPPORTED;
10972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        } else {
109829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // FIXME how do we know this interface is exposed?
1099bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLBufferQueueItf bufferQueue = &this->mBufferQueue.mItf;
11002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // FIXME should use a private internal API, and disallow
11012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // application to have access to our buffer queue
11022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // FIXME if we had an internal API, could call this directly
110329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // FIXME can't call this directly as we get a double lock
110429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // result = (*bufferQueue)->RegisterCallback(bufferQueue,
110529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            //    SndFile_Callback, &this->mSndFile);
110629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // FIXME so let's inline the code, but this is maintenance risk
110729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // we know we are called by Object_Realize, which holds a lock,
110829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // but if interface lock != object lock, need to rewrite this
110972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            IBufferQueue *thisBQ =
111072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten                (IBufferQueue *) bufferQueue;
111129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            thisBQ->mCallback = SndFile_Callback;
111229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            thisBQ->mContext = &this->mSndFile;
11132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
11142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
1115bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE
11162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return result;
11172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
11182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
1119bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void AudioPlayer_Destroy(void *self)
11202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
112172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CAudioPlayer *this = (CAudioPlayer *) self;
11222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // FIXME stop the player in a way that app can't restart it
1123bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // Free the buffer queue, if it was larger than typical
1124bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this->mBufferQueue.mArray &&
1125bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        this->mBufferQueue.mArray != this->mBufferQueue.mTypical) {
11262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        free(this->mBufferQueue.mArray);
1127bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        this->mBufferQueue.mArray = NULL;
1128bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
11292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SNDFILE
11302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != this->mSndFile.mSNDFILE) {
11312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        sf_close(this->mSndFile.mSNDFILE);
11322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        this->mSndFile.mSNDFILE = NULL;
11332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
1134bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE
1135bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1136bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1137bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable AudioPlayer_interfaces[] = {
1138bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
113972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mObject)},
1140bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
114172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mDynamicInterfaceManagement)},
1142bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PLAY, INTERFACE_IMPLICIT,
114372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mPlay)},
1144bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME,
114572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, m3DDoppler)},
1146bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DGROUPING, INTERFACE_GAME,
114772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, m3DGrouping)},
1148bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DLOCATION, INTERFACE_GAME,
114972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, m3DLocation)},
1150bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DSOURCE, INTERFACE_GAME,
115172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, m3DSource)},
1152bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME Currently we create an internal buffer queue for playing files
1153bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_BUFFERQUEUE, /* INTERFACE_GAME */ INTERFACE_IMPLICIT,
115472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mBufferQueue)},
1155bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_EFFECTSEND, INTERFACE_MUSIC_GAME,
115672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mEffectSend)},
1157bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_MUTESOLO, INTERFACE_GAME,
115872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mMuteSolo)},
1159bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_METADATAEXTRACTION, INTERFACE_MUSIC_GAME,
116072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mMetadataExtraction)},
1161bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_METADATATRAVERSAL, INTERFACE_MUSIC_GAME,
116272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mMetadataTraversal)},
1163bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PREFETCHSTATUS, INTERFACE_TBD,
116472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mPrefetchStatus)},
1165bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_RATEPITCH, INTERFACE_DYNAMIC_GAME,
116672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mRatePitch)},
1167bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_SEEK, INTERFACE_TBD,
116872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mSeek)},
1169bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VOLUME, INTERFACE_TBD,
117072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mVolume)},
1171bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DMACROSCOPIC, INTERFACE_OPTIONAL,
117272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, m3DMacroscopic)},
1173bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_BASSBOOST, INTERFACE_OPTIONAL,
117472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mBassBoost)},
1175bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICSOURCE, INTERFACE_OPTIONAL,
117672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mDynamicSource)},
1177bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_ENVIRONMENTALREVERB, INTERFACE_OPTIONAL,
117872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mEnvironmentalReverb)},
1179bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_EQUALIZER, INTERFACE_OPTIONAL,
118072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mEqualizer)},
1181bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PITCH, INTERFACE_OPTIONAL,
118272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mPitch)},
1183bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PRESETREVERB, INTERFACE_OPTIONAL,
118472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mPresetReverb)},
1185bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PLAYBACKRATE, INTERFACE_OPTIONAL,
118672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mPlaybackRate)},
1187bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VIRTUALIZER, INTERFACE_OPTIONAL,
118872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mVirtualizer)},
1189bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VISUALIZATION, INTERFACE_OPTIONAL,
119072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioPlayer, mVisualization)}
1191bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1192bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
119372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable AudioPlayer_class = {
1194bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    AudioPlayer_interfaces,
1195bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(AudioPlayer_interfaces)/sizeof(AudioPlayer_interfaces[0]),
1196bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_AudioPlayer,
1197bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"AudioPlayer",
119872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CAudioPlayer),
1199bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_AUDIOPLAYER,
1200bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    AudioPlayer_Realize,
120129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL /*AudioPlayer_Resume*/,
1202bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    AudioPlayer_Destroy
1203bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1204bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1205bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// AudioRecorder class
1206bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1207bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable AudioRecorder_interfaces[] = {
1208bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
120972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mObject)},
1210bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
121172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mDynamicInterfaceManagement)},
1212bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_RECORD, INTERFACE_IMPLICIT,
121372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mRecord)},
1214bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_AUDIOENCODER, INTERFACE_TBD,
121572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mAudioEncoder)},
1216bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_BASSBOOST, INTERFACE_OPTIONAL,
121772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mBassBoost)},
1218bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICSOURCE, INTERFACE_OPTIONAL,
121972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mDynamicSource)},
1220bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_EQUALIZER, INTERFACE_OPTIONAL,
122172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mEqualizer)},
1222bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VISUALIZATION, INTERFACE_OPTIONAL,
122372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mVisualization)},
1224bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VOLUME, INTERFACE_OPTIONAL,
122572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CAudioRecorder, mVolume)}
1226bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1227bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
122872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable AudioRecorder_class = {
1229bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    AudioRecorder_interfaces,
1230bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(AudioRecorder_interfaces)/sizeof(AudioRecorder_interfaces[0]),
1231bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_AudioRecorder,
1232bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"AudioRecorder",
123372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CAudioRecorder),
1234bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_AUDIORECORDER,
1235bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
123629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1237bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1238bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1239bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1240bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Engine class
1241bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1242bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable Engine_interfaces[] = {
1243bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
124472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mObject)},
1245bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
124672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mDynamicInterfaceManagement)},
1247bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_ENGINE, INTERFACE_IMPLICIT,
124872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mEngine)},
1249bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_ENGINECAPABILITIES, INTERFACE_IMPLICIT,
125072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mEngineCapabilities)},
1251bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_THREADSYNC, INTERFACE_IMPLICIT,
125272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mThreadSync)},
1253bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_AUDIOIODEVICECAPABILITIES, INTERFACE_IMPLICIT,
125472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mAudioIODeviceCapabilities)},
1255bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_AUDIODECODERCAPABILITIES, INTERFACE_EXPLICIT,
125672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mAudioDecoderCapabilities)},
1257bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_AUDIOENCODERCAPABILITIES, INTERFACE_EXPLICIT,
125872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mAudioEncoderCapabilities)},
1259bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DCOMMIT, INTERFACE_EXPLICIT_GAME,
126072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, m3DCommit)},
1261bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DEVICEVOLUME, INTERFACE_OPTIONAL,
126272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CEngine, mDeviceVolume)}
1263bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1264bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
126572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable Engine_class = {
1266bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Engine_interfaces,
1267bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(Engine_interfaces)/sizeof(Engine_interfaces[0]),
1268bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_Engine,
1269bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"Engine",
127072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CEngine),
1271bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_ENGINE,
1272bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
127329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1274bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1275bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1276bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1277bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// LEDDevice class
1278bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1279bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable LEDDevice_interfaces[] = {
1280bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
128172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CLEDDevice, mObject)},
1282bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
128372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CLEDDevice, mDynamicInterfaceManagement)},
1284bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_LED, INTERFACE_IMPLICIT,
128572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CLEDDevice, mLEDArray)}
1286bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1287bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
128872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable LEDDevice_class = {
1289bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    LEDDevice_interfaces,
1290bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(LEDDevice_interfaces)/sizeof(LEDDevice_interfaces[0]),
1291bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_LEDDevice,
1292bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"LEDDevice",
129372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CLEDDevice),
1294bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_LEDDEVICE,
1295bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
129629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1297bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1298bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1299bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1300bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Listener class
1301bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1302bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable Listener_interfaces[] = {
1303bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
130472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CListener, mObject)},
1305bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
130672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CListener, mDynamicInterfaceManagement)},
1307bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME,
130872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DDoppler)},
1309bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DLOCATION, INTERFACE_EXPLICIT_GAME,
131072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DLocation)}
1311bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1312bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
131372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable Listener_class = {
1314bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Listener_interfaces,
1315bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(Listener_interfaces)/sizeof(Listener_interfaces[0]),
1316bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_Listener,
1317bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"Listener",
131872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CListener),
1319bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_LISTENER,
1320bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
132129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1322bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1323bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1324bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1325bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// MetadataExtractor class
1326bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1327bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable MetadataExtractor_interfaces[] = {
1328bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
132972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMetadataExtractor, mObject)},
1330bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
133172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMetadataExtractor, mDynamicInterfaceManagement)},
1332bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICSOURCE, INTERFACE_IMPLICIT,
133372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMetadataExtractor, mDynamicSource)},
1334bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_METADATAEXTRACTION, INTERFACE_IMPLICIT,
133572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMetadataExtractor, mMetadataExtraction)},
1336bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_METADATATRAVERSAL, INTERFACE_IMPLICIT,
133772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMetadataExtractor, mMetadataTraversal)}
1338bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1339bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
134072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable MetadataExtractor_class = {
1341bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtractor_interfaces,
1342bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(MetadataExtractor_interfaces) /
1343bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        sizeof(MetadataExtractor_interfaces[0]),
1344bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_MetadataExtractor,
1345bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"MetadataExtractor",
134672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CMetadataExtractor),
1347bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_METADATAEXTRACTOR,
1348bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
134929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1350bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1351bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1352bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1353bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// MidiPlayer class
1354bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1355bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable MidiPlayer_interfaces[] = {
1356bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
135772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mObject)},
1358bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
135972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mDynamicInterfaceManagement)},
1360bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PLAY, INTERFACE_IMPLICIT,
136172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mPlay)},
1362bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME,
136372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(C3DGroup, m3DDoppler)},
1364bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DGROUPING, INTERFACE_GAME,
136572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, m3DGrouping)},
1366bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DLOCATION, INTERFACE_GAME,
136772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, m3DLocation)},
1368bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DSOURCE, INTERFACE_GAME,
136972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, m3DSource)},
1370bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_BUFFERQUEUE, INTERFACE_GAME,
137172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mBufferQueue)},
1372bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_EFFECTSEND, INTERFACE_GAME,
137372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mEffectSend)},
1374bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_MUTESOLO, INTERFACE_GAME,
137572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMuteSolo)},
1376bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_METADATAEXTRACTION, INTERFACE_GAME,
137772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMetadataExtraction)},
1378bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_METADATATRAVERSAL, INTERFACE_GAME,
137972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMetadataTraversal)},
1380bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_MIDIMESSAGE, INTERFACE_PHONE_GAME,
138172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMIDIMessage)},
1382bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_MIDITIME, INTERFACE_PHONE_GAME,
138372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMIDITime)},
1384bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_MIDITEMPO, INTERFACE_PHONE_GAME,
138572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMIDITempo)},
1386bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_MIDIMUTESOLO, INTERFACE_GAME,
138772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mMIDIMuteSolo)},
1388bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PREFETCHSTATUS, INTERFACE_PHONE_GAME,
138972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mPrefetchStatus)},
1390bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_SEEK, INTERFACE_PHONE_GAME,
139172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mSeek)},
1392bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VOLUME, INTERFACE_PHONE_GAME,
139372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mVolume)},
1394bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_3DMACROSCOPIC, INTERFACE_OPTIONAL,
139572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, m3DMacroscopic)},
1396bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_BASSBOOST, INTERFACE_OPTIONAL,
139772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mBassBoost)},
1398bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICSOURCE, INTERFACE_OPTIONAL,
139972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mDynamicSource)},
1400bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_ENVIRONMENTALREVERB, INTERFACE_OPTIONAL,
140172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mEnvironmentalReverb)},
1402bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_EQUALIZER, INTERFACE_OPTIONAL,
140372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mEqualizer)},
1404bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PITCH, INTERFACE_OPTIONAL,
140572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mPitch)},
1406bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PRESETREVERB, INTERFACE_OPTIONAL,
140772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mPresetReverb)},
1408bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PLAYBACKRATE, INTERFACE_OPTIONAL,
140972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mPlaybackRate)},
1410bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VIRTUALIZER, INTERFACE_OPTIONAL,
141172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mVirtualizer)},
1412bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VISUALIZATION, INTERFACE_OPTIONAL,
141372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CMidiPlayer, mVisualization)}
1414bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1415bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
141672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable MidiPlayer_class = {
1417bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MidiPlayer_interfaces,
1418bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(MidiPlayer_interfaces)/sizeof(MidiPlayer_interfaces[0]),
1419bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_MidiPlayer,
1420bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"MidiPlayer",
142172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CMidiPlayer),
1422bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_MIDIPLAYER,
1423bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
142429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1425bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1426bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1427bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1428bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// OutputMix class
1429bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1430bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable OutputMix_interfaces[] = {
1431bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_IMPLICIT,
143272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mObject)},
1433bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
143472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mDynamicInterfaceManagement)},
1435bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OUTPUTMIX, INTERFACE_IMPLICIT,
143672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mOutputMix)},
1437bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT
1438bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OUTPUTMIXEXT, INTERFACE_IMPLICIT,
143972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mOutputMixExt)},
1440bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
1441bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OUTPUTMIXEXT, INTERFACE_TBD /*NOT AVAIL*/, 0},
1442bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
1443bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_ENVIRONMENTALREVERB, INTERFACE_DYNAMIC_GAME,
144472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mEnvironmentalReverb)},
1445bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_EQUALIZER, INTERFACE_DYNAMIC_MUSIC_GAME,
144672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mEqualizer)},
1447bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_PRESETREVERB, INTERFACE_DYNAMIC_MUSIC,
144872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mPresetReverb)},
1449bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VIRTUALIZER, INTERFACE_DYNAMIC_MUSIC_GAME,
145072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mVirtualizer)},
1451bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VOLUME, INTERFACE_GAME_MUSIC,
145272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mVolume)},
1453bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_BASSBOOST, INTERFACE_OPTIONAL_DYNAMIC,
145472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mBassBoost)},
1455bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VISUALIZATION, INTERFACE_OPTIONAL,
145672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(COutputMix, mVisualization)}
1457bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1458bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
145972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable OutputMix_class = {
1460bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    OutputMix_interfaces,
1461bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(OutputMix_interfaces)/sizeof(OutputMix_interfaces[0]),
1462bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_OutputMix,
1463bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"OutputMix",
146472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(COutputMix),
1465bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_OUTPUTMIX,
1466bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
146729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1468bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1469bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1470bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1471bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Vibra class
1472bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1473bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable VibraDevice_interfaces[] = {
1474bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_OBJECT, INTERFACE_OPTIONAL,
147572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CVibraDevice, mObject)},
1476bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_OPTIONAL,
147772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CVibraDevice, mDynamicInterfaceManagement)},
1478bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    {MPH_VIBRA, INTERFACE_OPTIONAL,
147972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        offsetof(CVibraDevice, mVibra)}
1480bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1481bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
148272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable VibraDevice_class = {
1483bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    VibraDevice_interfaces,
1484bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    sizeof(VibraDevice_interfaces)/sizeof(VibraDevice_interfaces[0]),
1485bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MPH_to_Vibra,
1486bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //"VibraDevice",
148772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    sizeof(CVibraDevice),
1488bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SL_OBJECTID_VIBRADEVICE,
1489bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL,
149029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    NULL,
1491bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    NULL
1492bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1493bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1494bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Map SL_OBJECTID to class */
1495bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
149672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable * const classes[] = {
1497bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // Do not change order of these entries; they are in numerical order
1498bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &Engine_class,
1499bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &LEDDevice_class,
1500bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &AudioPlayer_class,
1501bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &AudioRecorder_class,
1502bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &MidiPlayer_class,
1503bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &Listener_class,
1504bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &_3DGroup_class,
1505bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &VibraDevice_class,
1506bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &OutputMix_class,
1507bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    &MetadataExtractor_class
1508bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1509bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
151072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable *objectIDtoClass(SLuint32 objectID)
1511bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
1512bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 objectID0 = classes[0]->mObjectID;
1513bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (objectID0 <= objectID &&
1514bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        classes[sizeof(classes)/sizeof(classes[0])-1]->mObjectID >= objectID)
1515bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return classes[objectID - objectID0];
1516bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return NULL;
1517bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1518bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1519bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Construct a new instance of the specified class, exposing selected interfaces
1520bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
152172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic IObject *construct(const ClassTable *class__,
152229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    unsigned exposedMask, SLEngineItf engine)
1523bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
152472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this;
1525bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
152672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) malloc(class__->mSize);
1527bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
152872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) calloc(1, class__->mSize);
1529bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
1530bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this) {
1531bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
1532bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        // for debugging, to detect uninitialized fields
1533bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        memset(this, 0x55, class__->mSize);
1534bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
153529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        this->mClass = class__;
153629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        this->mExposedMask = exposedMask;
153772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
153872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
153972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        if (NULL == thisEngine)
154072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            thisEngine = &((CEngine *) this)->mEngine;
154172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        else if (thisEngine->mLossOfControlGlobal)
154272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            lossOfControlMask = ~0;
154372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mLossOfControlMask = lossOfControlMask;
1544bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct iid_vtable *x = class__->mInterfaces;
1545bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        unsigned i;
1546bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        for (i = 0; exposedMask; ++i, ++x, exposedMask >>= 1) {
1547bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (exposedMask & 1) {
154883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                void *self = (char *) this + x->mOffset;
154972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten                ((IObject **) self)[1] = this;
155083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                VoidHook init = MPH_init_table[x->mMPH].mInit;
1551bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                if (NULL != init)
1552bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    (*init)(self);
1553bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
1554bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
155572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        // FIXME need a lock
155672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        if (INSTANCE_MAX > thisEngine->mInstanceCount) {
155772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            // FIXME ignores Destroy
155872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            thisEngine->mInstances[thisEngine->mInstanceCount++] = this;
155972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        }
156072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        // FIXME else what
1561bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
1562bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return this;
1563bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1564bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1565bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Interface implementations */
1566bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1567bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// FIXME Sort by interface
1568bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1569bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Object implementation */
1570bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1571bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_Realize(SLObjectItf self, SLboolean async)
1572bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
157372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
157472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = this->mClass;
1575bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    StatusHook realize = class__->mRealize;
157629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
157729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(this);
157829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME The realize hook and callback should be asynchronous if requested
157929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (SL_OBJECT_STATE_UNREALIZED != this->mState) {
158029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
158129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    } else {
158229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (NULL != realize)
158329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            result = (*realize)(this);
158429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (SL_RESULT_SUCCESS == result)
158529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            this->mState = SL_OBJECT_STATE_REALIZED;
158629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        // FIXME callback should not run with mutex lock
158729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (async && (NULL != this->mCallback))
158829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            (*this->mCallback)(self, this->mContext,
158929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            SL_OBJECT_EVENT_ASYNC_TERMINATION, result, this->mState, NULL);
159029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
159129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(this);
1592bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return result;
1593bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1594bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1595bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_Resume(SLObjectItf self, SLboolean async)
1596bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
159772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
159872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = this->mClass;
159929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    StatusHook resume = class__->mResume;
160029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
160129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(this);
160229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME The resume hook and callback should be asynchronous if requested
160329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (SL_OBJECT_STATE_SUSPENDED != this->mState) {
160429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
160529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    } else {
160629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (NULL != resume)
160729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            result = (*resume)(this);
160829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (SL_RESULT_SUCCESS == result)
160929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            this->mState = SL_OBJECT_STATE_REALIZED;
161029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        // FIXME callback should not run with mutex lock
161129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (async && (NULL != this->mCallback))
161229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            (*this->mCallback)(self, this->mContext,
161329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            SL_OBJECT_EVENT_ASYNC_TERMINATION, result, this->mState, NULL);
161429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
161529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(this);
161629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    return result;
1617bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1618bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1619bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_GetState(SLObjectItf self, SLuint32 *pState)
1620bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
1621bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pState)
1622bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
162372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
162429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME Investigate what it would take to change to a peek lock
162529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_shared(this);
162629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLuint32 state = this->mState;
162729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_shared(this);
162829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pState = state;
1629bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
1630bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1631bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1632bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_GetInterface(SLObjectItf self, const SLInterfaceID iid,
1633bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    void *pInterface)
1634bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
163529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (NULL == pInterface)
1636bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
163729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result;
163829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    void *interface = NULL;
163929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (NULL == iid)
164029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
164129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    else {
164272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IObject *this = (IObject *) self;
164372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        const ClassTable *class__ = this->mClass;
164429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        int MPH, index;
164529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) ||
164629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            (0 > (index = class__->mMPH_to_index[MPH])))
164729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
164829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        else {
164929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            unsigned mask = 1 << index;
165029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            object_lock_shared(this);
165129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if (SL_OBJECT_STATE_REALIZED != this->mState)
165229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
165329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            else if (!(this->mExposedMask & mask))
165429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                result = SL_RESULT_FEATURE_UNSUPPORTED;
165529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            else {
165629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                // FIXME Should note that interface has been gotten,
165729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                // so as to detect use of ill-gotten interfaces; be sure
165829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                // to change the lock to exclusive if that is done
165929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                interface = (char *) this + class__->mInterfaces[index].mOffset;
166029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                result = SL_RESULT_SUCCESS;
166129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            }
166229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            object_unlock_shared(this);
166329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        }
166429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
166529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *(void **)pInterface = interface;
1666bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
1667bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1668bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1669bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_RegisterCallback(SLObjectItf self,
1670bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    slObjectCallback callback, void *pContext)
1671bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
167272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
167329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME This could be a poke lock, if we had atomic double-word load/store
167429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(this);
1675bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = callback;
1676bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = pContext;
167729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(this);
1678bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
1679bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1680bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1681bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Object_AbortAsyncOperation(SLObjectItf self)
1682bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
168329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME Asynchronous operations are not yet implemented
1684bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1685bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1686bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void Object_Destroy(SLObjectItf self)
1687bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
1688bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Object_AbortAsyncOperation(self);
168972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
169072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = this->mClass;
1691bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    VoidHook destroy = class__->mDestroy;
169229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    const struct iid_vtable *x = class__->mInterfaces;
169329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(this);
169429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // Call the deinitializer for each currently exposed interface,
169529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // whether it is implicit, explicit, optional, or dynamically added.
169629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    unsigned exposedMask = this->mExposedMask;
169729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    for ( ; exposedMask; exposedMask >>= 1, ++x) {
169829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (exposedMask & 1) {
169929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            VoidHook deinit = MPH_init_table[x->mMPH].mDeinit;
170029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if (NULL != deinit)
170129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                (*deinit)((char *) this + x->mOffset);
170229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        }
170329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
1704bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != destroy)
1705bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        (*destroy)(this);
170629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED;
170729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(this);
1708bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
170929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    memset(this, 0x55, class__->mSize);
17102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#endif
17112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    free(this);
17122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
17132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
1714bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_SetPriority(SLObjectItf self, SLint32 priority,
1715bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean preemptable)
1716bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
171772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
171829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(this);
1719bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPriority = priority;
1720bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPreemptable = preemptable;
172129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(this);
1722bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
1723bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1724bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1725bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_GetPriority(SLObjectItf self, SLint32 *pPriority,
1726bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pPreemptable)
1727bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
1728bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pPriority || NULL == pPreemptable)
1729bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
173072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this = (IObject *) self;
173129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_shared(this);
173229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLint32 priority = this->mPriority;
173329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLboolean preemptable = this->mPreemptable;
173429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_shared(this);
173529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pPriority = priority;
173629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pPreemptable = preemptable;
1737bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
1738bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1739bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1740bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Object_SetLossOfControlInterfaces(SLObjectItf self,
1741bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled)
1742bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
174329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (0 < numInterfaces) {
174429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        SLuint32 i;
174529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (NULL == pInterfaceIDs)
174629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            return SL_RESULT_PARAMETER_INVALID;
174772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IObject *this = (IObject *) self;
174872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        const ClassTable *class__ = this->mClass;
174929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        unsigned lossOfControlMask = 0;
175029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        // FIXME The cast is due to a typo in the spec
175129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        for (i = 0; i < (SLuint32) numInterfaces; ++i) {
175229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            SLInterfaceID iid = pInterfaceIDs[i];
175329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if (NULL == iid)
175429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
175529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
175629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if (0 <= (MPH = IID_to_MPH(iid)) &&
175729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                (0 <= (index = class__->mMPH_to_index[MPH])))
175829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                lossOfControlMask |= (1 << index);
175929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        }
176029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        object_lock_exclusive(this);
176129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (enabled)
176229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            this->mLossOfControlMask |= lossOfControlMask;
176329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        else
176429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            this->mLossOfControlMask &= ~lossOfControlMask;
176529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        object_unlock_exclusive(this);
176629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
1767bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
1768bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1769bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1770bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLObjectItf_ Object_ObjectItf = {
1771bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Object_Realize,
17722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_Resume,
17732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_GetState,
17742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_GetInterface,
17752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_RegisterCallback,
17762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_AbortAsyncOperation,
1777bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Object_Destroy,
17782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_SetPriority,
17792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_GetPriority,
17802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Object_SetLossOfControlInterfaces,
17812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
17822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
1783d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* DynamicInterfaceManagement implementation */
1784d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1785d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult DynamicInterfaceManagement_AddInterface(
1786bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLDynamicInterfaceManagementItf self, const SLInterfaceID iid,
1787bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean async)
1788d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1789bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == iid)
1790bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
179172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicInterfaceManagement *this =
179272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDynamicInterfaceManagement *) self;
179372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject = this->mThis;
179472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
179529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    int MPH, index;
179629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if ((0 > (MPH = IID_to_MPH(iid))) ||
179729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        (0 > (index = class__->mMPH_to_index[MPH])))
1798bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_FEATURE_UNSUPPORTED;
179929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result;
180029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    VoidHook init = MPH_init_table[MPH].mInit;
1801bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *x = &class__->mInterfaces[index];
1802bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    size_t offset = x->mOffset;
1803bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    void *thisItf = (char *) thisObject + offset;
1804bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
1805bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        class__->mSize : x[1].mOffset) - offset;
180629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    unsigned mask = 1 << index;
180729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // Lock the object rather than the DIM interface, because
180829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // we modify both the object (exposed) and interface (added)
180929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(thisObject);
181029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (thisObject->mExposedMask & mask) {
181129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
181229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    } else {
181329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        // FIXME Currently do initialization here, but might be asynchronous
1814bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
1815bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// for debugging, to detect uninitialized fields
1816bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#define FILLER 0x55
1817bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
1818bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#define FILLER 0
1819bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
182029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        memset(thisItf, FILLER, size);
182129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        ((void **) thisItf)[1] = thisObject;
182229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (NULL != init)
182329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            (*init)(thisItf);
182429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        thisObject->mExposedMask |= mask;
182529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        this->mAddedMask |= mask;
182629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_SUCCESS;
182729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (async && (NULL != this->mCallback)) {
182829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // FIXME Callback runs with mutex locked
182929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            (*this->mCallback)(self, this->mContext,
183029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                SL_DYNAMIC_ITF_EVENT_RESOURCES_AVAILABLE, result, iid);
183129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        }
1832bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
183329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(thisObject);
1834bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return result;
1835d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1836d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1837d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult DynamicInterfaceManagement_RemoveInterface(
1838bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLDynamicInterfaceManagementItf self, const SLInterfaceID iid)
1839d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1840bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == iid)
1841bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
184272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicInterfaceManagement *this =
184372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDynamicInterfaceManagement *) self;
184472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject =
184572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IObject *) this->mThis;
184672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
1847bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    int MPH = IID_to_MPH(iid);
184829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (0 > MPH)
1849bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
1850bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    int index = class__->mMPH_to_index[MPH];
185129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (0 > index)
1852bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
185329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
185429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    VoidHook deinit = MPH_init_table[MPH].mDeinit;
1855bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *x = &class__->mInterfaces[index];
1856bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    size_t offset = x->mOffset;
1857bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    void *thisItf = (char *) thisObject + offset;
1858bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
1859bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        class__->mSize : x[1].mOffset) - offset;
186029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    unsigned mask = 1 << index;
186129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // Lock the object rather than the DIM interface, because
186229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // we modify both the object (exposed) and interface (added)
186329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(thisObject);
186429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // disallow removal of non-dynamic interfaces
186529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (!(this->mAddedMask & mask)) {
186629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
186729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    } else {
186829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        if (NULL != deinit)
186929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            (*deinit)(thisItf);
1870bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
187129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        memset(thisItf, 0x55, size);
1872bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
187329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        thisObject->mExposedMask &= ~mask;
187429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        this->mAddedMask &= ~mask;
187529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
187629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(thisObject);
187729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    return result;
1878d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1879d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1880d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult DynamicInterfaceManagement_ResumeInterface(
1881d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLDynamicInterfaceManagementItf self,
1882d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLInterfaceID iid, SLboolean async)
1883d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
188429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (NULL == iid)
188529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
188672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicInterfaceManagement *this =
188772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDynamicInterfaceManagement *) self;
188872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject =
188972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IObject *) this->mThis;
189072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
189129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    int MPH = IID_to_MPH(iid);
189229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (0 > MPH)
189329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
189429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    int index = class__->mMPH_to_index[MPH];
189529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (0 > index)
189629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
189729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
189829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    unsigned mask = 1 << index;
189929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME Change to exclusive when resume hook implemented
190029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_shared(thisObject);
190129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (!(this->mAddedMask & mask))
190229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
190329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME Call a resume hook on the interface, if suspended
190429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_shared(thisObject);
190529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    return result;
1906d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1907d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1908d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult DynamicInterfaceManagement_RegisterCallback(
1909d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLDynamicInterfaceManagementItf self,
1910d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    slDynamicInterfaceManagementCallback callback, void *pContext)
1911d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
191272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicInterfaceManagement *this =
191372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDynamicInterfaceManagement *) self;
191472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject = this->mThis;
191529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME This could be a poke lock, if we had atomic double-word load/store
191629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_lock_exclusive(thisObject);
1917bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = callback;
1918bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = pContext;
191929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    object_unlock_exclusive(thisObject);
1920d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
1921d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1922d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1923bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLDynamicInterfaceManagementItf_
1924d7143537437acbd4b97761a1c5bf852be9ba485aGlenn KastenDynamicInterfaceManagement_DynamicInterfaceManagementItf = {
1925d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    DynamicInterfaceManagement_AddInterface,
1926d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    DynamicInterfaceManagement_RemoveInterface,
1927d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    DynamicInterfaceManagement_ResumeInterface,
1928d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    DynamicInterfaceManagement_RegisterCallback
1929d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten};
1930d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1931d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* Play implementation */
1932d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1933d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_SetPlayState(SLPlayItf self, SLuint32 state)
1934d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1935d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    switch (state) {
1936d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_PLAYSTATE_STOPPED:
1937d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_PLAYSTATE_PAUSED:
1938d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_PLAYSTATE_PLAYING:
1939d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        break;
1940d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    default:
1941d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
1942d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
194372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
194429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_exclusive(this);
1945d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    this->mState = state;
19462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SL_PLAYSTATE_STOPPED == state) {
19472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        this->mPosition = (SLmillisecond) 0;
19482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // this->mPositionSamples = 0;
19492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
195029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_exclusive(this);
195148913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#ifdef USE_ANDROID
195248913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    return sles_to_android_audioPlayerSetPlayState(this, state);
195348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#else
1954d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
195548913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#endif
1956d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1957d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1958d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_GetPlayState(SLPlayItf self, SLuint32 *pState)
1959d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1960d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (NULL == pState)
1961d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
196272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
196329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
196429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLuint32 state = this->mState;
196529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
196629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pState = state;
1967d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
1968d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1969d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
19702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Play_GetDuration(SLPlayItf self, SLmillisecond *pMsec)
1971d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
19722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // FIXME: for SNDFILE only, check to see if already know duration
19732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // if so, good, otherwise save position,
19742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // read quickly to end of file, counting frames,
19752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // use sample rate to compute duration, then seek back to current position
19762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pMsec)
19772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
197872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
197929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
198029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLmillisecond duration = this->mDuration;
198129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
198229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pMsec = duration;
1983d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
1984d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1985d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
19862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Play_GetPosition(SLPlayItf self, SLmillisecond *pMsec)
1987d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
19882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pMsec)
19892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
199072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
199129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
199229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLmillisecond position = this->mPosition;
199329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
199429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pMsec = position;
1995bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME convert sample units to time units
199629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME handle SL_TIME_UNKNOWN
1997d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
1998d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1999d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2000d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_RegisterCallback(SLPlayItf self, slPlayCallback callback,
2001d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    void *pContext)
2002d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
200372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
200429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME This could be a poke lock, if we had atomic double-word load/store
200529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_exclusive(this);
2006bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = callback;
2007bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = pContext;
200829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_exclusive(this);
2009d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2010d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2011d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2012d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_SetCallbackEventsMask(SLPlayItf self, SLuint32 eventFlags)
2013d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
201472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
201529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
2016bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mEventFlags = eventFlags;
201729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2018d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2019d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2020d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
20212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Play_GetCallbackEventsMask(SLPlayItf self,
20222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 *pEventFlags)
2023d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2024bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pEventFlags)
2025bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
202672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
202729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
202829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLuint32 eventFlags = this->mEventFlags;
202929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
203029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pEventFlags = eventFlags;
2031d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2032d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2033d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2034d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_SetMarkerPosition(SLPlayItf self, SLmillisecond mSec)
2035d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
203672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
203729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
2038bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mMarkerPosition = mSec;
203929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2040d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2041d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2042d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2043d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_ClearMarkerPosition(SLPlayItf self)
2044d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
204572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
204629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
2047bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mMarkerPosition = 0;
204829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2049d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2050d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2051d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2052d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_GetMarkerPosition(SLPlayItf self, SLmillisecond *pMsec)
2053d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2054bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pMsec)
2055bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
205672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
205729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
205829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLmillisecond markerPosition = this->mMarkerPosition;
205929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
206029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pMsec = markerPosition;
2061d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2062d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2063d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2064d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Play_SetPositionUpdatePeriod(SLPlayItf self, SLmillisecond mSec)
2065d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
206672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
206729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
2068bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPositionUpdatePeriod = mSec;
206929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2070d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2071d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2072d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
20732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Play_GetPositionUpdatePeriod(SLPlayItf self,
20742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillisecond *pMsec)
2075d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2076bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pMsec)
2077bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
207872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlay *this = (IPlay *) self;
207929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
208029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLmillisecond positionUpdatePeriod = this->mPositionUpdatePeriod;
208129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
208229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pMsec = positionUpdatePeriod;
2083d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2084d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2085d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2086bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLPlayItf_ Play_PlayItf = {
2087d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_SetPlayState,
2088d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_GetPlayState,
2089d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_GetDuration,
2090d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_GetPosition,
2091d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_RegisterCallback,
2092d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_SetCallbackEventsMask,
2093d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_GetCallbackEventsMask,
2094d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_SetMarkerPosition,
2095d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_ClearMarkerPosition,
2096d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_GetMarkerPosition,
2097d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_SetPositionUpdatePeriod,
2098d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Play_GetPositionUpdatePeriod
2099d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten};
2100d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2101d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* BufferQueue implementation */
2102d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2103d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult BufferQueue_Enqueue(SLBufferQueueItf self, const void *pBuffer,
2104d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 size)
2105d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
210648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    //FIXME if queue is empty and associated player is not in SL_PLAYSTATE_PLAYING state,
210748913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    // set it to SL_PLAYSTATE_PLAYING (and start playing)
2108d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (NULL == pBuffer)
2109d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
211072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
211129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLresult result;
211229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_exclusive(this);
211329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    struct BufferHeader *oldRear = this->mRear, *newRear;
211429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if ((newRear = oldRear + 1) == &this->mArray[this->mNumBuffers])
2115d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        newRear = this->mArray;
211629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    if (newRear == this->mFront) {
211729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_BUFFER_INSUFFICIENT;
211829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    } else {
211929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        oldRear->mBuffer = pBuffer;
212029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        oldRear->mSize = size;
212129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        this->mRear = newRear;
212229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        ++this->mState.count;
212329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        result = SL_RESULT_SUCCESS;
212429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
212529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_exclusive(this);
212629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    return result;
2127d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2128d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2129d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult BufferQueue_Clear(SLBufferQueueItf self)
2130d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
213172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
213229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_exclusive(this);
2133bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mFront = &this->mArray[0];
2134bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mRear = &this->mArray[0];
213529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    this->mState.count = 0;
213629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_exclusive(this);
2137d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2138d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2139d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
21402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult BufferQueue_GetState(SLBufferQueueItf self,
21412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLBufferQueueState *pState)
2142d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2143d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (NULL == pState)
2144d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
214572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
214629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLBufferQueueState state;
214729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_shared(this);
214829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
214929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    state.count = this->mState.count;
215029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    state.playIndex = this->mState.playIndex;
2151bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
215229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    state = this->mState;
215329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#endif
215429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_shared(this);
215529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
215629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    pState->count = state.count;
215729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    pState->playIndex = state.playIndex;
215829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten#else
215929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pState = state;
2160bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
2161d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2162d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2163d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2164d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult BufferQueue_RegisterCallback(SLBufferQueueItf self,
2165d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    slBufferQueueCallback callback, void *pContext)
2166d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
216772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
216829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME This could be a poke lock, if we had atomic double-word load/store
216929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_exclusive(this);
2170d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    this->mCallback = callback;
2171d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    this->mContext = pContext;
217229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_exclusive(this);
2173d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2174d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2175d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2176bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLBufferQueueItf_ BufferQueue_BufferQueueItf = {
2177d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    BufferQueue_Enqueue,
2178d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    BufferQueue_Clear,
2179d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    BufferQueue_GetState,
2180d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    BufferQueue_RegisterCallback
2181d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten};
2182d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2183d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* Volume implementation */
2184d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2185d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_SetVolumeLevel(SLVolumeItf self, SLmillibel level)
2186d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2187e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#if 0
2188e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    // some compilers allow a wider int type to be passed as a parameter,
2189e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    // but that will be truncated during the field assignment
21902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (!((SL_MILLIBEL_MIN <= level) && (SL_MILLIBEL_MAX >= level)))
2191d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2192e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#endif
219372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
219429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
2195d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    this->mLevel = level;
219629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2197d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2198d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2199d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2200d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_GetVolumeLevel(SLVolumeItf self, SLmillibel *pLevel)
2201d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
22022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pLevel)
22032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
220472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
220529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
220629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLmillibel level = this->mLevel;
220729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
220829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pLevel = level;
2209d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2210d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2211d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
22122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Volume_GetMaxVolumeLevel(SLVolumeItf self,
22132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillibel *pMaxLevel)
2214d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
22152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pMaxLevel)
22162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
22172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pMaxLevel = SL_MILLIBEL_MAX;
2218d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2219d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2220d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2221d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_SetMute(SLVolumeItf self, SLboolean mute)
2222d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
222372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
222429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
22252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mMute = mute;
222629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2227d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2228d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2229d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2230d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_GetMute(SLVolumeItf self, SLboolean *pMute)
2231d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
22322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pMute)
22332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
223472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
223529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
223629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLboolean mute = this->mMute;
223729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
223829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pMute = mute;
2239d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2240d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2241d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2242d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_EnableStereoPosition(SLVolumeItf self, SLboolean enable)
2243d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
224472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
224529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
22462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mEnableStereoPosition = enable;
224729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2248d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2249d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2250d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2251d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_IsEnabledStereoPosition(SLVolumeItf self,
2252d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLboolean *pEnable)
2253d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
22542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pEnable)
22552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
225672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
225729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
225829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLboolean enable = this->mEnableStereoPosition;
225929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
226029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pEnable = enable;
2261d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2262d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2263d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2264d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_SetStereoPosition(SLVolumeItf self,
2265d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLpermille stereoPosition)
2266d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
22672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (!((-1000 <= stereoPosition) && (1000 >= stereoPosition)))
22682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
226972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
227029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_poke(this);
22712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mStereoPosition = stereoPosition;
227229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_poke(this);
2273d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2274d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2275d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2276d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Volume_GetStereoPosition(SLVolumeItf self,
2277d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLpermille *pStereoPosition)
2278d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
22792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pStereoPosition)
22802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
228172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVolume *this = (IVolume *) self;
228229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_lock_peek(this);
228329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLpermille stereoPosition = this->mStereoPosition;
228429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    interface_unlock_peek(this);
228529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    *pStereoPosition = stereoPosition;
2286d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2287d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2288d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2289bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLVolumeItf_ Volume_VolumeItf = {
2290d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_SetVolumeLevel,
2291d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_GetVolumeLevel,
2292d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_GetMaxVolumeLevel,
2293d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_SetMute,
2294d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_GetMute,
2295d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_EnableStereoPosition,
2296d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_IsEnabledStereoPosition,
2297d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_SetStereoPosition,
2298d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Volume_GetStereoPosition
2299d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten};
2300d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2301d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* Engine implementation */
2302d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2303d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice,
2304d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 deviceID, SLuint32 numInterfaces,
23052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
2306d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2307bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pDevice || SL_DEFAULTDEVICEID_LED != deviceID)
23082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
23092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pDevice = NULL;
2310bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2311bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&LEDDevice_class, numInterfaces,
2312bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
23132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SL_RESULT_SUCCESS != result)
23142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return result;
231572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CLEDDevice *this = (CLEDDevice *)
231629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&LEDDevice_class, exposedMask, self);
23172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == this)
23182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_MEMORY_FAILURE;
2319ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLHSL *color = (SLHSL *) malloc(sizeof(SLHSL) * this->mLEDArray.mCount);
2320ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // FIXME
2321ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    assert(NULL != this->mLEDArray.mColor);
2322ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mLEDArray.mColor = color;
2323ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    unsigned i;
2324ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    for (i = 0; i < this->mLEDArray.mCount; ++i) {
2325ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        // per specification 1.0.1 pg. 259: "Default color is undefined."
2326ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        color->hue = 0;
2327ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        color->saturation = 1000;
2328ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        color->lightness = 1000;
2329ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    }
23302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mDeviceID = deviceID;
2331bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pDevice = &this->mObject.mItf;
2332d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2333d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2334d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2335d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateVibraDevice(SLEngineItf self,
2336d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLObjectItf *pDevice, SLuint32 deviceID, SLuint32 numInterfaces,
2337d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
2338d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2339bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pDevice || SL_DEFAULTDEVICEID_VIBRA != deviceID)
23402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
23412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pDevice = NULL;
2342bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2343bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&VibraDevice_class, numInterfaces,
2344bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
23452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SL_RESULT_SUCCESS != result)
23462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return result;
234772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CVibraDevice *this = (CVibraDevice *)
234829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&VibraDevice_class, exposedMask, self);
23492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == this)
23502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_MEMORY_FAILURE;
23512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mDeviceID = deviceID;
2352bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pDevice = &this->mObject.mItf;
2353d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2354d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2355d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2356d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten
2357d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer,
2358d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
2359d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
2360d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2361c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    fprintf(stderr, "entering Engine_CreateAudioPlayer()\n");
2362c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi
2363d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (NULL == pPlayer)
2364d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2365d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    *pPlayer = NULL;
2366bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2367bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&AudioPlayer_class, numInterfaces,
2368bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
23692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SL_RESULT_SUCCESS != result)
23702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return result;
2371bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // check the audio source and sinks
237248913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    result = sles_checkAudioPlayerSourceSink(pAudioSrc, pAudioSnk);
2373c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    if (result != SL_RESULT_SUCCESS) {
2374c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi        return result;
2375c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    }
2376c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    fprintf(stderr, "\t after sles_checkSourceSink()\n");
2377c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    // check the audio source and sink parameters against platform support
2378c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi#ifdef USE_ANDROID
237948913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    result = sles_to_android_checkAudioPlayerSourceSink(pAudioSrc, pAudioSnk);
2380c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    if (result != SL_RESULT_SUCCESS) {
2381c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi            return result;
2382c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    }
238348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    fprintf(stderr, "\t after sles_to_android_checkAudioPlayerSourceSink()\n");
2384c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi#endif
2385c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi
238648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#ifdef USE_SNDFILE
23872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator;
23882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat;
2389d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numBuffers = 0;
23902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLDataFormat_PCM *df_pcm = NULL;
23912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLchar *pathname = NULL;
23922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (locatorType) {
2393d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
2394d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        {
23952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLDataLocator_BufferQueue *dl_bq =
23962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            (SLDataLocator_BufferQueue *) pAudioSrc->pLocator;
23972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        numBuffers = dl_bq->numBuffers;
2398d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        if (0 == numBuffers)
2399d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
24002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        switch (formatType) {
2401d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        case SL_DATAFORMAT_PCM:
2402d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            {
24032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            df_pcm = (SLDataFormat_PCM *) pAudioSrc->pFormat;
24042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (df_pcm->numChannels) {
2405d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case 1:
2406d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case 2:
2407d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2408d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            default:
2409d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
2410d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
24112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (df_pcm->samplesPerSec) {
2412d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case 44100:
2413d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2414d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten#if 1 // wrong units for samplesPerSec!
2415d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case SL_SAMPLINGRATE_44_1:
2416d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2417d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten#endif
2418d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            // others
2419d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            default:
2420d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
2421d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
24222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (df_pcm->bitsPerSample) {
2423d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case SL_PCMSAMPLEFORMAT_FIXED_16:
2424d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2425d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            // others
2426d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            default:
2427d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
2428d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
24292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (df_pcm->containerSize) {
2430d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case 16:
2431d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2432d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            // others
2433d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            default:
2434d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
2435d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
24362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (df_pcm->channelMask) {
2437d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            // needs work
2438d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            default:
2439d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2440d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
24412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (df_pcm->endianness) {
2442d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            case SL_BYTEORDER_LITTLEENDIAN:
2443d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                break;
2444d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            // others esp. big and native (new not in spec)
2445d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            default:
2446d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
2447d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
2448d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            }
2449d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            break;
2450d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        case SL_DATAFORMAT_MIME:
2451d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        case SL_DATAFORMAT_RESERVED3:
2452d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
2453d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        default:
2454d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
2455d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
2456d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
2457d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        break;
2458d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_URI:
24592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        {
24602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator;
24612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLchar *uri = dl_uri->URI;
24622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (NULL == uri)
24632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return SL_RESULT_PARAMETER_INVALID;
24642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (strncmp((const char *) uri, "file:///", 8))
24652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
24662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        pathname = &uri[8];
24672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        switch (formatType) {
24682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        case SL_DATAFORMAT_MIME:
24692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            {
24702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            SLDataFormat_MIME *df_mime =
24712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                (SLDataFormat_MIME *) pAudioSrc->pFormat;
24722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            SLchar *mimeType = df_mime->mimeType;
24732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (NULL == mimeType)
24742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
24752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            SLuint32 containerType = df_mime->containerType;
24762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (!strcmp((const char *) mimeType, "audio/x-wav"))
24772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                ;
24782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // else if (others)
24792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            //    ;
24802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            else
24812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
24822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            switch (containerType) {
24832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            case SL_CONTAINERTYPE_WAV:
24842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                break;
24852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // others
24862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            default:
24872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
24882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            }
24892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            }
24902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            break;
24912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        default:
24922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
24932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
24942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // FIXME magic number, should be configurable
24952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        numBuffers = 2;
24962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
24972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
24982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
24992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
25002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
25012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_DATALOCATOR_RESERVED5:
25022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
25032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_DATALOCATOR_RESERVED8:
25042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_CONTENT_UNSUPPORTED;
2505d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    default:
2506d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2507d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
250848913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#endif // USE_SNDFILE
2509c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi
251048913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#ifdef USE_OUTPUTMIXEXT
251172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    struct Track *track = NULL;
2512d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    switch (*(SLuint32 *)pAudioSnk->pLocator) {
2513d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
2514d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        {
25152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // pAudioSnk->pFormat is ignored
25162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLDataLocator_OutputMix *dl_outmix =
25172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            (SLDataLocator_OutputMix *) pAudioSnk->pLocator;
25182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLObjectItf outputMix = dl_outmix->outputMix;
2519d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        // FIXME make this an operation on Object: GetClass
25202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if ((NULL == outputMix) || (&OutputMix_class !=
252172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            ((IObject *) outputMix)->mClass))
2522d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
252372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IOutputMix *om =
252472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            &((COutputMix *) outputMix)->mOutputMix;
25252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // allocate an entry within OutputMix for this track
25262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // FIXME O(n)
25272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        unsigned i;
25282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        for (i = 0, track = &om->mTracks[0]; i < 32; ++i, ++track) {
25292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (om->mActiveMask & (1 << i))
25302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                continue;
25312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            om->mActiveMask |= 1 << i;
25322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            break;
25332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
25342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (32 <= i) {
25352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // FIXME Need a better error code for all slots full in output mix
25362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return SL_RESULT_MEMORY_FAILURE;
25372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
2538bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        // FIXME replace the above for Android - do not use our own mixer!
2539d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
2540d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        break;
2541d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
2542d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_URI:
2543d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_ADDRESS:
2544d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_IODEVICE:
2545d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_RESERVED5:
2546d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
2547d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    case SL_DATALOCATOR_RESERVED8:
2548d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_CONTENT_UNSUPPORTED;
2549d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    default:
2550d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2551d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
255248913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi#endif // USE_OUTPUTMIXEXT
255348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi
255448913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    // Construct our new AudioPlayer instance
255572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CAudioPlayer *this = (CAudioPlayer *)
255629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&AudioPlayer_class, exposedMask, self);
25572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == this)
2558d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_MEMORY_FAILURE;
255948913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi
256048913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    // DataSource specific initializations
256148913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    switch(*(SLuint32 *)pAudioSrc->pLocator) {
256272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    case SL_DATALOCATOR_URI:
256372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten#ifndef USE_OUTPUTMIXEXT // e.g. USE_ANDROID
256472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        break;
256572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten#else
256672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        // fall through
256772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten#endif
256848913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    case SL_DATALOCATOR_BUFFERQUEUE:
256948913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        {
257048913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        SLDataLocator_BufferQueue *dl_bq = (SLDataLocator_BufferQueue *) pAudioSrc->pLocator;
257148913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        SLuint32 numBuffs = dl_bq->numBuffers;
257248913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        if (0 == numBuffs) {
257348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
257448913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        }
257548913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        this->mBufferQueue.mNumBuffers = numBuffs;
257648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        // inline allocation of circular mArray, up to a typical max
257748913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        if (BUFFER_HEADER_TYPICAL >= numBuffs) {
257848913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi            this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
257948913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        } else {
258048913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi            // FIXME integer overflow possible during multiplication
258148913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi            this->mBufferQueue.mArray = (struct BufferHeader *)
258248913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi                    malloc((numBuffs + 1) * sizeof(struct BufferHeader));
258348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi            if (NULL == this->mBufferQueue.mArray) {
258448913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi                free(this);
258548913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi                return SL_RESULT_MEMORY_FAILURE;
258648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi            }
258748913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        }
258848913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        this->mBufferQueue.mFront = this->mBufferQueue.mArray;
258948913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        this->mBufferQueue.mRear = this->mBufferQueue.mArray;
2590bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
259148913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        break;
259248913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    default:
259348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        // no other init required
259448913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi        break;
2595bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
259648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi
2597a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    // used to store the data source of our audio player
2598ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDynamicSource.mDataSource = pAudioSrc;
25992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SNDFILE
26002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mSndFile.mPathname = pathname;
26012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mSndFile.mIs0 = SL_BOOLEAN_TRUE;
2602bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG
2603bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mSndFile.mSNDFILE = NULL;
26042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mSndFile.mRetryBuffer = NULL;
26052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mSndFile.mRetrySize = 0;
26062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#endif
2607bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE
2608d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten#ifdef USE_OUTPUTMIXEXT
2609bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // link track to player (NOT for Android!!)
26102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    track->mDfPcm = df_pcm;
26112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    track->mBufferQueue = &this->mBufferQueue;
2612bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    track->mPlay = &this->mPlay;
2613bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // next 2 fields must be initialized explicitly (not part of this)
26142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    track->mReader = NULL;
26152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    track->mAvail = 0;
2616d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten#endif
2617d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten#ifdef USE_ANDROID
261848913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi    sles_to_android_createAudioPlayer(pAudioSrc, pAudioSnk, this);
2619d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten#endif
26202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // return the new audio player object
2621bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pPlayer = &this->mObject.mItf;
2622d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2623d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2624d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2625d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateAudioRecorder(SLEngineItf self,
2626d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLObjectItf *pRecorder, SLDataSource *pAudioSrc, SLDataSink *pAudioSnk,
2627d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
2628d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLboolean *pInterfaceRequired)
2629d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2630bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pRecorder)
2631bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2632bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pRecorder = NULL;
2633bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2634bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&AudioRecorder_class, numInterfaces,
2635bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
2636bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (SL_RESULT_SUCCESS != result)
2637bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return result;
2638d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2639d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2640d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2641d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
2642d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
2643d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
2644d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
2645d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
26462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pPlayer)
26472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
26482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pPlayer = NULL;
2649bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2650bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&MidiPlayer_class, numInterfaces,
2651bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
26522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SL_RESULT_SUCCESS != result)
26532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return result;
26542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pMIDISrc || NULL == pAudioOutput)
26552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
265672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CMidiPlayer *this = (CMidiPlayer *)
265729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&MidiPlayer_class, exposedMask, self);
26582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == this)
26592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_MEMORY_FAILURE;
26602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // return the new MIDI player object
2661bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pPlayer = &this->mObject.mItf;
2662d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2663d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2664d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2665d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
2666d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
2667d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLboolean *pInterfaceRequired)
2668d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2669bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pListener)
2670bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2671bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pListener = NULL;
2672bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2673bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&Listener_class, numInterfaces,
2674bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
2675bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (SL_RESULT_SUCCESS != result)
2676bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return result;
2677bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_FEATURE_UNSUPPORTED;
2678d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2679d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2680d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup,
2681d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
2682d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLboolean *pInterfaceRequired)
2683d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2684bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pGroup)
2685bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2686bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pGroup = NULL;
2687bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2688bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&_3DGroup_class, numInterfaces,
2689bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
2690bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (SL_RESULT_SUCCESS != result)
2691bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return result;
2692bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_FEATURE_UNSUPPORTED;
2693d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2694d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2695d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix,
2696d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
2697d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLboolean *pInterfaceRequired)
2698d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2699d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (NULL == pMix)
2700d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2701bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pMix = NULL;
2702bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2703bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&OutputMix_class, numInterfaces,
2704bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
2705d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (SL_RESULT_SUCCESS != result)
2706d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return result;
270772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    COutputMix *this = (COutputMix *)
270829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&OutputMix_class, exposedMask, self);
2709bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == this)
2710d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_MEMORY_FAILURE;
2711bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pMix = &this->mObject.mItf;
2712d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2713d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2714d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2715d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateMetadataExtractor(SLEngineItf self,
2716d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLObjectItf *pMetadataExtractor, SLDataSource *pDataSource,
2717d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
2718d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLboolean *pInterfaceRequired)
2719d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2720bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pMetadataExtractor)
2721bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2722bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pMetadataExtractor = NULL;
2723bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
2724bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&MetadataExtractor_class, numInterfaces,
2725bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
2726bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (SL_RESULT_SUCCESS != result)
2727bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return result;
272872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CMetadataExtractor *this = (CMetadataExtractor *)
272929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&MetadataExtractor_class, exposedMask, self);
2730bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == this)
2731bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_MEMORY_FAILURE;
2732bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pMetadataExtractor = &this->mObject.mItf;
2733d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2734d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2735d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2736d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_CreateExtensionObject(SLEngineItf self,
2737d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLObjectItf *pObject, void *pParameters, SLuint32 objectID,
2738d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
2739d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLboolean *pInterfaceRequired)
2740d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2741bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pObject)
2742bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2743bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pObject = NULL;
2744bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_FEATURE_UNSUPPORTED;
2745d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2746d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2747d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_QueryNumSupportedInterfaces(SLEngineItf self,
2748d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
2749d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2750bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pNumSupportedInterfaces)
2751bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
275272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = objectIDtoClass(objectID);
2753bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == class__)
2754bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_FEATURE_UNSUPPORTED;
2755bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pNumSupportedInterfaces = class__->mInterfaceCount;
2756d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2757d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2758d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2759bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Engine_QuerySupportedInterfaces(SLEngineItf self,
2760d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
2761d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2762e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pInterfaceId)
2763e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
276472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    const ClassTable *class__ = objectIDtoClass(objectID);
2765e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == class__)
2766e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_FEATURE_UNSUPPORTED;
2767e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (index >= class__->mInterfaceCount)
2768e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2769e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    *pInterfaceId = &SL_IID_array[class__->mInterfaces[index].mMPH];
2770d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2771e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten};
2772d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2773d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_QueryNumSupportedExtensions(SLEngineItf self,
2774d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 *pNumExtensions)
2775d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2776bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pNumExtensions)
2777bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2778bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pNumExtensions = 0;
2779d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2780d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2781d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2782d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_QuerySupportedExtension(SLEngineItf self,
2783d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
2784d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2785bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // any index >= 0 will be >= number of supported extensions
2786bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_PARAMETER_INVALID;
2787d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2788d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2789d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kastenstatic SLresult Engine_IsExtensionSupported(SLEngineItf self,
2790d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    const SLchar *pExtensionName, SLboolean *pSupported)
2791d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
2792bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pExtensionName || NULL == pSupported)
2793bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2794bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pSupported = SL_BOOLEAN_FALSE;
2795d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2796d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2797d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2798bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLEngineItf_ Engine_EngineItf = {
2799d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateLEDDevice,
2800d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateVibraDevice,
2801d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateAudioPlayer,
2802d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateAudioRecorder,
2803d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateMidiPlayer,
2804d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateListener,
2805d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_Create3DGroup,
2806d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateOutputMix,
2807d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateMetadataExtractor,
2808d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_CreateExtensionObject,
2809d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_QueryNumSupportedInterfaces,
2810d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_QuerySupportedInterfaces,
2811d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_QueryNumSupportedExtensions,
2812d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_QuerySupportedExtension,
2813d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    Engine_IsExtensionSupported
2814d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten};
2815d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
28162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* AudioIODeviceCapabilities implementation */
2817d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
28182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_GetAvailableAudioInputs(
28192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLint32 *pNumInputs,
28202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 *pInputDeviceIDs)
2821d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
28227754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pNumInputs)
28237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
28247754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL != pInputDeviceIDs) {
28257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        // FIXME should be OEM-configurable
28267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        if (1 > *pNumInputs)
28277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            return SL_RESULT_BUFFER_INSUFFICIENT;
28287754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        pInputDeviceIDs[0] = SL_DEFAULTDEVICEID_AUDIOINPUT;
28297754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
28307754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pNumInputs = 1;
28312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
28322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
28332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
28342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_QueryAudioInputCapabilities(
28352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
28362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioInputDescriptor *pDescriptor)
28372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
28387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pDescriptor)
28397754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
28407754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    switch (deviceID) {
28417754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // FIXME should be OEM-configurable
28427754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOINPUT:
28437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        *pDescriptor = AudioInputDescriptor_mic;
28447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
28457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    default:
28467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_IO_ERROR;
28477754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
28482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
28492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
28502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
28512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult
28522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_RegisterAvailableAudioInputsChangedCallback(
28532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self,
28542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    slAvailableAudioInputsChangedCallback callback, void *pContext)
28552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
285672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioIODeviceCapabilities * this =
285772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioIODeviceCapabilities *) self;
28587754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
28597754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioInputsChangedCallback = callback;
28607754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioInputsChangedContext = pContext;
28617754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
28622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
28632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
28642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
28652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_GetAvailableAudioOutputs(
28662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLint32 *pNumOutputs,
28672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 *pOutputDeviceIDs)
28682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
28692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pNumOutputs)
2870d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
28712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pOutputDeviceIDs) {
28722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // FIXME should be OEM-configurable
28732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (2 > *pNumOutputs)
28742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            return SL_RESULT_BUFFER_INSUFFICIENT;
28752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        pOutputDeviceIDs[0] = DEVICE_ID_HEADSET;
28762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        pOutputDeviceIDs[1] = DEVICE_ID_HANDSFREE;
28772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
28782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pNumOutputs = 2;
28792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
28802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
28812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
28822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_QueryAudioOutputCapabilities(
28832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
28842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioOutputDescriptor *pDescriptor)
28852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
28862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pDescriptor)
2887d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
28882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (deviceID) {
28892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // FIXME should be OEM-configurable
28902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case DEVICE_ID_HEADSET:
28912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        *pDescriptor = AudioOutputDescriptor_headset;
28922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
28932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case DEVICE_ID_HANDSFREE:
28942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        *pDescriptor = AudioOutputDescriptor_handsfree;
28952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
28962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
28972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_IO_ERROR;
2898d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
2899d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
2900d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
2901d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
29022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult
29032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_RegisterAvailableAudioOutputsChangedCallback(
29042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self,
29052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    slAvailableAudioOutputsChangedCallback callback, void *pContext)
2906d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
290772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioIODeviceCapabilities * this =
290872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioIODeviceCapabilities *) self;
29097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
29107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioOutputsChangedCallback = callback;
29117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAvailableAudioOutputsChangedContext = pContext;
29127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
29132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
29142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
29152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
2916bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult
2917bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    AudioIODeviceCapabilities_RegisterDefaultDeviceIDMapChangedCallback(
29182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self,
29192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    slDefaultDeviceIDMapChangedCallback callback, void *pContext)
29202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
292172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioIODeviceCapabilities * this =
292272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioIODeviceCapabilities *) self;
29237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
29247754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mDefaultDeviceIDMapChangedCallback = callback;
29257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mDefaultDeviceIDMapChangedContext = pContext;
29267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
29272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
29282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
29292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
29302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_GetAssociatedAudioInputs(
29312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
29322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLint32 *pNumAudioInputs, SLuint32 *pAudioInputDeviceIDs)
29332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
29347754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pNumAudioInputs)
29357754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
29367754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pNumAudioInputs = 0;
29372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
29382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
29392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
29402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_GetAssociatedAudioOutputs(
29412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
29422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLint32 *pNumAudioOutputs, SLuint32 *pAudioOutputDeviceIDs)
29432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
29447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pNumAudioOutputs)
29457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
29467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pNumAudioOutputs = 0;
29472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
29482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
29492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
29502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_GetDefaultAudioDevices(
29512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLuint32 defaultDeviceID,
29522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLint32 *pNumAudioDevices, SLuint32 *pAudioDeviceIDs)
29532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
29547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pNumAudioDevices)
29557754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
29567754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    switch (defaultDeviceID) {
29577754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOINPUT:
29587754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
29597754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
29607754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    default:
29617754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_IO_ERROR;
29627754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
29637754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL != pAudioDeviceIDs) {
29647754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        // FIXME should be OEM-configurable
29657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        if (2 > *pNumAudioDevices)
29667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            return SL_RESULT_BUFFER_INSUFFICIENT;
29677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        pAudioDeviceIDs[0] = DEVICE_ID_HEADSET;
29687754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        pAudioDeviceIDs[1] = DEVICE_ID_HANDSFREE;
29697754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
29707754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pNumAudioDevices = 1;
29712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
29722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
29732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
29742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioIODeviceCapabilities_QuerySampleFormatsSupported(
29752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
29762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmilliHertz samplingRate, SLint32 *pSampleFormats,
29772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLint32 *pNumOfSampleFormats)
29782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
29797754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pNumOfSampleFormats)
29807754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
29817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    switch (deviceID) {
29827754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOINPUT:
29837754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
29847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
29857754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    default:
29867754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_IO_ERROR;
29877754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
29887754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    switch (samplingRate) {
29897754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_SAMPLINGRATE_44_1:
29907754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
29917754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    default:
29927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_IO_ERROR;
29937754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
29947754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL != pSampleFormats) {
29957754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        if (1 > *pNumOfSampleFormats)
29967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            return SL_RESULT_BUFFER_INSUFFICIENT;
29977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        pSampleFormats[0] = SL_PCMSAMPLEFORMAT_FIXED_16;
29987754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
29997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pNumOfSampleFormats = 1;
30002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
30012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
30022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3003bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLAudioIODeviceCapabilitiesItf_
30042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_AudioIODeviceCapabilitiesItf = {
30052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_GetAvailableAudioInputs,
30062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_QueryAudioInputCapabilities,
30072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_RegisterAvailableAudioInputsChangedCallback,
30082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_GetAvailableAudioOutputs,
30092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_QueryAudioOutputCapabilities,
30102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_RegisterAvailableAudioOutputsChangedCallback,
30112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_RegisterDefaultDeviceIDMapChangedCallback,
30122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_GetAssociatedAudioInputs,
30132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_GetAssociatedAudioOutputs,
30142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_GetDefaultAudioDevices,
30152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioIODeviceCapabilities_QuerySampleFormatsSupported
30162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
30172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
30182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* OutputMix implementation */
30192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
30202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult OutputMix_GetDestinationOutputDeviceIDs(SLOutputMixItf self,
30212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten   SLint32 *pNumDevices, SLuint32 *pDeviceIDs)
30222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
30237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pNumDevices)
30247754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
30257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL != pDeviceIDs) {
30267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        if (1 > *pNumDevices)
30277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            return SL_RESULT_BUFFER_INSUFFICIENT;
30287754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        pDeviceIDs[0] = SL_DEFAULTDEVICEID_AUDIOOUTPUT;
30297754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
30307754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pNumDevices = 1;
30312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
30322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
30332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
30342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult OutputMix_RegisterDeviceChangeCallback(SLOutputMixItf self,
30352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    slMixDeviceChangeCallback callback, void *pContext)
30362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
303772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IOutputMix *this = (IOutputMix *) self;
30387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
30397754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mCallback = callback;
30407754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mContext = pContext;
30417754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
30422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
30432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
30442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
30452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult OutputMix_ReRoute(SLOutputMixItf self, SLint32 numOutputDevices,
30462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 *pOutputDeviceIDs)
30472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
30487754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (1 > numOutputDevices)
30497754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
30507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    if (NULL == pOutputDeviceIDs)
30517754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
30527754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    switch (pOutputDeviceIDs[0]) {
30537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
30547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case DEVICE_ID_HEADSET:
30557754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    case DEVICE_ID_HANDSFREE:
30567754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
30577754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    default:
30587754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
30597754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
30602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
30612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
30622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3063bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLOutputMixItf_ OutputMix_OutputMixItf = {
30642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    OutputMix_GetDestinationOutputDeviceIDs,
30652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    OutputMix_RegisterDeviceChangeCallback,
30662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    OutputMix_ReRoute
30672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
30682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
30692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* Seek implementation */
30702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
30712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Seek_SetPosition(SLSeekItf self, SLmillisecond pos,
30722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 seekMode)
30732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
30742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (seekMode) {
30752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_SEEKMODE_FAST:
30762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_SEEKMODE_ACCURATE:
30772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
30782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
3079d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
30802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
308172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ISeek *this = (ISeek *) self;
30827754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
30832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mPos = pos;
30847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
30852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
3086d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
3087d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
30882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Seek_SetLoop(SLSeekItf self, SLboolean loopEnable,
30892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillisecond startPos, SLmillisecond endPos)
3090d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
309172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ISeek *this = (ISeek *) self;
30927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
30932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mLoopEnabled = loopEnable;
30942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mStartPos = startPos;
30952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    this->mEndPos = endPos;
30967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
30972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
30982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
30992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
31002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult Seek_GetLoop(SLSeekItf self, SLboolean *pLoopEnabled,
31012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillisecond *pStartPos, SLmillisecond *pEndPos)
31022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
31032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pLoopEnabled || NULL == pStartPos || NULL == pEndPos)
3104d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
310572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ISeek *this = (ISeek *) self;
31067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_shared(this);
31077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLboolean loopEnabled = this->mLoopEnabled;
31087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLmillisecond startPos = this->mStartPos;
31097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLmillisecond endPos = this->mEndPos;
31107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_shared(this);
31117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pLoopEnabled = loopEnabled;
31127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pStartPos = startPos;
31137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pEndPos = endPos;
31142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
3115d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
3116d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
3117bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLSeekItf_ Seek_SeekItf = {
31182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Seek_SetPosition,
31192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Seek_SetLoop,
31202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    Seek_GetLoop
31212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
3122d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
31232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* 3DCommit implementation */
3124d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
31252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DCommit_Commit(SL3DCommitItf self)
3126d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
312772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DCommit *this = (I3DCommit *) self;
312872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject = this->mThis;
312932918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    object_lock_exclusive(thisObject);
313032918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    if (this->mDeferred) {
313132918086b694fc383c8c2d590ac45492801676f7Glenn Kasten        SLuint32 myGeneration = this->mGeneration;
313232918086b694fc383c8c2d590ac45492801676f7Glenn Kasten        do
313332918086b694fc383c8c2d590ac45492801676f7Glenn Kasten            object_cond_wait(thisObject);
313432918086b694fc383c8c2d590ac45492801676f7Glenn Kasten        while (this->mGeneration == myGeneration);
313532918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    }
313632918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    object_unlock_exclusive(thisObject);
31372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
31382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
3139d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
31402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DCommit_SetDeferred(SL3DCommitItf self, SLboolean deferred)
31412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
314272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DCommit *this = (I3DCommit *) self;
314372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject = this->mThis;
314432918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    object_lock_exclusive(thisObject);
3145bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mDeferred = deferred;
314632918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    object_unlock_exclusive(thisObject);
31472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
3148d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
3149d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
3150bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SL3DCommitItf_ _3DCommit_3DCommitItf = {
31512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DCommit_Commit,
31522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DCommit_SetDeferred
31532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
31542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
31552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* 3DDoppler implementation */
31562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3157bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DDoppler_SetVelocityCartesian(SL3DDopplerItf self,
31582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLVec3D *pVelocity)
3159d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
3160bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pVelocity)
3161bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
316272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DDoppler *this = (I3DDoppler *) self;
31637754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D velocityCartesian = *pVelocity;
316432918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_lock_exclusive(this);
31657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityCartesian = velocityCartesian;
31667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
316732918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_unlock_exclusive(this);
31682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
31692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
3170d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
3171bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DDoppler_SetVelocitySpherical(SL3DDopplerItf self,
31722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillidegree azimuth, SLmillidegree elevation, SLmillimeter speed)
31732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
317472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DDoppler *this = (I3DDoppler *) self;
317532918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_lock_exclusive(this);
31767754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocitySpherical.mAzimuth = azimuth;
31777754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocitySpherical.mElevation = elevation;
31787754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocitySpherical.mSpeed = speed;
31797754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mVelocityActive = CARTESIAN_UNKNOWN_SPHERICAL_SET;
318032918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_unlock_exclusive(this);
31812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
31822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
3183d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
3184bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DDoppler_GetVelocityCartesian(SL3DDopplerItf self,
31852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLVec3D *pVelocity)
31862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3187bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pVelocity)
3188bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
318972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DDoppler *this = (I3DDoppler *) self;
31907754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
319132918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    for (;;) {
31927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        enum CartesianSphericalActive velocityActive = this->mVelocityActive;
31937754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        switch (velocityActive) {
31947754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_COMPUTED_SPHERICAL_SET:
31957754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_COMPUTED:  // not in 1.0.1
31967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
31977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_UNKNOWN:
31987754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            {
31997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            SLVec3D velocityCartesian = this->mVelocityCartesian;
32007754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_unlock_exclusive(this);
32017754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            *pVelocity = velocityCartesian;
32027754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            }
32037754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
32047754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_UNKNOWN_SPHERICAL_SET:
32057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mVelocityActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
32067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // fall through
32077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_REQUESTED_SPHERICAL_SET:
32087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // matched by cond_broadcast in case multiple requesters
32097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_cond_wait(this);
32107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            continue;
32117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        default:
32127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            assert(SL_BOOLEAN_FALSE);
32137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_unlock_exclusive(this);
32147754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pVelocity->x = 0;
32157754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pVelocity->y = 0;
32167754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pVelocity->z = 0;
321732918086b694fc383c8c2d590ac45492801676f7Glenn Kasten            break;
32187754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        }
321932918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    }
32202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
32212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
32222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3223bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DDoppler_SetDopplerFactor(SL3DDopplerItf self,
32242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLpermille dopplerFactor)
32252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
322672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DDoppler *this = (I3DDoppler *) self;
322732918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_lock_poke(this);
3228bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mDopplerFactor = dopplerFactor;
322932918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_unlock_poke(this);
32302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
32312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
32322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3233bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DDoppler_GetDopplerFactor(SL3DDopplerItf self,
3234bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pDopplerFactor)
32352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3236bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pDopplerFactor)
3237bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
323872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DDoppler *this = (I3DDoppler *) self;
323932918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_lock_peek(this);
324032918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    SLpermille dopplerFactor = this->mDopplerFactor;
324132918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_unlock_peek(this);
324232918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    *pDopplerFactor = dopplerFactor;
32432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
32442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
32452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3246bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SL3DDopplerItf_ _3DDoppler_3DDopplerItf = {
3247bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DDoppler_SetVelocityCartesian,
3248bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DDoppler_SetVelocitySpherical,
3249bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DDoppler_GetVelocityCartesian,
3250bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DDoppler_SetDopplerFactor,
3251bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DDoppler_GetDopplerFactor
32522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
32532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
32542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* 3DLocation implementation */
32552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
32562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_SetLocationCartesian(SL3DLocationItf self,
32572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLVec3D *pLocation)
32582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3259bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pLocation)
3260bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
326172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
32627754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D locationCartesian = *pLocation;
32637754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
32647754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationCartesian = locationCartesian;
32657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
32667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
32672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
32682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
32692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
32702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_SetLocationSpherical(SL3DLocationItf self,
32712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillidegree azimuth, SLmillidegree elevation, SLmillimeter distance)
32722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
327372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
32747754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
32757754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationSpherical.mAzimuth = azimuth;
32767754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationSpherical.mElevation = elevation;
32777754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationSpherical.mDistance = distance;
32787754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mLocationActive = CARTESIAN_UNKNOWN_SPHERICAL_SET;
32797754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
32802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
3281d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
32822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
32832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_Move(SL3DLocationItf self, const SLVec3D *pMovement)
32842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3285bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pMovement)
3286bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
328772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
32887754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D movementCartesian = *pMovement;
32897754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
32907754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    for (;;) {
32917754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        enum CartesianSphericalActive locationActive = this->mLocationActive;
32927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        switch (locationActive) {
32937754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_COMPUTED_SPHERICAL_SET:
32947754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_COMPUTED:  // not in 1.0.1
32957754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
32967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_UNKNOWN:
32977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mLocationCartesian.x += movementCartesian.x;
32987754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mLocationCartesian.y += movementCartesian.y;
32997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mLocationCartesian.z += movementCartesian.z;
33007754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
33017754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
33027754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_UNKNOWN_SPHERICAL_SET:
33037754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mLocationActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
33047754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // fall through
33057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_REQUESTED_SPHERICAL_SET:
33067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // matched by cond_broadcast in case multiple requesters
33077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_cond_wait(this);
33087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            continue;
33097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        default:
33107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            assert(SL_BOOLEAN_FALSE);
33117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
33127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        }
33137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
33147754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
33157754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
33162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
33172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
33182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
33192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_GetLocationCartesian(SL3DLocationItf self,
33202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLVec3D *pLocation)
33212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3322bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pLocation)
3323bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
332472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
33257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
33267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    for (;;) {
33277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        enum CartesianSphericalActive locationActive = this->mLocationActive;
33287754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        switch (locationActive) {
33297754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_COMPUTED_SPHERICAL_SET:
33307754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_COMPUTED:  // not in 1.0.1
33317754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
33327754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_SET_SPHERICAL_UNKNOWN:
33337754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            {
33347754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            SLVec3D locationCartesian = this->mLocationCartesian;
33357754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_unlock_exclusive(this);
33367754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            *pLocation = locationCartesian;
33377754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            }
33387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
33397754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_UNKNOWN_SPHERICAL_SET:
33407754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mLocationActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
33417754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // fall through
33427754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case CARTESIAN_REQUESTED_SPHERICAL_SET:
33437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // matched by cond_broadcast in case multiple requesters
33447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_cond_wait(this);
33457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            continue;
33467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        default:
33477754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            assert(SL_BOOLEAN_FALSE);
33487754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_unlock_exclusive(this);
33497754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pLocation->x = 0;
33507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pLocation->y = 0;
33517754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pLocation->z = 0;
33527754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
33537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        }
33547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
33552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
33562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
33572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
33582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_SetOrientationVectors(SL3DLocationItf self,
33592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLVec3D *pFront, const SLVec3D *pAbove)
33602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3361bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pFront || NULL == pAbove)
3362bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
33637754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D front = *pFront;
33647754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D above = *pAbove;
336572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
33667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
33677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mFront = front;
33687754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationVectors.mAbove = above;
33697754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationActive = ANGLES_UNKNOWN_VECTORS_SET;
33707754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_FALSE;
33717754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
33722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
33732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
33742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
33752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_SetOrientationAngles(SL3DLocationItf self,
33762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillidegree heading, SLmillidegree pitch, SLmillidegree roll)
33772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
337872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
33797754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
33807754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mHeading = heading;
33817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mPitch = pitch;
33827754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationAngles.mRoll = roll;
33837754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
33847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_FALSE;
33857754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
33862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
33872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
33882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
33892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_Rotate(SL3DLocationItf self, SLmillidegree theta,
33902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLVec3D *pAxis)
33912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3392bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pAxis)
3393bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
33947754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D axis = *pAxis;
339572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
33967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
33977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    while (this->mRotatePending)
33987754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        interface_cond_wait(this);
33997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mTheta = theta;
34007754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis = axis;
34017754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_TRUE;
34027754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
34032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
34042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
34052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
34062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult _3DLocation_GetOrientationVectors(SL3DLocationItf self,
34072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLVec3D *pFront, SLVec3D *pUp)
34082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3409bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pFront || NULL == pUp)
3410bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
341172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DLocation *this = (I3DLocation *) self;
34127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_shared(this);
34137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D front = this->mOrientationVectors.mFront;
34147754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLVec3D up = this->mOrientationVectors.mUp;
34157754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_shared(this);
34167754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pFront = front;
34177754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pUp = up;
34182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
34192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
34202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3421bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SL3DLocationItf_ _3DLocation_3DLocationItf = {
34222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_SetLocationCartesian,
34232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_SetLocationSpherical,
34242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_Move,
34252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_GetLocationCartesian,
34262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_SetOrientationVectors,
34272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_SetOrientationAngles,
34282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_Rotate,
34292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    _3DLocation_GetOrientationVectors
34302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
34312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
34322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* AudioDecoderCapabilities implementation */
34332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3434e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten// These are not in 1.0.1 header file
3435e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define SL_AUDIOCODEC_NULL   0
3436e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define SL_AUDIOCODEC_VORBIS 9
3437e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten
34382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten// FIXME should build this table from Caps table below
3439e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenstatic const SLuint32 Decoder_IDs[] = {
34402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_PCM,
34412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_MP3,
34422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_AMR,
34432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_AMRWB,
34442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_AMRWBPLUS,
34452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_AAC,
34462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_WMA,
34472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_REAL,
34482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOCODEC_VORBIS
34492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
3450e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define MAX_DECODERS (sizeof(Decoder_IDs) / sizeof(Decoder_IDs[0]))
34512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3452e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten// For now, but encoders might be different than decoders later
3453e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define Encoder_IDs Decoder_IDs
3454e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten#define MAX_ENCODERS (sizeof(Encoder_IDs) / sizeof(Encoder_IDs[0]))
34552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3456e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenstatic const SLmilliHertz SamplingRates_A[] = {
34572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_8,
34582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_11_025,
34592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_12,
34602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_16,
34612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_22_05,
34622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_24,
34632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_32,
34642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_44_1,
34652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_48
34662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
34672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3468e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenstatic const SLAudioCodecDescriptor CodecDescriptor_A = {
34692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    2,                   // maxChannels
34702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    8,                   // minBitsPerSample
34712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    16,                  // maxBitsPerSample
34722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_8,   // minSampleRate
34732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_SAMPLINGRATE_48,  // maxSampleRate
34742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_BOOLEAN_FALSE,    // isFreqRangeContinuous
3475e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    (SLmilliHertz *) SamplingRates_A,
34762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                         // pSampleRatesSupported;
3477e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    sizeof(SamplingRates_A) / sizeof(SamplingRates_A[0]),
34782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                         // numSampleRatesSupported
34792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    1,                   // minBitRate
34802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    ~0,                  // maxBitRate
34812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_BOOLEAN_TRUE,     // isBitrateRangeContinuous
34822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    NULL,                // pBitratesSupported
34832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    0,                   // numBitratesSupported
34842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SL_AUDIOPROFILE_PCM, // profileSetting
34852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    0                    // modeSetting
34862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
34872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3488e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenstatic const struct CodecDescriptor {
3489e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLuint32 mCodecID;
3490e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    const SLAudioCodecDescriptor *mDescriptor;
3491e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten} DecoderDescriptors[] = {
3492e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    {SL_AUDIOCODEC_PCM, &CodecDescriptor_A},
3493e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    {SL_AUDIOCODEC_NULL, NULL}
3494e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten}, EncoderDescriptors[] = {
3495e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    {SL_AUDIOCODEC_PCM, &CodecDescriptor_A},
3496e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    {SL_AUDIOCODEC_NULL, NULL}
34972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
34982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3499e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenstatic SLresult AudioDecoderCapabilities_GetAudioDecoders(
3500e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLAudioDecoderCapabilitiesItf self, SLuint32 *pNumDecoders,
3501e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLuint32 *pDecoderIds)
3502e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten{
3503e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pNumDecoders)
3504e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
3505e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pDecoderIds) {
3506e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        *pNumDecoders = MAX_DECODERS;
3507e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    } else {
3508e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        SLuint32 numDecoders = *pNumDecoders;
3509e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        if (MAX_DECODERS <= numDecoders)
3510e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            *pNumDecoders = numDecoders = MAX_DECODERS;
3511e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        memcpy(pDecoderIds, Decoder_IDs, numDecoders * sizeof(SLuint32));
3512e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    }
3513e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    return SL_RESULT_SUCCESS;
3514e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten}
3515e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten
3516e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten// private helper shared by decoder and encoder
3517e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kastenstatic SLresult GetCodecCapabilities(SLuint32 decoderId, SLuint32 *pIndex,
3518e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLAudioCodecDescriptor *pDescriptor,
3519e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    const struct CodecDescriptor *codecDescriptors)
3520e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten{
3521e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pIndex)
3522e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
3523e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    const struct CodecDescriptor *cd = codecDescriptors;
3524e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLuint32 index;
3525e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pDescriptor) {
3526e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        for (index = 0 ; NULL != cd->mDescriptor; ++cd)
3527e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            if (cd->mCodecID == decoderId)
3528e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten                ++index;
3529e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        *pIndex = index;
3530e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_SUCCESS;
3531e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    }
3532e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    index = *pIndex;
3533e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    for ( ; NULL != cd->mDescriptor; ++cd) {
3534e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        if (cd->mCodecID == decoderId) {
3535e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            if (0 == index) {
3536e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten                *pDescriptor = *cd->mDescriptor;
3537e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten                return SL_RESULT_SUCCESS;
3538e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            }
3539e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            --index;
3540e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        }
3541e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    }
3542e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    return SL_RESULT_PARAMETER_INVALID;
3543e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten}
3544e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten
35452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioDecoderCapabilities_GetAudioDecoderCapabilities(
35462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioDecoderCapabilitiesItf self, SLuint32 decoderId, SLuint32 *pIndex,
35472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioCodecDescriptor *pDescriptor)
35482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3549e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    return GetCodecCapabilities(decoderId, pIndex, pDescriptor,
3550e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        DecoderDescriptors);
35512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
35522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3553bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLAudioDecoderCapabilitiesItf_
35542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioDecoderCapabilities_AudioDecoderCapabilitiesItf = {
35552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioDecoderCapabilities_GetAudioDecoders,
35562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioDecoderCapabilities_GetAudioDecoderCapabilities
35572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
35582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
35592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* AudioEncoder implementation */
35602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
35612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioEncoder_SetEncoderSettings(SLAudioEncoderItf self,
35622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioEncoderSettings  *pSettings)
35632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3564bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pSettings)
3565bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
356672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioEncoder *this =
356772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioEncoder *) self;
3568e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLAudioEncoderSettings settings = *pSettings;
3569e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_exclusive(this);
3570e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mSettings = settings;
3571e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_exclusive(this);
35722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
35732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
35742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
35752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioEncoder_GetEncoderSettings(SLAudioEncoderItf self,
35762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioEncoderSettings *pSettings)
35772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3578bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pSettings)
3579bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
358072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IAudioEncoder *this =
358172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IAudioEncoder *) self;
3582e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_shared(this);
3583e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLAudioEncoderSettings settings = this->mSettings;
3584e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_shared(this);
3585e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    *pSettings = settings;
35862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
35872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
35882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3589bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLAudioEncoderItf_ AudioEncoder_AudioEncoderItf = {
35902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioEncoder_SetEncoderSettings,
35912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioEncoder_GetEncoderSettings
35922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
35932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
35942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* AudioEncoderCapabilities implementation */
35952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
35962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioEncoderCapabilities_GetAudioEncoders(
3597bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLAudioEncoderCapabilitiesItf self, SLuint32 *pNumEncoders,
3598bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pEncoderIds)
35992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3600e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pNumEncoders)
3601e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
3602e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pEncoderIds) {
3603e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        *pNumEncoders = MAX_ENCODERS;
3604e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    } else {
3605e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        SLuint32 numEncoders = *pNumEncoders;
3606e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        if (MAX_ENCODERS <= numEncoders)
3607e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            *pNumEncoders = numEncoders = MAX_ENCODERS;
3608e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        memcpy(pEncoderIds, Encoder_IDs, numEncoders * sizeof(SLuint32));
3609e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    }
36102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
36112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
36122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult AudioEncoderCapabilities_GetAudioEncoderCapabilities(
36142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioEncoderCapabilitiesItf self, SLuint32 encoderId, SLuint32 *pIndex,
36152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLAudioCodecDescriptor *pDescriptor)
36162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3617e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    return GetCodecCapabilities(encoderId, pIndex, pDescriptor,
3618e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        EncoderDescriptors);
36192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
36202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3621bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLAudioEncoderCapabilitiesItf_
36222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioEncoderCapabilities_AudioEncoderCapabilitiesItf = {
36232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioEncoderCapabilities_GetAudioEncoders,
36242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    AudioEncoderCapabilities_GetAudioEncoderCapabilities
36252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
36262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* DeviceVolume implementation */
36282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult DeviceVolume_GetVolumeScale(SLDeviceVolumeItf self,
36302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 deviceID, SLint32 *pMinValue, SLint32 *pMaxValue,
36312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLboolean *pIsMillibelScale)
36322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
36332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pMinValue)
36342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        *pMinValue = 0;
36352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pMaxValue)
36362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        *pMaxValue = 10;
36372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pIsMillibelScale)
36382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        *pIsMillibelScale = SL_BOOLEAN_FALSE;
36392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
36402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
36412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult DeviceVolume_SetVolume(SLDeviceVolumeItf self,
36432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 deviceID, SLint32 volume)
36442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
364583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    switch (deviceID) {
364683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOINPUT:
364783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
364883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        break;
364983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    default:
365083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
365183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    }
365272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDeviceVolume *this =
365372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDeviceVolume *) self;
36547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
365583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    this->mVolume[~deviceID] = volume;
36567754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
36572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
36582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
36592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult DeviceVolume_GetVolume(SLDeviceVolumeItf self,
36612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 deviceID, SLint32 *pVolume)
36622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3663bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pVolume)
3664bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
366583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    switch (deviceID) {
366683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOINPUT:
366783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
366883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        break;
366983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    default:
367083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
367183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    }
367272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDeviceVolume *this =
367372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IDeviceVolume *) self;
36747754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
367583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLint32 volume = this->mVolume[~deviceID];
36767754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
367783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pVolume = volume;
36782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
36792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
36802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3681bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLDeviceVolumeItf_ DeviceVolume_DeviceVolumeItf = {
36822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    DeviceVolume_GetVolumeScale,
36832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    DeviceVolume_SetVolume,
36842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    DeviceVolume_GetVolume
36852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
36862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* DynamicSource implementation */
36882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
36892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult DynamicSource_SetSource(SLDynamicSourceItf self,
36902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLDataSource *pDataSource)
36912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
3692ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pDataSource)
3693ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
369472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IDynamicSource *this = (IDynamicSource *) self;
3695ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // need to lock the object, as a change to source can impact most of object
369672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisObject = this->mThis;
3697ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    object_lock_exclusive(thisObject);
3698ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // FIXME a bit of a simplification to say the least!
3699ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDataSource = pDataSource;
3700ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    object_unlock_exclusive(thisObject);
37012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
37022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
37032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3704bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLDynamicSourceItf_ DynamicSource_DynamicSourceItf = {
37052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    DynamicSource_SetSource
37062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
37072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
37082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* EffectSend implementation */
37092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
371072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic struct EnableLevel *getEnableLevel(IEffectSend *this,
371183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    const void *pAuxEffect)
371283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten{
371372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    COutputMix *outputMix = this->mOutputMix;
371483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    // Make sure the sink for this player is an output mix
371583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten#if 0 // not necessary
371683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == outputMix)
371783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return NULL;
371883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten#endif
371983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (pAuxEffect == &outputMix->mEnvironmentalReverb)
372083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return &this->mEnableLevels[AUX_ENVIRONMENTALREVERB];
372183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (pAuxEffect == &outputMix->mPresetReverb)
372283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return &this->mEnableLevels[AUX_PRESETREVERB];
372383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    return NULL;
372483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten#if 0 // App couldn't have an interface for effect without exposure
372583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    unsigned interfaceMask = 1 << MPH_to_OutputMix[AUX_to_MPH[aux]];
372683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (outputMix->mExposedMask & interfaceMask)
372783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
372883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten#endif
372983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten}
373083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten
37312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EffectSend_EnableEffectSend(SLEffectSendItf self,
37322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel)
37332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
373472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
373583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
373683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == enableLevel)
373783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
373883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    interface_lock_exclusive(this);
373983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    enableLevel->mEnable = enable;
374083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    enableLevel->mSendLevel = initialLevel;
374183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    interface_unlock_exclusive(this);
37422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
37432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
37442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
37452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EffectSend_IsEnabled(SLEffectSendItf self,
37462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const void *pAuxEffect, SLboolean *pEnable)
37472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
374883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == pEnable)
374983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
375072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
375183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
375283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == enableLevel)
375383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
37547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
375583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLboolean enable = enableLevel->mEnable;
37567754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
375783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pEnable = enable;
37582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
37592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
37602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
37612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EffectSend_SetDirectLevel(SLEffectSendItf self,
37622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillibel directLevel)
37632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
376472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
37657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
376683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    this->mDirectLevel = directLevel;
37677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
37682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
37692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
37702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
37712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EffectSend_GetDirectLevel(SLEffectSendItf self,
37722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLmillibel *pDirectLevel)
37732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
377483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == pDirectLevel)
377583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
377672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
37777754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
377883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLmillibel directLevel = this->mDirectLevel;
37797754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
378083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pDirectLevel = directLevel;
37812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
37822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
37832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
37842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EffectSend_SetSendLevel(SLEffectSendItf self,
37852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const void *pAuxEffect, SLmillibel sendLevel)
37862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
378772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
378883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
378983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == enableLevel)
379083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
37917754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // EnableEffectSend is exclusive, so this has to be also
379283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    interface_lock_exclusive(this);
379383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    enableLevel->mSendLevel = sendLevel;
379483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    interface_unlock_exclusive(this);
37952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
37962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
37972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
37982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EffectSend_GetSendLevel(SLEffectSendItf self,
37992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const void *pAuxEffect, SLmillibel *pSendLevel)
38002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
380183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == pSendLevel)
380283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
380372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEffectSend *this = (IEffectSend *) self;
380483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
380583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL == enableLevel)
380683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
38077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
380883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLmillibel sendLevel = enableLevel->mSendLevel;
38097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
381083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pSendLevel = sendLevel;
38112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
38122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
38132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3814bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLEffectSendItf_ EffectSend_EffectSendItf = {
38152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EffectSend_EnableEffectSend,
38162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EffectSend_IsEnabled,
38172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EffectSend_SetDirectLevel,
38182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EffectSend_GetDirectLevel,
38192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EffectSend_SetSendLevel,
38202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EffectSend_GetSendLevel
38212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
38222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
38232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* EngineCapabilities implementation */
38242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
38252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_QuerySupportedProfiles(
38262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLEngineCapabilitiesItf self, SLuint16 *pProfilesSupported)
38272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
38282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pProfilesSupported)
38292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
383083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    // This omits the unofficial driver profile
383183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pProfilesSupported =
383283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        SL_PROFILES_PHONE | SL_PROFILES_MUSIC | SL_PROFILES_GAME;
38332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
38342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
38352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
38362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_QueryAvailableVoices(
38372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLEngineCapabilitiesItf self, SLuint16 voiceType, SLint16 *pNumMaxVoices,
38382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLboolean *pIsAbsoluteMax, SLint16 *pNumFreeVoices)
38392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
38402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    switch (voiceType) {
38412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_VOICETYPE_2D_AUDIO:
38422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_VOICETYPE_MIDI:
38432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_VOICETYPE_3D_AUDIO:
38442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    case SL_VOICETYPE_3D_MIDIOUTPUT:
38452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        break;
38462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    default:
38472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
38482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
38492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pNumMaxVoices)
385083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        *pNumMaxVoices = 32;
38512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pIsAbsoluteMax)
38522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        *pIsAbsoluteMax = SL_BOOLEAN_TRUE;
38532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL != pNumFreeVoices)
385483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        *pNumFreeVoices = 32;
38552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
38562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
38572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
38582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_QueryNumberOfMIDISynthesizers(
38592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLEngineCapabilitiesItf self, SLint16 *pNum)
38602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
38612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pNum)
38622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
386383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pNum = 1;
38642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
38652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
38662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
38672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_QueryAPIVersion(SLEngineCapabilitiesItf self,
38682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLint16 *pMajor, SLint16 *pMinor, SLint16 *pStep)
38692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
38702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (!(NULL != pMajor && NULL != pMinor && NULL != pStep))
38712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
38722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pMajor = 1;
38732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pMinor = 0;
38742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    *pStep = 1;
38752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
38762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
38772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
38782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_QueryLEDCapabilities(
38792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLEngineCapabilitiesItf self, SLuint32 *pIndex, SLuint32 *pLEDDeviceID,
38802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLLEDDescriptor *pDescriptor)
38812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
388283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLuint32 maxIndex = sizeof(LED_id_descriptors) /
388383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        sizeof(LED_id_descriptors[0]);
388483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    const struct LED_id_descriptor *id_descriptor;
388583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLuint32 index;
388683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL != pIndex) {
388783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        if (NULL != pLEDDeviceID || NULL != pDescriptor) {
388883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            index = *pIndex;
388983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            if (index >= maxIndex)
389083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
389183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            id_descriptor = &LED_id_descriptors[index];
389283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            if (NULL != pLEDDeviceID)
389383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                *pLEDDeviceID = id_descriptor->id;
389483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            if (NULL != pDescriptor)
389583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                *pDescriptor = *id_descriptor->descriptor;
389683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        }
389783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        /* FIXME else? */
389883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        *pIndex = maxIndex;
389983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_SUCCESS;
390083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    } else {
390183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        if (NULL != pLEDDeviceID && NULL != pDescriptor) {
390283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            SLuint32 id = *pLEDDeviceID;
390383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            for (index = 0; index < maxIndex; ++index) {
390483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                id_descriptor = &LED_id_descriptors[index];
390583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                if (id == id_descriptor->id) {
390683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                    *pDescriptor = *id_descriptor->descriptor;
390783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                    return SL_RESULT_SUCCESS;
390883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                }
390983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            }
391083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        }
391183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
391283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    }
39132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
39142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
39152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_QueryVibraCapabilities(
39162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLEngineCapabilitiesItf self, SLuint32 *pIndex, SLuint32 *pVibraDeviceID,
39172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLVibraDescriptor *pDescriptor)
39182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
391983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLuint32 maxIndex = sizeof(Vibra_id_descriptors) /
392083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        sizeof(Vibra_id_descriptors[0]);
392183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    const struct Vibra_id_descriptor *id_descriptor;
392283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    SLuint32 index;
392383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    if (NULL != pIndex) {
392483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        if (NULL != pVibraDeviceID || NULL != pDescriptor) {
392583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            index = *pIndex;
392683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            if (index >= maxIndex)
392783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
392883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            id_descriptor = &Vibra_id_descriptors[index];
392983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            if (NULL != pVibraDeviceID)
393083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                *pVibraDeviceID = id_descriptor->id;
393183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            if (NULL != pDescriptor)
393283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                *pDescriptor = *id_descriptor->descriptor;
393383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        }
393483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        /* FIXME else? */
393583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        *pIndex = maxIndex;
393683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_SUCCESS;
393783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    } else {
393883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        if (NULL != pVibraDeviceID && NULL != pDescriptor) {
393983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            SLuint32 id = *pVibraDeviceID;
394083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            for (index = 0; index < maxIndex; ++index) {
394183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                id_descriptor = &Vibra_id_descriptors[index];
394283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                if (id == id_descriptor->id) {
394383f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                    *pDescriptor = *id_descriptor->descriptor;
394483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                    return SL_RESULT_SUCCESS;
394583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                }
394683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten            }
394783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        }
394883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
394983f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    }
39502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
39512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
39522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
39532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLresult EngineCapabilities_IsThreadSafe(SLEngineCapabilitiesItf self,
39542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLboolean *pIsThreadSafe)
39552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
39562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pIsThreadSafe)
39572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
395872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEngineCapabilities *this =
395972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IEngineCapabilities *) self;
396083f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    *pIsThreadSafe = this->mThreadSafe;
39612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
39622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
39632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3964bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLEngineCapabilitiesItf_
39652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_EngineCapabilitiesItf = {
39662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_QuerySupportedProfiles,
39672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_QueryAvailableVoices,
39682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_QueryNumberOfMIDISynthesizers,
39692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_QueryAPIVersion,
39702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_QueryLEDCapabilities,
39712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_QueryVibraCapabilities,
39722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    EngineCapabilities_IsThreadSafe
39732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
39742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
3975bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* LEDArray implementation */
3976bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
3977bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult LEDArray_ActivateLEDArray(SLLEDArrayItf self,
3978bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 lightMask)
3979bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
398072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ILEDArray *this = (ILEDArray *) self;
39817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
3982ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mLightMask = lightMask;
39837754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
3984bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
3985bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
3986bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
3987bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult LEDArray_IsLEDArrayActivated(SLLEDArrayItf self,
3988ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 *pLightMask)
3989bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
3990ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pLightMask)
3991ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
399272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ILEDArray *this = (ILEDArray *) self;
39937754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
3994ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 lightMask = this->mLightMask;
39957754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
3996ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pLightMask = lightMask;
3997bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
3998bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
3999bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4000bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult LEDArray_SetColor(SLLEDArrayItf self, SLuint8 index,
4001ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    const SLHSL *pColor)
4002bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4003ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pColor)
4004ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4005ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLHSL color = *pColor;
400672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ILEDArray *this = (ILEDArray *) self;
40077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
4008ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mColor[index] = color;
40097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
4010bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4011bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4012bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4013bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult LEDArray_GetColor(SLLEDArrayItf self, SLuint8 index,
4014ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLHSL *pColor)
4015bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4016ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pColor)
4017ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
401872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ILEDArray *this = (ILEDArray *) self;
40197754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
4020ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLHSL color = this->mColor[index];
40217754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
4022ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pColor = color;
4023bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4024bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4025bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4026bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLLEDArrayItf_ LEDArray_LEDArrayItf = {
4027bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    LEDArray_ActivateLEDArray,
4028bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    LEDArray_IsLEDArrayActivated,
4029bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    LEDArray_SetColor,
4030bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    LEDArray_GetColor,
4031bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4032bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4033bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* MetadataExtraction implementation */
4034bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4035bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_GetItemCount(SLMetadataExtractionItf self,
4036bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pItemCount)
4037bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
403872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMetadataExtraction *this = (IMetadataExtraction *) self;
4039ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pItemCount)
4040ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4041ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pItemCount = 0;
4042bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4043bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4044bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4045bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_GetKeySize(SLMetadataExtractionItf self,
4046bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 index, SLuint32 *pKeySize)
4047bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
404872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMetadataExtraction *this = (IMetadataExtraction *) self;
4049ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pKeySize)
4050ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4051ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pKeySize = 0;
4052bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4053bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4054bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4055bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_GetKey(SLMetadataExtractionItf self,
4056bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 index, SLuint32 keySize, SLMetadataInfo *pKey)
4057bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
405872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMetadataExtraction *this = (IMetadataExtraction *) self;
4059ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pKey)
4060ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
406172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    SLMetadataInfo key;
406272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    key.size = 0;
406372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    key.encoding = 0;
406472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    key.langCountry[-0] = '\0';
406572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    key.data[0] = 0;
406672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    *pKey = key;
4067bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4068bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4069bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4070bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_GetValueSize(SLMetadataExtractionItf self,
4071bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 index, SLuint32 *pValueSize)
4072bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
407372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMetadataExtraction *this = (IMetadataExtraction *) self;
4074ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pValueSize)
4075ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4076ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pValueSize = 0;
4077bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4078bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4079bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4080bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_GetValue(SLMetadataExtractionItf self,
4081bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 index, SLuint32 valueSize, SLMetadataInfo *pValue)
4082bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
408372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMetadataExtraction *this = (IMetadataExtraction *) self;
4084ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pValue)
4085ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4086ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLMetadataInfo value;
408772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    value.size = 0;
408872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    value.encoding = 0;
408972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    value.langCountry[-0] = '\0';
409072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    value.data[0] = 0;
4091ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pValue = value;;
4092bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4093bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4094bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4095bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_AddKeyFilter(SLMetadataExtractionItf self,
4096bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 keySize, const void *pKey, SLuint32 keyEncoding,
4097bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const SLchar *pValueLangCountry, SLuint32 valueEncoding, SLuint8 filterMask)
4098bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4099ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pKey || NULL == pValueLangCountry)
4100ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
410172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataExtraction *this = (IMetadataExtraction *) self;
4102ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
4103ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKeySize = keySize;
4104ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKey = pKey;
4105ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKeyEncoding = keyEncoding;
4106ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mValueLangCountry = pValueLangCountry; // FIXME local copy?
4107ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mValueEncoding = valueEncoding;
4108ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mFilterMask = filterMask;
4109ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
4110bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4111bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4112bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4113bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataExtraction_ClearKeyFilter(SLMetadataExtractionItf self)
4114bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
411572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataExtraction *this = (IMetadataExtraction *) self;
4116ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mKeyFilter = 0;
4117bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4118bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4119bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4120bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLMetadataExtractionItf_
4121bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_MetadataExtractionItf = {
4122bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_GetItemCount,
4123bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_GetKeySize,
4124bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_GetKey,
4125bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_GetValueSize,
4126bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_GetValue,
4127bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_AddKeyFilter,
4128bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataExtraction_ClearKeyFilter
4129bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4130bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4131bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* MetadataTraversal implementation */
4132bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4133bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataTraversal_SetMode(SLMetadataTraversalItf self,
4134bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 mode)
4135bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
413672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataTraversal *this = (IMetadataTraversal *) self;
4137ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMode = mode;
4138bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4139bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4140bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4141bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataTraversal_GetChildCount(SLMetadataTraversalItf self,
4142bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pCount)
4143bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4144ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pCount)
4145ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
414672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataTraversal *this = (IMetadataTraversal *) self;
4147ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pCount = this->mCount;
4148bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4149bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4150bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4151bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataTraversal_GetChildMIMETypeSize(
4152bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLMetadataTraversalItf self, SLuint32 index, SLuint32 *pSize)
4153bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4154ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pSize)
4155ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
415672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataTraversal *this = (IMetadataTraversal *) self;
4157ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pSize = this->mSize;
4158bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4159bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4160bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4161bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataTraversal_GetChildInfo(SLMetadataTraversalItf self,
4162bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 index, SLint32 *pNodeID, SLuint32 *pType, SLuint32 size,
4163bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLchar *pMimeType)
4164bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
416572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMetadataTraversal *this = (IMetadataTraversal *) self;
4166bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4167bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4168bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4169bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MetadataTraversal_SetActiveNode(SLMetadataTraversalItf self,
4170bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 index)
4171bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
417272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMetadataTraversal *this = (IMetadataTraversal *) self;
4173ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mIndex = index;
4174bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4175bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4176bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4177bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLMetadataTraversalItf_
4178bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataTraversal_MetadataTraversalItf = {
4179bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataTraversal_SetMode,
4180bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataTraversal_GetChildCount,
4181bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataTraversal_GetChildMIMETypeSize,
4182bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataTraversal_GetChildInfo,
4183bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MetadataTraversal_SetActiveNode
4184bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4185bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4186bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* MuteSolo implementation */
4187bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4188bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MuteSolo_SetChannelMute(SLMuteSoloItf self, SLuint8 chan,
4189bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten   SLboolean mute)
4190bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
419172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMuteSolo *this = (IMuteSolo *) self;
4192ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 mask = 1 << chan;
41937754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
4194ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (mute)
4195ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mMuteMask |= mask;
4196ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    else
4197ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mMuteMask &= ~mask;
41987754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
4199bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4200bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4201bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4202bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MuteSolo_GetChannelMute(SLMuteSoloItf self, SLuint8 chan,
4203bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pMute)
4204bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4205ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMute)
4206ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
420772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMuteSolo *this = (IMuteSolo *) self;
42087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
42097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = this->mMuteMask;
42107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
42117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pMute = (mask >> chan) & 1;
4212bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4213bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4214bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4215bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MuteSolo_SetChannelSolo(SLMuteSoloItf self, SLuint8 chan,
4216bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean solo)
4217bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
421872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMuteSolo *this = (IMuteSolo *) self;
42197754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = 1 << chan;
42207754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
4221ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (solo)
4222ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mSoloMask |= mask;
4223ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    else
4224ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mSoloMask &= ~mask;
42257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
4226bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4227bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4228bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4229bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MuteSolo_GetChannelSolo(SLMuteSoloItf self, SLuint8 chan,
4230bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pSolo)
4231bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4232ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pSolo)
4233ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
423472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMuteSolo *this = (IMuteSolo *) self;
42357754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
42367754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = this->mSoloMask;
42377754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
42387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pSolo = (mask >> chan) & 1;
4239bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4240bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4241bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4242bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult MuteSolo_GetNumChannels(SLMuteSoloItf self,
4243bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint8 *pNumChannels)
4244bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4245ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pNumChannels)
4246ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
424772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMuteSolo *this = (IMuteSolo *) self;
4248ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // FIXME const
4249ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 numChannels = this->mNumChannels;
4250ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pNumChannels = numChannels;
4251bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4252bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4253bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4254bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLMuteSoloItf_ MuteSolo_MuteSoloItf = {
4255bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MuteSolo_SetChannelMute,
4256bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MuteSolo_GetChannelMute,
4257bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MuteSolo_SetChannelSolo,
4258bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MuteSolo_GetChannelSolo,
4259bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    MuteSolo_GetNumChannels
4260bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4261bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4262bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Pitch implementation */
4263bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4264bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Pitch_SetPitch(SLPitchItf self, SLpermille pitch)
4265bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
426672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPitch *this = (IPitch *) self;
42677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
4268ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mPitch = pitch;
42697754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
4270bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4271bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4272bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4273bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Pitch_GetPitch(SLPitchItf self, SLpermille *pPitch)
4274bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4275ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pPitch)
4276ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
427772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPitch *this = (IPitch *) self;
42787754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
4279ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille pitch = this->mPitch;
42807754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
4281ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pPitch = pitch;
4282bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4283bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4284bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4285bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Pitch_GetPitchCapabilities(SLPitchItf self,
4286bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pMinPitch, SLpermille *pMaxPitch)
4287bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4288ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMinPitch || NULL == pMaxPitch)
4289ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
429072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPitch *this = (IPitch *) self;
4291ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille minPitch = this->mMinPitch;
4292ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille maxPitch = this->mMaxPitch;
4293ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMinPitch = minPitch;
4294ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMaxPitch = maxPitch;
4295bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4296bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4297bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4298bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLPitchItf_ Pitch_PitchItf = {
4299bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Pitch_SetPitch,
4300bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Pitch_GetPitch,
4301bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Pitch_GetPitchCapabilities
4302bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4303bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4304bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* PlaybackRate implementation */
4305bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4306bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PlaybackRate_SetRate(SLPlaybackRateItf self, SLpermille rate)
4307bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
430872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlaybackRate *this = (IPlaybackRate *) self;
43097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
4310ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRate = rate;
43117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
4312bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4313bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4314bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4315bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PlaybackRate_GetRate(SLPlaybackRateItf self, SLpermille *pRate)
4316bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4317ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pRate)
4318ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
431972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlaybackRate *this = (IPlaybackRate *) self;
43207754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
4321ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille rate = this->mRate;
43227754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
4323ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRate = rate;
4324bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4325bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4326bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4327bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PlaybackRate_SetPropertyConstraints(SLPlaybackRateItf self,
4328bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 constraints)
4329bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
433072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlaybackRate *this = (IPlaybackRate *) self;
4331ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // FIXME are properties and property constraints the same thing?
4332ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties = constraints;
4333bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4334bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4335bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4336bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PlaybackRate_GetProperties(SLPlaybackRateItf self,
4337bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pProperties)
4338bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4339ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pProperties)
4340ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
434172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlaybackRate *this = (IPlaybackRate *) self;
4342ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 properties = this->mProperties;
4343ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pProperties = properties;
4344bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4345bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4346bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4347bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PlaybackRate_GetCapabilitiesOfRate(SLPlaybackRateItf self,
4348bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille rate, SLuint32 *pCapabilities)
4349bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4350ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pCapabilities)
4351ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
435272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    // IPlaybackRate *this = (IPlaybackRate *) self;
43537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 capabilities = 0; // FIXME
4354ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pCapabilities = capabilities;
4355bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4356bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4357bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4358bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PlaybackRate_GetRateRange(SLPlaybackRateItf self, SLuint8 index,
4359bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pMinRate, SLpermille *pMaxRate, SLpermille *pStepSize,
4360bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pCapabilities)
4361bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4362ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMinRate || NULL == pMaxRate || NULL == pStepSize || NULL == pCapabilities)
4363ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
436472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPlaybackRate *this = (IPlaybackRate *) self;
4365ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_shared(this);
4366ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille minRate = this->mMinRate;
4367ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille maxRate = this->mMaxRate;
4368ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille stepSize = this->mStepSize;
4369ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 capabilities = this->mCapabilities;
4370ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_shared(this);
4371ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMinRate = minRate;
4372ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMaxRate = maxRate;
4373ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pStepSize = stepSize;
4374ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pCapabilities = capabilities;
4375bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4376bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4377bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4378bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLPlaybackRateItf_ PlaybackRate_PlaybackRateItf = {
4379bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PlaybackRate_SetRate,
4380bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PlaybackRate_GetRate,
4381bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PlaybackRate_SetPropertyConstraints,
4382bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PlaybackRate_GetProperties,
4383bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PlaybackRate_GetCapabilitiesOfRate,
4384bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PlaybackRate_GetRateRange
4385bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4386bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4387bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* PrefetchStatus implementation */
4388bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4389bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_GetPrefetchStatus(SLPrefetchStatusItf self,
4390bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pStatus)
4391bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4392ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pStatus)
4393ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
439472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4395ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4396ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 status = this->mStatus;
4397ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4398ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pStatus = status;
4399bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4400bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4401bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4402bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_GetFillLevel(SLPrefetchStatusItf self,
4403bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pLevel)
4404bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4405ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pLevel)
4406ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
440772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4408ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4409ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille level = this->mLevel;
4410ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4411ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pLevel = level;
4412bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4413bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4414bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4415bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_RegisterCallback(SLPrefetchStatusItf self,
4416bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    slPrefetchCallback callback, void *pContext)
4417bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
441872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4419ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
4420ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mCallback = callback;
4421ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mContext = pContext;
4422ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
4423bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4424bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4425bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4426bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_SetCallbackEventsMask(SLPrefetchStatusItf self,
4427bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 eventFlags)
4428bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
442972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4430ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4431ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mCallbackEventsMask = eventFlags;
4432ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4433bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4434bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4435bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4436bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_GetCallbackEventsMask(SLPrefetchStatusItf self,
4437bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pEventFlags)
4438bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4439ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pEventFlags)
4440ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
444172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4442ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4443ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 callbackEventsMask = this->mCallbackEventsMask;
4444ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4445ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pEventFlags = callbackEventsMask;
4446bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4447bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4448bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4449bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_SetFillUpdatePeriod(SLPrefetchStatusItf self,
4450bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille period)
4451bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
445272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4453ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4454ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mFillUpdatePeriod = period;
4455ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4456bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4457bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4458bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4459bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PrefetchStatus_GetFillUpdatePeriod(SLPrefetchStatusItf self,
4460bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pPeriod)
4461bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4462ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pPeriod)
4463ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
446472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPrefetchStatus *this = (IPrefetchStatus *) self;
4465ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4466ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille fillUpdatePeriod = this->mFillUpdatePeriod;
4467ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4468ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pPeriod = fillUpdatePeriod;
4469bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4470bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4471bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4472bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLPrefetchStatusItf_
4473bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn KastenPrefetchStatus_PrefetchStatusItf = {
4474bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_GetPrefetchStatus,
4475bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_GetFillLevel,
4476bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_RegisterCallback,
4477bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_SetCallbackEventsMask,
4478bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_GetCallbackEventsMask,
4479bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_SetFillUpdatePeriod,
4480bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PrefetchStatus_GetFillUpdatePeriod
4481bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4482bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4483bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* RatePitch implementation */
4484bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4485bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult RatePitch_SetRate(SLRatePitchItf self, SLpermille rate)
4486bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
448772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRatePitch *this = (IRatePitch *) self;
4488ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4489ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRate = rate;
4490ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4491bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4492bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4493bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4494bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult RatePitch_GetRate(SLRatePitchItf self, SLpermille *pRate)
4495bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4496ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pRate)
4497ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
449872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRatePitch *this = (IRatePitch *) self;
4499ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4500ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille rate = this->mRate;
4501ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4502ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRate = rate;
4503bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4504bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4505bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4506bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult RatePitch_GetRatePitchCapabilities(SLRatePitchItf self,
4507bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pMinRate, SLpermille *pMaxRate)
4508bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4509ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMinRate || NULL == pMaxRate)
4510ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
451172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRatePitch *this = (IRatePitch *) self;
4512ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // FIXME const, direct access?
4513ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille minRate = this->mMinRate;
4514ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille maxRate = this->mMaxRate;
4515ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMinRate = minRate;
4516ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMaxRate = maxRate;
4517bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4518bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4519bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4520bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLRatePitchItf_ RatePitch_RatePitchItf = {
4521bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    RatePitch_SetRate,
4522bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    RatePitch_GetRate,
4523bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    RatePitch_GetRatePitchCapabilities
4524bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4525bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4526bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Record implementation */
4527bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4528bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_SetRecordState(SLRecordItf self, SLuint32 state)
4529bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
453072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4531ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4532ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mState = state;
4533ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4534bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4535bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4536bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4537bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_GetRecordState(SLRecordItf self, SLuint32 *pState)
4538bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
453972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4540ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pState)
4541ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4542ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4543ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 state = this->mState;
4544ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4545ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pState = state;
4546bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4547bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4548bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4549bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_SetDurationLimit(SLRecordItf self, SLmillisecond msec)
4550bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
455172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4552ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4553ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDurationLimit = msec;
4554ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4555bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4556bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4557bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4558bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_GetPosition(SLRecordItf self, SLmillisecond *pMsec)
4559bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4560ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMsec)
4561ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
456272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4563ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4564ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillisecond position = this->mPosition;
4565ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4566ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMsec = position;
4567bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4568bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4569bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4570bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_RegisterCallback(SLRecordItf self,
4571bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    slRecordCallback callback, void *pContext)
4572bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
457372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4574ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
4575ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mCallback = callback;
4576ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mContext = pContext;
4577ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
4578bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4579bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4580bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4581bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_SetCallbackEventsMask(SLRecordItf self,
4582bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 eventFlags)
4583bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
458472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4585ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4586ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mCallbackEventsMask = eventFlags;
4587ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4588bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4589bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4590bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4591bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_GetCallbackEventsMask(SLRecordItf self,
4592bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 *pEventFlags)
4593bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4594ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pEventFlags)
4595ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
459672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4597ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4598ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 callbackEventsMask = this->mCallbackEventsMask;
4599ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4600ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pEventFlags = callbackEventsMask;
4601bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4602bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4603bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4604bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_SetMarkerPosition(SLRecordItf self, SLmillisecond mSec)
4605bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
460672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4607ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4608ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMarkerPosition = mSec;
4609ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4610bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4611bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4612bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4613bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_ClearMarkerPosition(SLRecordItf self)
4614bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
461572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4616ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4617ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMarkerPosition = 0;
4618ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4619bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4620bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4621bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4622bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_GetMarkerPosition(SLRecordItf self, SLmillisecond *pMsec)
4623bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4624ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMsec)
4625ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
462672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4627ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4628ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillisecond markerPosition = this->mMarkerPosition;
4629ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4630ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMsec = markerPosition;
4631bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4632bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4633bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4634bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_SetPositionUpdatePeriod(SLRecordItf self,
4635bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillisecond mSec)
4636bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
463772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4638ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
4639ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mPositionUpdatePeriod = mSec;
4640ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
4641bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4642bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4643bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4644bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Record_GetPositionUpdatePeriod(SLRecordItf self,
4645bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillisecond *pMsec)
4646bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4647ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMsec)
4648ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
464972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IRecord *this = (IRecord *) self;
4650ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
4651ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillisecond positionUpdatePeriod = this->mPositionUpdatePeriod;
4652ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
4653ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMsec = positionUpdatePeriod;
4654bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4655bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4656bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4657bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLRecordItf_ Record_RecordItf = {
4658bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_SetRecordState,
4659bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_GetRecordState,
4660bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_SetDurationLimit,
4661bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_GetPosition,
4662bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_RegisterCallback,
4663bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_SetCallbackEventsMask,
4664bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_GetCallbackEventsMask,
4665bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_SetMarkerPosition,
4666bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_ClearMarkerPosition,
4667bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_GetMarkerPosition,
4668bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_SetPositionUpdatePeriod,
4669bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Record_GetPositionUpdatePeriod
4670bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4671bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4672bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* ThreadSync implementation */
4673bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4674bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult ThreadSync_EnterCriticalSection(SLThreadSyncItf self)
4675bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
467672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IThreadSync *this = (IThreadSync *) self;
4677e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLresult result;
4678e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_exclusive(this);
4679e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    for (;;) {
4680e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        if (this->mInCriticalSection) {
4681e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            if (this->mOwner != pthread_self()) {
4682e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten                this->mWaiting = SL_BOOLEAN_TRUE;
4683e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten                interface_cond_wait(this);
4684e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten                continue;
4685e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            }
4686e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
4687e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            break;
4688e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        }
4689e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        this->mInCriticalSection = SL_BOOLEAN_TRUE;
4690e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        this->mOwner = pthread_self();
4691e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        result = SL_RESULT_SUCCESS;
4692e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        break;
4693e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    }
4694e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_exclusive(this);
4695e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    return result;
4696bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4697bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4698bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult ThreadSync_ExitCriticalSection(SLThreadSyncItf self)
4699bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
470072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IThreadSync *this = (IThreadSync *) self;
4701e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLresult result;
4702e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_exclusive(this);
4703e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (!this->mInCriticalSection || this->mOwner != pthread_self()) {
4704e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
4705e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    } else {
4706e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        this->mInCriticalSection = SL_BOOLEAN_FALSE;
4707e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        this->mOwner = NULL;
4708e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        result = SL_RESULT_SUCCESS;
4709e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        if (this->mWaiting) {
4710e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            this->mWaiting = SL_BOOLEAN_FALSE;
4711e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten            interface_cond_signal(this);
4712e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        }
4713e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    }
4714e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_exclusive(this);
4715e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    return result;
4716bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4717bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4718bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLThreadSyncItf_ ThreadSync_ThreadSyncItf = {
4719bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    ThreadSync_EnterCriticalSection,
4720bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    ThreadSync_ExitCriticalSection
4721bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4722bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4723bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Vibra implementation */
4724bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4725bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Vibra_Vibrate(SLVibraItf self, SLboolean vibrate)
4726bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
472772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
4728e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_poke(this);
4729e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mVibrate = vibrate;
4730e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_poke(this);
4731bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4732bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4733bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4734bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Vibra_IsVibrating(SLVibraItf self, SLboolean *pVibrating)
4735bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4736e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pVibrating)
4737e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
473872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
4739e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_peek(this);
4740e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLboolean vibrate = this->mVibrate;
4741e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_peek(this);
4742e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    *pVibrating = vibrate;
4743bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4744bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4745bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4746bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Vibra_SetFrequency(SLVibraItf self, SLmilliHertz frequency)
4747bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
474872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
4749e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_poke(this);
4750e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mFrequency = frequency;
4751e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_exclusive(this);
4752bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4753bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4754bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4755bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Vibra_GetFrequency(SLVibraItf self, SLmilliHertz *pFrequency)
4756bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4757e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pFrequency)
4758e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
475972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
4760e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_peek(this);
4761e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLmilliHertz frequency = this->mFrequency;
4762e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_peek(this);
4763e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    *pFrequency = frequency;
4764bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4765bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4766bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4767bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Vibra_SetIntensity(SLVibraItf self, SLpermille intensity)
4768bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
476972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
4770e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_poke(this);
4771e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    this->mIntensity = intensity;
4772e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_poke(this);
4773bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4774bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4775bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4776bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Vibra_GetIntensity(SLVibraItf self, SLpermille *pIntensity)
4777bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4778e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    if (NULL == pIntensity)
4779e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
478072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVibra *this = (IVibra *) self;
4781e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_lock_peek(this);
4782e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    SLpermille intensity = this->mIntensity;
4783e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    interface_unlock_peek(this);
4784e0e0b596ad06527ca5814c78db4ab6ab5b16e06cGlenn Kasten    *pIntensity = intensity;
4785bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4786bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4787bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4788bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLVibraItf_ Vibra_VibraItf = {
4789bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Vibra_Vibrate,
4790bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Vibra_IsVibrating,
4791bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Vibra_SetFrequency,
4792bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Vibra_GetFrequency,
4793bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Vibra_SetIntensity,
4794bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Vibra_GetIntensity
4795bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4796bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4797bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Visualization implementation */
4798bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4799bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Visualization_RegisterVisualizationCallback(
4800bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLVisualizationItf self, slVisualizationCallback callback, void *pContext,
4801bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmilliHertz rate)
4802bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
480372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVisualization *this =
480472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IVisualization *) self;
48057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
4806bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mCallback = callback;
4807bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mContext = pContext;
4808bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mRate = rate;
48097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
4810bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4811bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4812bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4813bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Visualization_GetMaxRate(SLVisualizationItf self,
4814bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmilliHertz *pRate)
4815bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4816bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pRate)
4817bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4818ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRate = 20000;
4819bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4820bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4821bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4822bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLVisualizationItf_ Visualization_VisualizationItf = {
4823bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Visualization_RegisterVisualizationCallback,
4824bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Visualization_GetMaxRate
4825bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4826bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4827bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* BassBoost implementation */
48282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4829bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult BassBoost_SetEnabled(SLBassBoostItf self, SLboolean enabled)
48302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
483172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBassBoost *this = (IBassBoost *) self;
48327754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
4833bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mEnabled = enabled;
48347754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
48352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
48362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
48372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4838bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult BassBoost_IsEnabled(SLBassBoostItf self, SLboolean *pEnabled)
48392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
4840bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pEnabled)
4841bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
484272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBassBoost *this = (IBassBoost *) self;
48437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
48447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLboolean enabled = this->mEnabled;
48457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
48467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pEnabled = enabled;
48472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
48482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
48492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4850bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult BassBoost_SetStrength(SLBassBoostItf self, SLpermille strength)
48512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
485272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBassBoost *this = (IBassBoost *) self;
48537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
4854bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mStrength = strength;
48557754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
48562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
48572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
48582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4859bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult BassBoost_GetRoundedStrength(SLBassBoostItf self,
4860bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pStrength)
48612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
4862bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pStrength)
4863bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
486472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IBassBoost *this = (IBassBoost *) self;
48657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
48667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLpermille strength = this->mStrength;
48677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
48687754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pStrength = strength;
48692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
48702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
48712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4872bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult BassBoost_IsStrengthSupported(SLBassBoostItf self,
4873bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pSupported)
4874bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
4875bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pSupported)
4876bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4877bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pSupported = SL_BOOLEAN_TRUE;
4878bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
4879bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
4880bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4881bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLBassBoostItf_ BassBoost_BassBoostItf = {
4882bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    BassBoost_SetEnabled,
4883bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    BassBoost_IsEnabled,
4884bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    BassBoost_SetStrength,
4885bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    BassBoost_GetRoundedStrength,
4886bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    BassBoost_IsStrengthSupported
48872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
48882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4889bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* 3DGrouping implementation */
48902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4891bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DGrouping_Set3DGroup(SL3DGroupingItf self, SLObjectItf group)
48922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
489372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DGrouping *this = (I3DGrouping *) self;
489432918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    if (NULL == group)
489532918086b694fc383c8c2d590ac45492801676f7Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
489672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *thisGroup = (IObject *) group;
489732918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    if (&_3DGroup_class != thisGroup->mClass)
489832918086b694fc383c8c2d590ac45492801676f7Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
489932918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    // FIXME race possible if group unrealized immediately after, should lock
490032918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    if (SL_OBJECT_STATE_REALIZED != thisGroup->mState)
490132918086b694fc383c8c2d590ac45492801676f7Glenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
490232918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_lock_exclusive(this);
4903bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mGroup = group;
490432918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    // FIXME add this object to the group's bag of objects
490532918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_unlock_exclusive(this);
49062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
49072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
49082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4909bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DGrouping_Get3DGroup(SL3DGroupingItf self,
4910bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLObjectItf *pGroup)
49112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
4912bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pGroup)
4913bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
491472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DGrouping *this = (I3DGrouping *) self;
491532918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_lock_peek(this);
4916bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pGroup = this->mGroup;
491732918086b694fc383c8c2d590ac45492801676f7Glenn Kasten    interface_unlock_peek(this);
49182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
49192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
49202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4921bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SL3DGroupingItf_ _3DGrouping_3DGroupingItf = {
4922bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DGrouping_Set3DGroup,
4923bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DGrouping_Get3DGroup
4924bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
4925bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4926bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* 3DMacroscopic implementation */
4927bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4928bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DMacroscopic_SetSize(SL3DMacroscopicItf self,
4929bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillimeter width, SLmillimeter height, SLmillimeter depth)
49302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
493172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
4932ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
4933ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mSize.mWidth = width;
4934ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mSize.mHeight = height;
4935ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mSize.mDepth = depth;
4936ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
49372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
49382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
49392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4940bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DMacroscopic_GetSize(SL3DMacroscopicItf self,
4941bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillimeter *pWidth, SLmillimeter *pHeight, SLmillimeter *pDepth)
49422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
4943ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pWidth || NULL == pHeight || NULL == pDepth)
4944ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
494572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
4946ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_shared(this);
4947ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillimeter width = this->mSize.mWidth;
4948ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillimeter height = this->mSize.mHeight;
4949ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillimeter depth = this->mSize.mDepth;
4950ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_shared(this);
4951ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pWidth = width;
4952ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pHeight = height;
4953ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pDepth = depth;
49542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
49552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
49562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4957bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DMacroscopic_SetOrientationAngles(SL3DMacroscopicItf self,
4958bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillidegree heading, SLmillidegree pitch, SLmillidegree roll)
49592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
496072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
4961ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
4962ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationAngles.mHeading = heading;
4963ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationAngles.mPitch = pitch;
4964ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationAngles.mRoll = roll;
49657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
49667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_FALSE;
49677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // ++this->mGeneration;
4968ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
49692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
49702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
49712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4972bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DMacroscopic_SetOrientationVectors(SL3DMacroscopicItf self,
4973bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const SLVec3D *pFront, const SLVec3D *pAbove)
49742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
4975ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pFront || NULL == pAbove)
4976ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
497772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
4978ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLVec3D front = *pFront;
4979ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLVec3D above = *pAbove;
4980ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
4981ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mFront = front;
4982ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mOrientationVectors.mUp = above;
49837754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mOrientationActive = ANGLES_UNKNOWN_VECTORS_SET;
49847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_FALSE;
4985ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
49862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
49872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
49882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
4989bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DMacroscopic_Rotate(SL3DMacroscopicItf self,
4990bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillidegree theta, const SLVec3D *pAxis)
49912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
4992ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pAxis)
4993ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
4994ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLVec3D axis = *pAxis;
499572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
4996ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // FIXME Do the rotate here:
49977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // interface_lock_shared(this);
4998ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // read old values and generation
49997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // interface_unlock_shared(this);
5000ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // compute new position
5001ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
50027754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    while (this->mRotatePending)
50037754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        interface_cond_wait(this);
50047754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mTheta = theta;
50057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mAxis = axis;
50067754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mRotatePending = SL_BOOLEAN_TRUE;
5007ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // compare generation with saved value
5008ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // if equal, store new position and increment generation
5009ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // if unequal, discard new position
5010ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
50112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
50122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
50132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5014bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DMacroscopic_GetOrientationVectors(SL3DMacroscopicItf self,
5015bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLVec3D *pFront, SLVec3D *pUp)
5016bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
5017ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pFront || NULL == pUp)
5018ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
501972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DMacroscopic *this = (I3DMacroscopic *) self;
50207754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
50217754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    for (;;) {
50227754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        enum AnglesVectorsActive orientationActive = this->mOrientationActive;
50237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        switch (orientationActive) {
50247754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case ANGLES_COMPUTED_VECTORS_SET:    // not in 1.0.1
50257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case ANGLES_REQUESTED_VECTORS_SET:   // not in 1.0.1
50267754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case ANGLES_UNKNOWN_VECTORS_SET:
50277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case ANGLES_SET_VECTORS_COMPUTED:
50287754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            {
50297754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            SLVec3D front = this->mOrientationVectors.mFront;
50307754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            SLVec3D up = this->mOrientationVectors.mUp;
50317754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_unlock_exclusive(this);
50327754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            *pFront = front;
50337754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            *pUp = up;
50347754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            }
50357754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
50367754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case ANGLES_SET_VECTORS_UNKNOWN:
50377754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            this->mOrientationActive = ANGLES_SET_VECTORS_REQUESTED;
50387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // fall through
50397754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        case ANGLES_SET_VECTORS_REQUESTED:
50407754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            // matched by cond_broadcast in case multiple requesters
50417754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_cond_wait(this);
50427754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            continue;
50437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        default:
50447754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            interface_unlock_exclusive(this);
50457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            assert(SL_BOOLEAN_FALSE);
50467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pFront->x = 0;
50477754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pFront->y = 0;
50487754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pFront->z = 0;
50497754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pUp->x = 0;
50507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pUp->y = 0;
50517754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            pUp->z = 0;
50527754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten            break;
50537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        }
50547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten        break;
50557754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    }
5056bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5057bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
5058bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
5059bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SL3DMacroscopicItf_ _3DMacroscopic_3DMacroscopicItf = {
5060bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DMacroscopic_SetSize,
5061bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DMacroscopic_GetSize,
5062bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DMacroscopic_SetOrientationAngles,
5063bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DMacroscopic_SetOrientationVectors,
5064bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DMacroscopic_Rotate,
5065bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DMacroscopic_GetOrientationVectors
50662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
50672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5068bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* 3DSource implementation */
50692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5070bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetHeadRelative(SL3DSourceItf self,
5071bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean headRelative)
50722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
507372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5074ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5075ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mHeadRelative = headRelative;
5076ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
50772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
50782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
50792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5080bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetHeadRelative(SL3DSourceItf self,
5081bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pHeadRelative)
50822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5083ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pHeadRelative)
5084ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
508572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5086ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5087ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLboolean headRelative = this->mHeadRelative;
5088ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5089ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pHeadRelative = headRelative;
50902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
50912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
50922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5093bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetRolloffDistances(SL3DSourceItf self,
5094bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillimeter minDistance, SLmillimeter maxDistance)
50952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
509672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5097ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
5098ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMinDistance = minDistance;
5099ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMaxDistance = maxDistance;
5100ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
51012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5104bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetRolloffDistances(SL3DSourceItf self,
5105bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillimeter *pMinDistance, SLmillimeter *pMaxDistance)
51062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5107ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMinDistance || NULL == pMaxDistance)
5108ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
510972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5110ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_shared(this);
5111ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillimeter minDistance = this->mMinDistance;
5112ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillimeter maxDistance = this->mMaxDistance;
5113ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_shared(this);
5114ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMinDistance = minDistance;
5115ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMaxDistance = maxDistance;
51162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5119bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetRolloffMaxDistanceMute(SL3DSourceItf self,
5120bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean mute)
51212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
512272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5123ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5124ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRolloffMaxDistanceMute = mute;
5125ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
51262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5129bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetRolloffMaxDistanceMute(SL3DSourceItf self,
5130bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pMute)
51312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5132ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMute)
5133ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
513472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5135ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5136ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLboolean mute = this->mRolloffMaxDistanceMute;
5137ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5138ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pMute = mute;
51392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5142bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetRolloffFactor(SL3DSourceItf self,
5143bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille rolloffFactor)
51442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
514572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5146ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5147ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRolloffFactor = rolloffFactor;
5148ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
51492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5152bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetRolloffFactor(SL3DSourceItf self,
5153bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pRolloffFactor)
51542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
515572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5156ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5157ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille rolloffFactor = this->mRolloffFactor;
5158ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5159ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRolloffFactor = rolloffFactor;
51602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5163bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetRoomRolloffFactor(SL3DSourceItf self,
5164bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille roomRolloffFactor)
51652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
516672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5167ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5168ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mRoomRolloffFactor = roomRolloffFactor;
5169ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
51702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5173bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetRoomRolloffFactor(SL3DSourceItf self,
5174bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pRoomRolloffFactor)
51752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
517672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5177ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5178ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille roomRolloffFactor = this->mRoomRolloffFactor;
5179ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5180ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRoomRolloffFactor = roomRolloffFactor;
51812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
51822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
51832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5184bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetRolloffModel(SL3DSourceItf self, SLuint8 model)
5185bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
518672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5187ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5188ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mDistanceModel = model;
5189ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
5190bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5191bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
51922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5193bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetRolloffModel(SL3DSourceItf self, SLuint8 *pModel)
51942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
519572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5196ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5197ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint8 model = this->mDistanceModel;
5198ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5199ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pModel = model;
52002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5203bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_SetCone(SL3DSourceItf self, SLmillidegree innerAngle,
5204bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillidegree outerAngle, SLmillibel outerLevel)
52052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
520672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5207ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
52087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mConeInnerAngle = innerAngle;
52097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    this->mConeOuterAngle = outerAngle;
5210ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mConeOuterLevel = outerLevel;
5211ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
52122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5215bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult _3DSource_GetCone(SL3DSourceItf self,
5216bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillidegree *pInnerAngle, SLmillidegree *pOuterAngle,
5217bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillibel *pOuterLevel)
52182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5219ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pInnerAngle || NULL == pOuterAngle || NULL == pOuterLevel)
5220ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
522172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    I3DSource *this = (I3DSource *) self;
5222ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_shared(this);
52237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLmillidegree innerAngle = this->mConeInnerAngle;
52247754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLmillidegree outerAngle = this->mConeOuterAngle;
5225ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillibel outerLevel = this->mConeOuterLevel;
5226ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_shared(this);
5227ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pInnerAngle = innerAngle;
5228ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pOuterAngle = outerAngle;
5229ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pOuterLevel = outerLevel;
52302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5233bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SL3DSourceItf_ _3DSource_3DSourceItf = {
5234bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetHeadRelative,
5235bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetHeadRelative,
5236bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetRolloffDistances,
5237bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetRolloffDistances,
5238bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetRolloffMaxDistanceMute,
5239bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetRolloffMaxDistanceMute,
5240bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetRolloffFactor,
5241bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetRolloffFactor,
5242bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetRoomRolloffFactor,
5243bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetRoomRolloffFactor,
5244bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetRolloffModel,
5245bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetRolloffModel,
5246bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_SetCone,
5247bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    _3DSource_GetCone
52482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
52492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5250bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Equalizer implementation */
52512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5252bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_SetEnabled(SLEqualizerItf self, SLboolean enabled)
52532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
525472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5255ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5256ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mEnabled = enabled;
5257ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
52582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5261bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_IsEnabled(SLEqualizerItf self, SLboolean *pEnabled)
52622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5263ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pEnabled)
5264ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
526572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5266ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5267ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLboolean enabled = this->mEnabled;
5268ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5269ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pEnabled = enabled;
52702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5273bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetNumberOfBands(SLEqualizerItf self,
5274bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint16 *pNumBands)
52752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5276ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pNumBands)
5277ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
527872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5279ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // Note: no lock, but OK because it is const
5280ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pNumBands = this->mNumBands;
52812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5284bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetBandLevelRange(SLEqualizerItf self,
5285bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillibel *pMin, SLmillibel *pMax)
52862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5287ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMin && NULL == pMax)
5288ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
528972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5290ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // Note: no lock, but OK because it is const
5291ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL != pMin)
5292ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        *pMin = this->mMin;
5293ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL != pMax)
5294ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        *pMax = this->mMax;
52952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
52962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
52972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5298bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_SetBandLevel(SLEqualizerItf self, SLuint16 band,
5299bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillibel level)
53002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
530172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5302ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (band >= this->mNumBands)
5303ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5304ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5305ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mLevels[band] = level;
5306ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
53072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
53082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
53092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5310bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetBandLevel(SLEqualizerItf self, SLuint16 band,
5311bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillibel *pLevel)
53122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5313ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pLevel)
5314ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
531572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5316ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (band >= this->mNumBands)
5317ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5318ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5319ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillibel level = this->mLevels[band];
5320ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
5321ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pLevel = level;
53222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
53232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
53242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5325bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetCenterFreq(SLEqualizerItf self, SLuint16 band,
5326bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmilliHertz *pCenter)
53272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5328ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pCenter)
5329ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
533072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5331ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (band >= this->mNumBands)
5332ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5333ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // Note: no lock, but OK because it is const
5334ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pCenter = this->mBands[band].mCenter;
53352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
53362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
53372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5338bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetBandFreqRange(SLEqualizerItf self, SLuint16 band,
5339bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmilliHertz *pMin, SLmilliHertz *pMax)
53402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5341ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMin && NULL == pMax)
5342ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
534372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5344ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (band >= this->mNumBands)
5345ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5346ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // Note: no lock, but OK because it is const
5347ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL != pMin)
5348ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        *pMin = this->mBands[band].mMin;
5349ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL != pMax)
5350ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        *pMax = this->mBands[band].mMax;
53512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
53522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
53532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5354bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency,
5355bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint16 *pBand)
53562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5357ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pBand)
5358ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
535972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5360ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // search for band whose center frequency has the closest ratio to 1.0
5361ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // assumes bands are unsorted (a pessimistic assumption)
5362ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // assumes bands can overlap (a pessimistic assumption)
5363ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // assumes a small number of bands, so no need for a fancier algorithm
5364ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    const struct EqualizerBand *band;
5365ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    float floatFreq = (float) frequency;
5366ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    float bestRatio = 0.0;
5367ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint16 bestBand = SL_EQUALIZER_UNDEFINED;
5368ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    for (band = this->mBands; band < &this->mBands[this->mNumBands]; ++band) {
5369ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        if (!(band->mMin <= frequency && frequency <= band->mMax))
5370ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten            continue;
5371ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        assert(band->mMin <= band->mCenter && band->mCenter <= band->mMax);
5372ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        assert(band->mCenter != 0);
5373ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        float ratio = frequency <= band->mCenter ?
5374ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten            floatFreq / band->mCenter : band->mCenter / floatFreq;
5375ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        if (ratio > bestRatio) {
5376ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten            bestRatio = ratio;
5377ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten            bestBand = band - this->mBands;
5378ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        }
5379ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    }
5380ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pBand = band - this->mBands;
53812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
53822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
53832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5384bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetCurrentPreset(SLEqualizerItf self,
5385bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint16 *pPreset)
53862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5387ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pPreset)
5388ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
538972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5390ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_peek(this);
5391ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pPreset = this->mPreset;
5392ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_peek(this);
53932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
53942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
53952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5396bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_UsePreset(SLEqualizerItf self, SLuint16 index)
53972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
539872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5399ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (index >= this->mNumPresets)
5400ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5401ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_poke(this);
5402ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mPreset = index;
5403ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_poke(this);
54042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
54052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
54062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5407bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetNumberOfPresets(SLEqualizerItf self,
5408bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint16 *pNumPresets)
54092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5410ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pNumPresets)
5411ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
541272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5413ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    // Note: no lock, but OK because it is const
5414ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pNumPresets = this->mNumPresets;
54152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
54162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
54172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5418bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Equalizer_GetPresetName(SLEqualizerItf self, SLuint16 index,
5419bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const SLchar ** ppName)
54202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5421ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == ppName)
5422ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
542372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
5424ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (index >= this->mNumPresets)
5425ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5426ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *ppName = this->mPresetNames[index];
54272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
54282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
54292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5430bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLEqualizerItf_ Equalizer_EqualizerItf = {
5431bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_SetEnabled,
5432bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_IsEnabled,
5433bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetNumberOfBands,
5434bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetBandLevelRange,
5435bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_SetBandLevel,
5436bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetBandLevel,
5437bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetCenterFreq,
5438bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetBandFreqRange,
5439bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetBand,
5440bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetCurrentPreset,
5441bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_UsePreset,
5442bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetNumberOfPresets,
5443bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Equalizer_GetPresetName
54442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
54452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5446bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// PresetReverb implementation
54472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5448bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PresetReverb_SetPreset(SLPresetReverbItf self,
5449bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint16 preset)
54502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
545172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPresetReverb *this =
545272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IPresetReverb *) self;
54537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
5454bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mPreset = preset;
54557754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
54562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
54572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
54582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5459bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult PresetReverb_GetPreset(SLPresetReverbItf self,
5460bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint16 *pPreset)
54612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5462bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pPreset)
5463bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
546472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IPresetReverb *this =
546572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IPresetReverb *) self;
54667754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
54677754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint16 preset = this->mPreset;
54687754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
54697754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pPreset = preset;
54702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
54712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
54722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5473bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLPresetReverbItf_ PresetReverb_PresetReverbItf = {
5474bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PresetReverb_SetPreset,
5475bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    PresetReverb_GetPreset
54762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
54772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5478bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// EnvironmentalReverb implementation
54792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
54807754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten// Note: all Set operations use exclusive not poke,
54817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten// because SetEnvironmentalReverbProperties is exclusive.
54827754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten// It is safe for the Get operations to use peek,
54837754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten// on the assumption that the block copy will atomically
54847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten// replace each word of the block.
54857754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten
5486bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetRoomLevel(SLEnvironmentalReverbItf self,
5487bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillibel room)
54882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
548972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
54907754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5491ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.roomLevel = room;
54927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
54932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
54942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
54952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5496bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetRoomLevel(SLEnvironmentalReverbItf self,
5497bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLmillibel *pRoom)
54982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5499ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pRoom)
5500ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
550172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55027754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5503ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillibel roomLevel = this->mProperties.roomLevel;
55047754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5505ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRoom = roomLevel;
55062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5509bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetRoomHFLevel(
5510bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillibel roomHF)
55112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
551272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55137754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5514ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.roomHFLevel = roomHF;
55157754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
55162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5519bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetRoomHFLevel(
5520bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillibel *pRoomHF)
55212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5522ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pRoomHF)
5523ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
552472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55257754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5526ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillibel roomHFLevel = this->mProperties.roomHFLevel;
55277754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5528ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pRoomHF = roomHFLevel;
55292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5532bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetDecayTime(
5533bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillisecond decayTime)
55342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
553572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55367754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5537ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.decayTime = decayTime;
55387754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
55392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5542bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetDecayTime(
5543bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillisecond *pDecayTime)
55442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5545ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pDecayTime)
5546ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
554772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55487754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5549ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillisecond decayTime = this->mProperties.decayTime;
55507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5551ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pDecayTime = decayTime;
55522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5555bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetDecayHFRatio(
5556bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLpermille decayHFRatio)
55572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
555872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55597754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5560ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.decayHFRatio = decayHFRatio;
55617754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
55622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5565bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetDecayHFRatio(
5566bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLpermille *pDecayHFRatio)
55672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5568ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pDecayHFRatio)
5569ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
557072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55717754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5572ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille decayHFRatio = this->mProperties.decayHFRatio;
55737754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5574ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pDecayHFRatio = decayHFRatio;
55752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5578bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetReflectionsLevel(
5579bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillibel reflectionsLevel)
55802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
558172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55827754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5583ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.reflectionsLevel = reflectionsLevel;
55847754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
55852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
55872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5588bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetReflectionsLevel(
5589bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillibel *pReflectionsLevel)
55902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5591ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pReflectionsLevel)
5592ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
559372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
55947754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5595ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillibel reflectionsLevel = this->mProperties.reflectionsLevel;
55967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5597ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pReflectionsLevel = reflectionsLevel;
55982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
55992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5601bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetReflectionsDelay(
5602bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillisecond reflectionsDelay)
56032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
560472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5606ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.reflectionsDelay = reflectionsDelay;
56077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
56082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
56092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5611bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetReflectionsDelay(
5612bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillisecond *pReflectionsDelay)
56132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5614ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pReflectionsDelay)
5615ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
561672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56177754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5618ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillisecond reflectionsDelay = this->mProperties.reflectionsDelay;
56197754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5620ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pReflectionsDelay = reflectionsDelay;
56212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
56222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5624bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetReverbLevel(
5625bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillibel reverbLevel)
56262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
562772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56287754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5629ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.reverbLevel = reverbLevel;
56307754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
56312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
56322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5634bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetReverbLevel(
5635bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillibel *pReverbLevel)
56362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5637ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pReverbLevel)
5638ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
563972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56407754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5641ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillibel reverbLevel = this->mProperties.reverbLevel;
56427754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5643ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pReverbLevel = reverbLevel;
56442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
56452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5647bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetReverbDelay(
5648bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillisecond reverbDelay)
5649bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
565072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56517754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5652ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.reverbDelay = reverbDelay;
56537754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5654bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5655bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
56562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5657bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetReverbDelay(
5658bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLmillisecond *pReverbDelay)
5659bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
5660ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pReverbDelay)
5661ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
566272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56637754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5664ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLmillisecond reverbDelay = this->mProperties.reverbDelay;
56657754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5666ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pReverbDelay = reverbDelay;
5667bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5668bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
56692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5670bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetDiffusion(
5671bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLpermille diffusion)
56722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
567372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56747754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5675ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.diffusion = diffusion;
56767754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
56772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
56782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5680bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetDiffusion(SLEnvironmentalReverbItf self,
5681bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten     SLpermille *pDiffusion)
56822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5683ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pDiffusion)
5684ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
568572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56867754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5687ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille diffusion = this->mProperties.diffusion;
56887754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5689ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pDiffusion = diffusion;
56902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
56912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
56922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5693bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetDensity(SLEnvironmentalReverbItf self,
5694bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille density)
56952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
569672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
56977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5698ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties.density = density;
56997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
57002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
57012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
57022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5703bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetDensity(SLEnvironmentalReverbItf self,
5704bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pDensity)
57052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5706ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pDensity)
5707ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
570872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
57097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5710ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLpermille density = this->mProperties.density;
57117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5712ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pDensity = density;
57132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
57142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
57152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5716bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_SetEnvironmentalReverbProperties(
5717bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self,
5718bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const SLEnvironmentalReverbSettings *pProperties)
57192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5720ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pProperties)
5721ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
572272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
5723ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLEnvironmentalReverbSettings properties = *pProperties;
5724ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_exclusive(this);
5725ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mProperties = properties;
5726ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_exclusive(this);
57272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
57282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
57292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5730bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult EnvironmentalReverb_GetEnvironmentalReverbProperties(
5731bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLEnvironmentalReverbItf self, SLEnvironmentalReverbSettings *pProperties)
57322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5733ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pProperties)
5734ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
573572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IEnvironmentalReverb *this = (IEnvironmentalReverb *) self;
5736ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_lock_shared(this);
5737ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLEnvironmentalReverbSettings properties = this->mProperties;
5738ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    interface_unlock_shared(this);
5739ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pProperties = properties;
57402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
57412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
57422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5743bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLEnvironmentalReverbItf_
5744bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_EnvironmentalReverbItf = {
5745bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetRoomLevel,
5746bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetRoomLevel,
5747bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetRoomHFLevel,
5748bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetRoomHFLevel,
5749bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetDecayTime,
5750bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetDecayTime,
5751bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetDecayHFRatio,
5752bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetDecayHFRatio,
5753bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetReflectionsLevel,
5754bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetReflectionsLevel,
5755bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetReflectionsDelay,
5756bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetReflectionsDelay,
5757bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetReverbLevel,
5758bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetReverbLevel,
5759bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetReverbDelay,
5760bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetReverbDelay,
5761bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetDiffusion,
5762bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetDiffusion,
5763bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetDensity,
5764bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetDensity,
5765bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_SetEnvironmentalReverbProperties,
5766bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    EnvironmentalReverb_GetEnvironmentalReverbProperties
57672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
57682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5769bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Virtualizer implementation
57702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5771bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Virtualizer_SetEnabled(SLVirtualizerItf self, SLboolean enabled)
57722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
577372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVirtualizer *this = (IVirtualizer *) self;
57747754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
5775bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mEnabled = enabled;
57767754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
57772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
57782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
57792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5780bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Virtualizer_IsEnabled(SLVirtualizerItf self,
5781bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pEnabled)
57822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
5783bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pEnabled)
5784bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
578572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVirtualizer *this = (IVirtualizer *) self;
57867754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
57877754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLboolean enabled = this->mEnabled;
57887754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
57897754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pEnabled = enabled;
57902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
57912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
57922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5793bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Virtualizer_SetStrength(SLVirtualizerItf self,
5794bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille strength)
5795bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
579672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVirtualizer *this = (IVirtualizer *) self;
57977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
5798bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    this->mStrength = strength;
57997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
5800bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5801bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
5802bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
5803bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Virtualizer_GetRoundedStrength(SLVirtualizerItf self,
5804bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLpermille *pStrength)
5805bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
5806bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pStrength)
5807bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
580872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IVirtualizer *this = (IVirtualizer *) self;
58097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
58107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLpermille strength = this->mStrength;
58117754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
58127754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pStrength = strength;
5813bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5814bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
5815bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
5816bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult Virtualizer_IsStrengthSupported(SLVirtualizerItf self,
5817bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean *pSupported)
5818bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
5819bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pSupported)
5820bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
5821bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pSupported = SL_BOOLEAN_TRUE;
5822bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
5823bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
5824bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
5825bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLVirtualizerItf_ Virtualizer_VirtualizerItf = {
5826bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Virtualizer_SetEnabled,
5827bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Virtualizer_IsEnabled,
5828bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Virtualizer_SetStrength,
5829bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Virtualizer_GetRoundedStrength,
5830bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    Virtualizer_IsStrengthSupported
58312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten};
58322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
5833ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten// MIDIMessage implementation
5834ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5835ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMessage_SendMessage(SLMIDIMessageItf self, const SLuint8 *data, SLuint32 length)
5836ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
5837ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == data)
5838ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
583972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMIDIMessage *this = (IMIDIMessage *) self;
5840ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5841ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5842ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5843ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMessage_RegisterMetaEventCallback(SLMIDIMessageItf self,
5844ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    slMetaEventCallback callback, void *pContext)
5845ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
584672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMessage *this = (IMIDIMessage *) self;
58477754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5848ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMetaEventCallback = callback;
5849ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMetaEventContext = pContext;
58507754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5851ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5852ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5853ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5854ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMessage_RegisterMIDIMessageCallback(SLMIDIMessageItf self,
5855ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    slMIDIMessageCallback callback, void *pContext)
5856ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
585772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMessage *this = (IMIDIMessage *) self;
58587754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5859ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMessageCallback = callback;
5860ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMessageContext = pContext;
58617754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5862ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5863ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5864ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5865ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMessage_AddMIDIMessageCallbackFilter(SLMIDIMessageItf self,
5866ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 messageType)
5867ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
586872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMIDIMessage *this = (IMIDIMessage *) self;
5869ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5870ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5871ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5872ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMessage_ClearMIDIMessageCallbackFilter(SLMIDIMessageItf self)
5873ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
587472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IMIDIMessage *this = (IMIDIMessage *) self;
5875ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5876ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5877ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5878ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten/*static*/ const struct SLMIDIMessageItf_ MIDIMessage_MIDIMessageItf = {
5879ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMessage_SendMessage,
5880ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMessage_RegisterMetaEventCallback,
5881ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMessage_RegisterMIDIMessageCallback,
5882ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMessage_AddMIDIMessageCallbackFilter,
5883ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMessage_ClearMIDIMessageCallbackFilter
5884ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten};
5885ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5886ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten// MIDIMuteSolo implementation
5887ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5888ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_SetChannelMute(SLMIDIMuteSoloItf self, SLuint8 channel, SLboolean mute)
5889ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
589072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
5891ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint16 mask = 1 << channel;
58927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5893ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (mute)
5894ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mChannelMuteMask |= mask;
5895ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    else
5896ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mChannelMuteMask &= ~mask;
58977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5898ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5899ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5900ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5901ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_GetChannelMute(SLMIDIMuteSoloItf self, SLuint8 channel,
5902ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLboolean *pMute)
5903ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
5904ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMute)
5905ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
590672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59077754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
59087754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint16 mask = this->mChannelMuteMask;
59097754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
59107754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pMute = (mask >> channel) & 1;
5911ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5912ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5913ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5914ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_SetChannelSolo(SLMIDIMuteSoloItf self, SLuint8 channel, SLboolean solo)
5915ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
591672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
5917ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint16 mask = 1 << channel;
59187754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5919ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (solo)
5920ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mChannelSoloMask |= mask;
5921ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    else
5922ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mChannelSoloMask &= ~mask;
59237754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5924ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5925ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5926ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5927ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_GetChannelSolo(SLMIDIMuteSoloItf self, SLuint8 channel,
5928ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLboolean *pSolo)
5929ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
5930ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pSolo)
5931ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
593272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59337754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
59347754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint16 mask = this->mChannelSoloMask;
59357754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
59367754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pSolo = (mask >> channel) & 1;
5937ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5938ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5939ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5940ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_GetTrackCount(SLMIDIMuteSoloItf self, SLuint16 *pCount)
5941ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
5942ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pCount)
5943ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
594472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59457754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    // FIXME is this const? if so, remove the lock
59467754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
5947ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint16 trackCount = this->mTrackCount;
59487754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
5949ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pCount = trackCount;
5950ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5951ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5952ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5953ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_SetTrackMute(SLMIDIMuteSoloItf self, SLuint16 track, SLboolean mute)
5954ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
595572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59567754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = 1 << track;
59577754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5958ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (mute)
5959ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mTrackMuteMask |= mask;
5960ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    else
5961ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mTrackMuteMask &= ~mask;
59627754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5963ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5964ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5965ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5966ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_GetTrackMute(SLMIDIMuteSoloItf self, SLuint16 track, SLboolean *pMute)
5967ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
5968ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pMute)
5969ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
597072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59717754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
59727754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = this->mTrackMuteMask;
59737754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
59747754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pMute = (mask >> track) & 1;
5975ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5976ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5977ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5978ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_SetTrackSolo(SLMIDIMuteSoloItf self, SLuint16 track, SLboolean solo)
5979ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
598072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = 1 << track;
59827754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
5983ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (solo)
5984ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mTrackSoloMask |= mask;
5985ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    else
5986ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        this->mTrackSoloMask &= ~mask;
59877754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
5988ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
5989ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
5990ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
5991ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDIMuteSolo_GetTrackSolo(SLMIDIMuteSoloItf self, SLuint16 track, SLboolean *pSolo)
5992ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
5993ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pSolo)
5994ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
599572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDIMuteSolo *this = (IMIDIMuteSolo *) self;
59967754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
59977754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    SLuint32 mask = this->mTrackSoloMask;
59987754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
59997754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    *pSolo = (mask >> track) & 1;
6000ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6001ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6002ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6003ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten/*static*/ const struct SLMIDIMuteSoloItf_ MIDIMuteSolo_MIDIMuteSoloItf = {
6004ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_SetChannelMute,
6005ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_GetChannelMute,
6006ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_SetChannelSolo,
6007ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_GetChannelSolo,
6008ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_GetTrackCount,
6009ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_SetTrackMute,
6010ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_GetTrackMute,
6011ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_SetTrackSolo,
6012ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDIMuteSolo_GetTrackSolo
6013ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten};
6014ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6015ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten// MIDITempo implementation
6016ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6017ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITempo_SetTicksPerQuarterNote(SLMIDITempoItf self, SLuint32 tpqn)
6018ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
601972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITempo *this = (IMIDITempo *) self;
60207754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
6021ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mTicksPerQuarterNote = tpqn;
60227754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
6023ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6024ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6025ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6026ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITempo_GetTicksPerQuarterNote(SLMIDITempoItf self, SLuint32 *pTpqn)
6027ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
6028ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pTpqn)
6029ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
603072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITempo *this = (IMIDITempo *) self;
60317754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
6032ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 ticksPerQuarterNote = this->mTicksPerQuarterNote;
60337754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
6034ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pTpqn = ticksPerQuarterNote;
6035ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6036ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6037ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6038ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITempo_SetMicrosecondsPerQuarterNote(SLMIDITempoItf self, SLmicrosecond uspqn)
6039ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
604072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITempo *this = (IMIDITempo *) self;
60417754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
6042ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mMicrosecondsPerQuarterNote = uspqn;
60437754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
6044ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6045ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6046ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6047ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITempo_GetMicrosecondsPerQuarterNote(SLMIDITempoItf self, SLmicrosecond *uspqn)
6048ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
6049ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == uspqn)
6050ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
605172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITempo *this = (IMIDITempo *) self;
60527754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
6053ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 microsecondsPerQuarterNote = this->mMicrosecondsPerQuarterNote;
60547754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
6055ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *uspqn = microsecondsPerQuarterNote;
6056ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6057ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6058ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6059ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten/*static*/ const struct SLMIDITempoItf_ MIDITempo_MIDITempoItf = {
6060ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITempo_SetTicksPerQuarterNote,
6061ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITempo_GetTicksPerQuarterNote,
6062ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITempo_SetMicrosecondsPerQuarterNote,
6063ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITempo_GetMicrosecondsPerQuarterNote
6064ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten};
6065ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6066ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten// MIDITime implementation
6067ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6068ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITime_GetDuration(SLMIDITimeItf self, SLuint32 *pDuration)
6069ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
6070ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pDuration)
6071ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
607272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITime *this = (IMIDITime *) self;
6073ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 duration = this->mDuration;
6074ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pDuration = duration;
6075ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6076ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6077ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6078ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITime_SetPosition(SLMIDITimeItf self, SLuint32 position)
6079ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
608072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITime *this = (IMIDITime *) self;
60817754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_poke(this);
6082ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mPosition = position;
60837754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_poke(this);
6084ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6085ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6086ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6087ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITime_GetPosition(SLMIDITimeItf self, SLuint32 *pPosition)
6088ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
6089ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pPosition)
6090ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
609172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITime *this = (IMIDITime *) self;
60927754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_peek(this);
6093ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 position = this->mPosition;
60947754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_peek(this);
6095ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pPosition = position;
6096ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6097ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6098ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6099ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITime_SetLoopPoints(SLMIDITimeItf self, SLuint32 startTick, SLuint32 numTicks)
6100ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
610172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITime *this = (IMIDITime *) self;
61027754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_exclusive(this);
6103ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mStartTick = startTick;
6104ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    this->mNumTicks = numTicks;
61057754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_exclusive(this);
6106ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6107ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6108ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6109ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kastenstatic SLresult MIDITime_GetLoopPoints(SLMIDITimeItf self, SLuint32 *pStartTick,
6110ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 *pNumTicks)
6111ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten{
6112ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    if (NULL == pStartTick || NULL == pNumTicks)
6113ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
611472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IMIDITime *this = (IMIDITime *) self;
61157754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_lock_shared(this);
6116ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 startTick = this->mStartTick;
6117ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    SLuint32 numTicks = this->mNumTicks;
61187754b1c33590dbb03531f59e6f108818bc303f4fGlenn Kasten    interface_unlock_shared(this);
6119ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pStartTick = startTick;
6120ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    *pNumTicks = numTicks;
6121ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    return SL_RESULT_SUCCESS;
6122ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten}
6123ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
6124ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten/*static */ const struct SLMIDITimeItf_ MIDITime_MIDITimeItf = {
6125ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITime_GetDuration,
6126ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITime_SetPosition,
6127ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITime_GetPosition,
6128ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITime_SetLoopPoints,
6129ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten    MIDITime_GetLoopPoints
6130ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten};
6131ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten
613272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten// Runs every graphics frame (50 Hz) to update audio
613372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten
613472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic void *frame_body(void *arg)
613572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten{
613672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CEngine *this = (CEngine *) arg;
613772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    for (;;) {
613872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        usleep(20000*50);
613972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned i;
614072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        for (i = 0; i < INSTANCE_MAX; ++i) {
614172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            IObject *instance = (IObject *) this->mEngine.mInstances[i];
614272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            if (NULL == instance)
614372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten                continue;
614472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            if (instance->mClass != &AudioPlayer_class)
614572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten                continue;
614672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            write(1, ".", 1);
614772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        }
614872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    }
614972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    return NULL;
615072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten}
615172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten
61522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* Initial entry points */
61532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
61542045b02407f6ac0a570faee3157b24317c8a69e0Glenn KastenSLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
61552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
61562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
61572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
61582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (NULL == pEngine)
61592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
6160bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pEngine = NULL;
6161bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // default values
6162bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLboolean threadSafe = SL_BOOLEAN_TRUE;
616329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
6164bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != pEngineOptions) {
6165bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        SLuint32 i;
6166ba51587362ce7ed3fe3be37e481e67b7caed7670Glenn Kasten        const SLEngineOption *option = pEngineOptions;
6167bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        for (i = 0; i < numOptions; ++i, ++option) {
6168bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            switch (option->feature) {
6169bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            case SL_ENGINEOPTION_THREADSAFE:
6170bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                threadSafe = (SLboolean) option->data;
6171bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                break;
6172bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            case SL_ENGINEOPTION_LOSSOFCONTROL:
617329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                lossOfControlGlobal = (SLboolean) option->data;
6174bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                break;
6175bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            default:
6176bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
6177bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
6178bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
6179bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
6180bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask;
6181bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result = checkInterfaces(&Engine_class, numInterfaces,
6182bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
61832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SL_RESULT_SUCCESS != result)
61842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return result;
618572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    CEngine *this = (CEngine *)
618629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten        construct(&Engine_class, exposedMask, NULL);
6187bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == this)
61882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_MEMORY_FAILURE;
618929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
619029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    this->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
619183f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten    this->mEngineCapabilities.mThreadSafe = threadSafe;
619272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    int ok;
619372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    ok = pthread_create(&this->mFrameThread, (const pthread_attr_t *) NULL,
619472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        frame_body, this);
619572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    assert(ok == 0);
6196bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pEngine = &this->mObject.mItf;
61972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    return SL_RESULT_SUCCESS;
61982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
61992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
62002045b02407f6ac0a570faee3157b24317c8a69e0Glenn KastenSLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(
62012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLuint32 *pNumSupportedInterfaces)
62022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
6203bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pNumSupportedInterfaces)
62042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
6205bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pNumSupportedInterfaces = Engine_class.mInterfaceCount;
6206bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
62072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
62082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
62092045b02407f6ac0a570faee3157b24317c8a69e0Glenn KastenSLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index,
62102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLInterfaceID *pInterfaceId)
62112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
6212bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (sizeof(Engine_interfaces)/sizeof(Engine_interfaces[0]) < index)
6213bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
6214bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL == pInterfaceId)
62152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
6216bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pInterfaceId = &SL_IID_array[Engine_interfaces[index].mMPH];
6217bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return SL_RESULT_SUCCESS;
62182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
62192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
6220bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT
6221bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
6222bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* OutputMixExt implementation */
6223bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
6224bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Used by SDL and Android but not specific to or dependent on either platform
62252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
6226bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void OutputMixExt_FillBuffer(SLOutputMixExtItf self, void *pBuffer,
6227bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 size)
62282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
62292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // Force to be a multiple of a frame, assumes stereo 16-bit PCM
62302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    size &= ~3;
623172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IOutputMixExt *thisExt =
623272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        (IOutputMixExt *) self;
623329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    // FIXME Finding one interface from another, but is it exposed?
623472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IOutputMix *this =
623572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        &((COutputMix *) thisExt->mThis)->mOutputMix;
62362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    unsigned activeMask = this->mActiveMask;
62372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    struct Track *track = &this->mTracks[0];
62382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    unsigned i;
62392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SLboolean mixBufferHasData = SL_BOOLEAN_FALSE;
62402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // FIXME O(32) loop even when few tracks are active.
62412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // To avoid loop, use activeMask to check for active track(s)
62422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // and decide whether we actually need to copy or mix.
62432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    for (i = 0; 0 != activeMask; ++i, ++track, activeMask >>= 1) {
62442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        assert(i < 32);
62452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (!(activeMask & 1))
62462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            continue;
62472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // track is allocated
624872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IPlay *play = track->mPlay;
62492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (NULL == play)
62502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            continue;
62512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // track is initialized
62522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (SL_PLAYSTATE_PLAYING != play->mState)
62532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            continue;
62542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        // track is playing
62552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        void *dstWriter = pBuffer;
62562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        unsigned desired = size;
62572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        SLboolean trackContributedToMix = SL_BOOLEAN_FALSE;
62582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        while (desired > 0) {
625972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            IBufferQueue *bufferQueue;
62602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            const struct BufferHeader *oldFront, *newFront, *rear;
62612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            unsigned actual = desired;
62622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (track->mAvail < actual)
62632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                actual = track->mAvail;
62642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // force actual to be a frame multiple
62652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (actual > 0) {
62662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // FIXME check for either mute or volume 0
62672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // in which case skip the input buffer processing
62682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                assert(NULL != track->mReader);
62692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // FIXME && gain == 1.0
62702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                if (mixBufferHasData) {
6271bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    stereo *mixBuffer = (stereo *) dstWriter;
6272bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    const stereo *source = (const stereo *) track->mReader;
62732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    unsigned j;
6274bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    for (j = 0; j < actual; j += sizeof(stereo), ++mixBuffer,
6275bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                        ++source) {
62762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        // apply gain here
62772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        mixBuffer->left += source->left;
62782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        mixBuffer->right += source->right;
62792045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    }
62802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                } else {
62812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    memcpy(dstWriter, track->mReader, actual);
62822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    trackContributedToMix = SL_BOOLEAN_TRUE;
62832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                }
62842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                dstWriter = (char *) dstWriter + actual;
62852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                desired -= actual;
62862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                track->mReader = (char *) track->mReader + actual;
62872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                track->mAvail -= actual;
62882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                if (track->mAvail == 0) {
62892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    bufferQueue = track->mBufferQueue;
62902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    if (NULL != bufferQueue) {
62912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        oldFront = bufferQueue->mFront;
62922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        rear = bufferQueue->mRear;
62932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        assert(oldFront != rear);
62942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        newFront = oldFront;
6295bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                        if (++newFront ==
6296bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                            &bufferQueue->mArray[bufferQueue->mNumBuffers])
62972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                            newFront = bufferQueue->mArray;
62982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        bufferQueue->mFront = (struct BufferHeader *) newFront;
62992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        assert(0 < bufferQueue->mState.count);
63002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        --bufferQueue->mState.count;
63012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        // FIXME here or in Enqueue?
63022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        ++bufferQueue->mState.playIndex;
6303bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                        // FIXME a good time to do an early warning
63042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        // callback depending on buffer count
63052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    }
63062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                }
63072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                continue;
63082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            }
63092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            // actual == 0
63102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            bufferQueue = track->mBufferQueue;
63112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (NULL != bufferQueue) {
63122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                oldFront = bufferQueue->mFront;
63132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                rear = bufferQueue->mRear;
63142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                if (oldFront != rear) {
63152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastengot_one:
63162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    assert(0 < bufferQueue->mState.count);
63172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    track->mReader = oldFront->mBuffer;
63182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    track->mAvail = oldFront->mSize;
63192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    continue;
63202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                }
63212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // FIXME should be able to configure when to
63222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // kick off the callback e.g. high/low water-marks etc.
6323bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                // need data but none available, attempt a desperate callback
63242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                slBufferQueueCallback callback = bufferQueue->mCallback;
63252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                if (NULL != callback) {
6326bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    (*callback)((SLBufferQueueItf) bufferQueue,
6327bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                        bufferQueue->mContext);
6328bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    // if lucky, the callback enqueued a buffer
63292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                    if (rear != bufferQueue->mRear)
63302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                        goto got_one;
6331bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    // unlucky, queue still empty, the callback failed
63322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                }
63332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // here on underflow due to no callback, or failed callback
63342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // FIXME underflow, send silence (or previous buffer?)
63352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // we did a callback to try to kick start again but failed
63362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                // should log this
63372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            }
6338bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            // no buffer queue or underflow, clear out rest of partial buffer
63392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            if (!mixBufferHasData && trackContributedToMix)
63402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten                memset(dstWriter, 0, actual);
63412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            break;
63422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        }
63432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        if (trackContributedToMix)
63442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten            mixBufferHasData = SL_BOOLEAN_TRUE;
63452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
63462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // No active tracks, so output silence
63472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (!mixBufferHasData)
63482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        memset(pBuffer, 0, size);
63492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
63502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
6351bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLOutputMixExtItf_ OutputMixExt_OutputMixExtItf = {
6352bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    OutputMixExt_FillBuffer
6353bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
6354bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
6355bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_OUTPUTMIXEXT
6356bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
63572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SDL
63582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
6359bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// FIXME move to separate source file
6360bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
63612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* SDL platform implementation */
63622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
63632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic void SDLCALL SDL_callback(void *context, Uint8 *stream, int len)
63642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
63652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    assert(len > 0);
6366bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    OutputMixExt_FillBuffer((SLOutputMixExtItf) context, stream,
6367bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        (SLuint32) len);
63682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
63692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
63702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenvoid SDL_start(SLObjectItf self)
63712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{
6372bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //assert(self != NULL);
63732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    // FIXME make this an operation on Object: GetClass
637472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    //IObject *this = (IObject *) self;
6375bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    //assert(&OutputMix_class == this->mClass);
6376bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLresult result;
6377bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLOutputMixExtItf OutputMixExt;
6378bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    result = (*self)->GetInterface(self, SL_IID_OUTPUTMIXEXT, &OutputMixExt);
6379bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
63802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
63812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SDL_AudioSpec fmt;
63822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    fmt.freq = 44100;
63832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    fmt.format = AUDIO_S16;
63842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    fmt.channels = 2;
63852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    fmt.samples = 256;
63862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    fmt.callback = SDL_callback;
6387bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME should be a GetInterface
638872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    // fmt.userdata = &((COutputMix *) this)->mOutputMixExt;
6389bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    fmt.userdata = (void *) OutputMixExt;
63902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
63912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    if (SDL_OpenAudio(&fmt, NULL) < 0) {
63922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
63932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        exit(1);
63942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    }
63952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten    SDL_PauseAudio(0);
63962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten}
63972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
6398bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SDL
6399d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
6400d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* End */
6401