summaryrefslogtreecommitdiffstats
path: root/opensles/libopensles/sles_allinclusive.h
blob: 64ddcc618fe5a4c54155c35c8aefa3cc8d848917 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** \file sles_allinclusive.h Everything including the kitchen sink */

#include "SLES/OpenSLES.h"
#ifdef ANDROID
#include "SLES/OpenSLES_Android.h"
#endif
#include <stddef.h> // offsetof
#include <stdlib.h> // malloc
#include <string.h> // memcmp
#include <stdio.h>  // debugging
#include <assert.h> // debugging
#include <pthread.h>
#include <unistd.h> // usleep
#include <errno.h>

#ifndef __cplusplus
typedef int bool;
#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif
#endif

// The OpenSLES.h definitions of SL_PROFILES_... have casts, so are unusable by preprocessor
#define USE_PROFILES_PHONE    0x1   // == SL_PROFILES_PHONE
#define USE_PROFILES_MUSIC    0x2   // == SL_PROFILES_MUSIC
#define USE_PROFILES_GAME     0x4   // == SL_PROFILES_GAME
// Pseudo profiles, used to decide whether to include code for incomplete or untested features
// Features that are not in union of all profiles: audio recorder, LED, Vibra
#define USE_PROFILES_OPTIONAL 0x8
// Features that are in the intersection of all profiles:
// object priorities, preemption, loss of control, device configuration
#define USE_PROFILES_BASE     0x10

#include "MPH.h"
#include "MPH_to.h"
#include "devices.h"
#include "OpenSLESUT.h"
#include "ThreadPool.h"

typedef struct CAudioPlayer_struct CAudioPlayer;
typedef struct CAudioRecorder_struct CAudioRecorder;
typedef struct C3DGroup_struct C3DGroup;
typedef struct COutputMix_struct COutputMix;

#ifdef USE_SNDFILE
#include <sndfile.h>
#include "SLSndFile.h"
#endif // USE_SNDFILE

#ifdef USE_SDL
#include <SDL/SDL_audio.h>
#endif // USE_SDL

#ifdef ANDROID
#include <utils/Log.h>
#include <utils/KeyedVector.h>
#include "SLES/OpenSLES_AndroidConfiguration.h"
#include "media/AudioSystem.h"
#include "media/mediarecorder.h"
#include "media/AudioRecord.h"
#include "media/AudioTrack.h"
#include "media/mediaplayer.h"
#ifndef USE_BACKPORT
#include "media/AudioEffect.h"
#include "media/EffectApi.h"
#include "media/EffectEqualizerApi.h"
#include "media/EffectBassBoostApi.h"
#include "media/EffectVirtualizerApi.h"
#include "media/EffectPresetReverbApi.h"
#include "media/EffectEnvironmentalReverbApi.h"
#endif
#include <utils/String8.h>
#define ANDROID_SL_MILLIBEL_MAX 0
#include <binder/ProcessState.h>
#include "android_sles_conversions.h"
#ifndef USE_BACKPORT
#include "android_SfPlayer.h"
#include "android_OutputMix.h"
#endif
#include "android_AudioRecorder.h"
#endif

#define STEREO_CHANNELS 2

#ifdef USE_OUTPUTMIXEXT
#include "OutputMixExt.h"
#endif

#include "sllog.h"

// Hook functions

typedef void (*VoidHook)(void *self);
//typedef SLresult (*ResultHook)(void *self);
typedef SLresult (*AsyncHook)(void *self, SLboolean async);
typedef bool (*BoolHook)(void *self);

// Describes how an interface is related to a given class, used in iid_vtable::mInterface

#define INTERFACE_IMPLICIT            0 // no need for application to request prior to GetInterface
#define INTERFACE_EXPLICIT            1 // must be requested explicitly during object creation
#define INTERFACE_DYNAMIC             2 // can be requested after object creation
#define INTERFACE_UNAVAILABLE         3 // this interface is not available on objects of this class
#define INTERFACE_IMPLICIT_PREREALIZE 4 // implicit, and can call GetInterface before Realize
#define INTERFACE_EXPLICIT_PREREALIZE 5 // explicit, and can call GetInterface before Realize
// 6 and 7 are reserved for the meaningless DYNAMIC_PREREALIZE and UNAVAILABLE_PREREALIZE
// note that INTERFACE_OPTIONAL is always re-mapped to one of the above
#define INTERFACE_PREREALIZE          4 // bit-mask to test for calling GetInterface before Realize

// Profile-specific interfaces

#if USE_PROFILES & USE_PROFILES_BASE
#define INTERFACE_IMPLICIT_BASE       INTERFACE_IMPLICIT
#define INTERFACE_EXPLICIT_BASE       INTERFACE_EXPLICIT
#else
#define INTERFACE_IMPLICIT_BASE       INTERFACE_UNAVAILABLE
#define INTERFACE_EXPLICIT_BASE       INTERFACE_UNAVAILABLE
#endif

#if USE_PROFILES & USE_PROFILES_GAME
#define INTERFACE_DYNAMIC_GAME        INTERFACE_DYNAMIC
#define INTERFACE_EXPLICIT_GAME       INTERFACE_EXPLICIT
#else
#define INTERFACE_DYNAMIC_GAME        INTERFACE_OPTIONAL
#define INTERFACE_EXPLICIT_GAME       INTERFACE_OPTIONAL
#endif

#if USE_PROFILES & USE_PROFILES_MUSIC
#define INTERFACE_DYNAMIC_MUSIC       INTERFACE_DYNAMIC
#else
#define INTERFACE_DYNAMIC_MUSIC       INTERFACE_OPTIONAL
#endif

#if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC)
#define INTERFACE_DYNAMIC_GAME_MUSIC  INTERFACE_DYNAMIC
#define INTERFACE_EXPLICIT_GAME_MUSIC INTERFACE_EXPLICIT
#else
#define INTERFACE_DYNAMIC_GAME_MUSIC  INTERFACE_OPTIONAL
#define INTERFACE_EXPLICIT_GAME_MUSIC INTERFACE_OPTIONAL
#endif

#if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE)
#define INTERFACE_EXPLICIT_GAME_PHONE INTERFACE_EXPLICIT
#else
#define INTERFACE_EXPLICIT_GAME_PHONE INTERFACE_OPTIONAL
#endif

#if USE_PROFILES & USE_PROFILES_OPTIONAL
#define INTERFACE_OPTIONAL            INTERFACE_EXPLICIT
#define INTERFACE_DYNAMIC_OPTIONAL    INTERFACE_DYNAMIC
#else
#define INTERFACE_OPTIONAL            INTERFACE_UNAVAILABLE
#define INTERFACE_DYNAMIC_OPTIONAL    INTERFACE_UNAVAILABLE
#endif

// Describes how an interface is related to a given object

#define INTERFACE_UNINITIALIZED 0  ///< not available
#define INTERFACE_INITIALIZED   1  ///< not requested at object creation time
#define INTERFACE_EXPOSED       2  ///< requested at object creation time
#define INTERFACE_ADDING_1      3  ///< part 1 of asynchronous AddInterface, pending
#define INTERFACE_ADDING_2      4  ///< synchronous AddInterface, or part 2 of asynchronous
#define INTERFACE_ADDED         5  ///< AddInterface has completed
#define INTERFACE_REMOVING      6  ///< unlocked phase of (synchronous) RemoveInterface
#define INTERFACE_SUSPENDING    7  ///< suspend in progress
#define INTERFACE_SUSPENDED     8  ///< suspend has completed
#define INTERFACE_RESUMING_1    9  ///< part 1 of asynchronous ResumeInterface, pending
#define INTERFACE_RESUMING_2   10  ///< synchronous ResumeInterface, or part 2 of asynchronous
#define INTERFACE_ADDING_1A    11  ///< part 1 of asynchronous AddInterface, aborted
#define INTERFACE_RESUMING_1A  12  ///< part 1 of asynchronous ResumeInterface, aborted


// Maps an interface ID to its offset within the class that exposes it

struct iid_vtable {
    unsigned char mMPH;         // primary MPH for this interface, does not include any aliases
    unsigned char mInterface;   // relationship of interface to this class
    /*size_t*/ unsigned short mOffset;
};

// Per-class const data shared by all instances of the same class

typedef struct {
    const struct iid_vtable *mInterfaces;   // maps interface index to info about that interface
    SLuint32 mInterfaceCount;  // number of possible interfaces
    const signed char *mMPH_to_index;
    const char * const mName;
    size_t mSize;
    SLuint32 mObjectID;
    // hooks
    AsyncHook mRealize;
    AsyncHook mResume;
    VoidHook mDestroy;
    BoolHook mPreDestroy;
} ClassTable;

// BufferHeader describes each element of a BufferQueue, other than the data

typedef struct {
    const void *mBuffer;
    SLuint32 mSize;
} BufferHeader;

#ifdef __cplusplus
#define this this_
#endif

#ifdef USE_SNDFILE

#define SndFile_BUFSIZE 512     // in 16-bit samples
#define SndFile_NUMBUFS 2

struct SndFile {
    // save URI also?
    SLchar *mPathname;
    SNDFILE *mSNDFILE;
    SF_INFO mSfInfo;
    pthread_mutex_t mMutex; // protects mSNDFILE only
    SLboolean mEOF;         // sf_read returned zero sample frames
    SLuint32 mWhich;        // which buffer to use next
    short mBuffer[SndFile_BUFSIZE * SndFile_NUMBUFS];
};

#endif // USE_SNDFILE

/* Our own merged version of SLDataSource and SLDataSink */

typedef union {
    SLuint32 mLocatorType;
    SLDataLocator_Address mAddress;
    SLDataLocator_BufferQueue mBufferQueue;
    SLDataLocator_IODevice mIODevice;
    SLDataLocator_MIDIBufferQueue mMIDIBufferQueue;
    SLDataLocator_OutputMix mOutputMix;
    SLDataLocator_URI mURI;
#ifdef ANDROID
    SLDataLocator_AndroidFD mFD;
#endif
} DataLocator;

typedef union {
    SLuint32 mFormatType;
    SLDataFormat_PCM mPCM;
    SLDataFormat_MIME mMIME;
} DataFormat;

typedef struct {
    union {
        SLDataSource mSource;
        SLDataSink mSink;
        struct {
            DataLocator *pLocator;
            DataFormat *pFormat;
        } mNeutral;
    } u;
    DataLocator mLocator;
    DataFormat mFormat;
} DataLocatorFormat;

/* Interface structures */

typedef struct Object_interface {
    const struct SLObjectItf_ *mItf;    // const
    // field mThis would be redundant within an IObject, so we substitute mEngine
    struct Engine_interface *mEngine;   // const
    const ClassTable *mClass;       // const
    SLuint32 mInstanceID;           // const for debugger and for RPC, 0 means unpublished
    slObjectCallback mCallback;
    void *mContext;
    unsigned mGottenMask;           ///< bit-mask of interfaces exposed or added, then gotten
    unsigned mLossOfControlMask;    // interfaces with loss of control enabled
    unsigned mAttributesMask;       // attributes which have changed since last sync
#if USE_PROFILES & USE_PROFILES_BASE
    SLint32 mPriority;
#endif
    pthread_mutex_t mMutex;
#ifdef USE_DEBUG
    pthread_t mOwner;
    const char *mFile;
    int mLine;
#endif
    pthread_cond_t mCond;
    SLuint8 mState;                 // really SLuint32, but SLuint8 to save space
#if USE_PROFILES & USE_PROFILES_BASE
    SLuint8 mPreemptable;           // really SLboolean, but SLuint8 to save space
#else
    SLuint8 mPadding;
#endif
    SLuint8 mStrongRefCount;        // number of strong references to this object
    // (object cannot be destroyed as long as > 0, and referrers _prefer_ it stay in Realized state)
    // for best alignment, do not add any fields here
#define INTERFACES_Default 1
    SLuint8 mInterfaceStates[INTERFACES_Default];    // state of each of interface
    // do not add any fields here
} IObject;

#include "locks.h"

typedef struct {
    const struct SL3DCommitItf_ *mItf;
    IObject *mThis;
    SLboolean mDeferred;
    SLuint32 mGeneration;   // incremented each master clock cycle
    SLuint32 mWaiting;      // number of threads waiting in Commit
} I3DCommit;

enum CartesianSphericalActive {
    CARTESIAN_COMPUTED_SPHERICAL_SET,
    CARTESIAN_REQUESTED_SPHERICAL_SET,
    CARTESIAN_UNKNOWN_SPHERICAL_SET,
    CARTESIAN_SET_SPHERICAL_COMPUTED,   // not in 1.0.1
    CARTESIAN_SET_SPHERICAL_REQUESTED,  // not in 1.0.1
    CARTESIAN_SET_SPHERICAL_UNKNOWN
};

typedef struct {
    const struct SL3DDopplerItf_ *mItf;
    IObject *mThis;
    // The API allows client to specify either Cartesian and spherical velocities.
    // But an implementation will likely prefer one or the other. So for
    // maximum portablity, we maintain both units and an indication of which
    // unit was set most recently. In addition, we keep a flag saying whether
    // the other unit has been derived yet. It can take significant time
    // to compute the other unit, so this may be deferred to another thread.
    // For this reason we also keep an indication of whether the secondary
    // has been computed yet, and its accuracy.
    // Though only one unit is primary at a time, a union is inappropriate:
    // the application might read in both units (not in 1.0.1),
    // and due to multi-threading concerns.
    SLVec3D mVelocityCartesian;
    struct {
        SLmillidegree mAzimuth;
        SLmillidegree mElevation;
        SLmillidegree mSpeed;
    } mVelocitySpherical;
    enum CartesianSphericalActive mVelocityActive;
    SLpermille mDopplerFactor;
} I3DDoppler;

typedef struct {
    const struct SL3DGroupingItf_ *mItf;
    IObject *mThis;
    C3DGroup *mGroup;   // strong reference to associated group or NULL
} I3DGrouping;

enum AnglesVectorsActive {
    ANGLES_COMPUTED_VECTORS_SET,    // not in 1.0.1
    ANGLES_REQUESTED_VECTORS_SET,   // not in 1.0.1
    ANGLES_UNKNOWN_VECTORS_SET,
    ANGLES_SET_VECTORS_COMPUTED,
    ANGLES_SET_VECTORS_REQUESTED,
    ANGLES_SET_VECTORS_UNKNOWN
};

typedef struct {
    const struct SL3DLocationItf_ *mItf;
    IObject *mThis;
    SLVec3D mLocationCartesian;
    struct {
        SLmillidegree mAzimuth;
        SLmillidegree mElevation;
        SLmillimeter mDistance;
    } mLocationSpherical;
    enum CartesianSphericalActive mLocationActive;
    struct {
        SLmillidegree mHeading;
        SLmillidegree mPitch;
        SLmillidegree mRoll;
    } mOrientationAngles;
    struct {
        SLVec3D mFront;
        SLVec3D mAbove;
        SLVec3D mUp;
    } mOrientationVectors;
    enum AnglesVectorsActive mOrientationActive;
    // Rotations can be slow, so are deferred.
    SLmillidegree mTheta;
    SLVec3D mAxis;
    SLboolean mRotatePending;
} I3DLocation;

typedef struct {
    const struct SL3DMacroscopicItf_ *mItf;
    IObject *mThis;
    struct {
        SLmillimeter mWidth;
        SLmillimeter mHeight;
        SLmillimeter mDepth;
    } mSize;
    struct {
        SLmillimeter mHeading;
        SLmillimeter mPitch;
        SLmillimeter mRoll;
    } mOrientationAngles;
    struct {
        SLVec3D mFront;
        SLVec3D mAbove;
        SLVec3D mUp;
    } mOrientationVectors;
    enum AnglesVectorsActive mOrientationActive;
    // Rotations can be slow, so are deferred.
    SLmillidegree mTheta;
    SLVec3D mAxis;
    SLboolean mRotatePending;
} I3DMacroscopic;

typedef struct {
    const struct SL3DSourceItf_ *mItf;
    IObject *mThis;
    SLboolean mHeadRelative;
    SLboolean mRolloffMaxDistanceMute;
    SLmillimeter mMaxDistance;
    SLmillimeter mMinDistance;
    SLmillidegree mConeInnerAngle;
    SLmillidegree mConeOuterAngle;
    SLmillibel mConeOuterLevel;
    SLpermille mRolloffFactor;
    SLpermille mRoomRolloffFactor;
    SLuint8 mDistanceModel;
} I3DSource;

typedef struct {
    const struct SLAudioDecoderCapabilitiesItf_ *mItf;
    IObject *mThis;
} IAudioDecoderCapabilities;

typedef struct {
    const struct SLAudioEncoderItf_ *mItf;
    IObject *mThis;
    SLAudioEncoderSettings mSettings;
} IAudioEncoder;

typedef struct {
    const struct SLAudioEncoderCapabilitiesItf_ *mItf;
    IObject *mThis;
} IAudioEncoderCapabilities;

typedef struct {
    const struct SLAudioIODeviceCapabilitiesItf_ *mItf;
    IObject *mThis;
    slAvailableAudioInputsChangedCallback mAvailableAudioInputsChangedCallback;
    void *mAvailableAudioInputsChangedContext;
    slAvailableAudioOutputsChangedCallback mAvailableAudioOutputsChangedCallback;
    void *mAvailableAudioOutputsChangedContext;
    slDefaultDeviceIDMapChangedCallback mDefaultDeviceIDMapChangedCallback;
    void *mDefaultDeviceIDMapChangedContext;
} IAudioIODeviceCapabilities;

typedef struct {
    const struct SLBassBoostItf_ *mItf;
    IObject *mThis;
    SLboolean mEnabled;
    SLpermille mStrength;
#if defined(ANDROID) && !defined(USE_BACKPORT)
    effect_descriptor_t mBassBoostDescriptor;
    android::sp<android::AudioEffect> mBassBoostEffect;
#endif
} IBassBoost;

typedef struct BufferQueue_interface {
    const struct SLBufferQueueItf_ *mItf;
    IObject *mThis;
    SLBufferQueueState mState;
    slBufferQueueCallback mCallback;
    void *mContext;
    // originally SLuint32, but range-checked down to SLuint16
    SLuint16 mNumBuffers;
    /*SLboolean*/ SLuint16 mClearRequested;
    BufferHeader *mArray;
    BufferHeader *mFront, *mRear;
#ifdef ANDROID
    SLuint32 mSizeConsumed;
#endif
    // saves a malloc in the typical case
#define BUFFER_HEADER_TYPICAL 4
    BufferHeader mTypical[BUFFER_HEADER_TYPICAL+1];
} IBufferQueue;

#define MAX_DEVICE 2    // hard-coded array size for default in/out

typedef struct {
    const struct SLDeviceVolumeItf_ *mItf;
    IObject *mThis;
    SLint32 mVolume[MAX_DEVICE];
} IDeviceVolume;

typedef struct {
    const struct SLDynamicInterfaceManagementItf_ *mItf;
    IObject *mThis;
    slDynamicInterfaceManagementCallback mCallback;
    void *mContext;
} IDynamicInterfaceManagement;

typedef struct {
    const struct SLDynamicSourceItf_ *mItf;
    IObject *mThis;
    SLDataSource *mDataSource;
} IDynamicSource;

// private

struct EnableLevel {
    SLboolean mEnable;
    SLmillibel mSendLevel;
};

// indexes into IEffectSend.mEnableLevels

#define AUX_ENVIRONMENTALREVERB 0
#define AUX_PRESETREVERB        1
#define AUX_MAX                 2

typedef struct {
    const struct SLEffectSendItf_ *mItf;
    IObject *mThis;
    struct EnableLevel mEnableLevels[AUX_MAX];  // wet enable and volume per effect type
} IEffectSend;

typedef struct Engine_interface {
    const struct SLEngineItf_ *mItf;
    IObject *mThis;
    SLboolean mLossOfControlGlobal;
#ifdef USE_SDL
    COutputMix *mOutputMix; // SDL pulls PCM from an arbitrary IOutputMixExt
#endif
    // Each engine is its own universe.
    SLuint32 mInstanceCount;
    unsigned mInstanceMask; // 1 bit per active object
    unsigned mChangedMask;  // objects which have changed since last sync
#define MAX_INSTANCE 32     // maximum active objects per engine, see mInstanceMask
    IObject *mInstances[MAX_INSTANCE];
    SLboolean mShutdown;
    SLboolean mShutdownAck;
    ThreadPool mThreadPool; // for asynchronous operations
#if defined(ANDROID) && !defined(USE_BACKPORT)
    // FIXME number of presets will only be saved in IEqualizer, preset names will not be stored
    SLuint32 mEqNumPresets;
    char** mEqPresetNames;
#endif
} IEngine;

typedef struct {
    const struct SLEngineCapabilitiesItf_ *mItf;
    IObject *mThis;
    SLboolean mThreadSafe;
    // const
    SLuint32 mMaxIndexLED;
    SLuint32 mMaxIndexVibra;
} IEngineCapabilities;

typedef struct {
    const struct SLEnvironmentalReverbItf_ *mItf;
    IObject *mThis;
    SLEnvironmentalReverbSettings mProperties;
#if defined(ANDROID) && !defined(USE_BACKPORT)
    effect_descriptor_t mEnvironmentalReverbDescriptor;
    android::sp<android::AudioEffect> mEnvironmentalReverbEffect;
#endif
} IEnvironmentalReverb;

struct EqualizerBand {
    SLmilliHertz mMin;
    SLmilliHertz mCenter;
    SLmilliHertz mMax;
};

#if defined(ANDROID) && !defined(USE_BACKPORT)
#define MAX_EQ_BANDS 0
#else
#define MAX_EQ_BANDS 4  // compile-time limit, runtime limit may be smaller
#endif

typedef struct {
    const struct SLEqualizerItf_ *mItf;
    IObject *mThis;
    SLboolean mEnabled;
    SLuint16 mPreset;
#if 0 < MAX_EQ_BANDS
    SLmillibel mLevels[MAX_EQ_BANDS];
#endif
    // const to end of struct
    SLuint16 mNumPresets;
    SLuint16 mNumBands;
#if !defined(ANDROID) || defined(USE_BACKPORT)
    const struct EqualizerBand *mBands;
    const struct EqualizerPreset *mPresets;
#endif
    SLmillibel mBandLevelRangeMin;
    SLmillibel mBandLevelRangeMax;
#if defined(ANDROID) && !defined(USE_BACKPORT)
    effect_descriptor_t mEqDescriptor;
    android::sp<android::AudioEffect> mEqEffect;
#endif
} IEqualizer;

#define MAX_LED_COUNT 32

typedef struct {
    const struct SLLEDArrayItf_ *mItf;
    IObject *mThis;
    SLuint32 mLightMask;
    SLHSL mColors[MAX_LED_COUNT];
    // const
    SLuint8 mCount;
} ILEDArray;

typedef struct {
    const struct SLMetadataExtractionItf_ *mItf;
    IObject *mThis;
    SLuint32 mKeySize;
    const void *mKey;
    SLuint32 mKeyEncoding;
    const SLchar *mValueLangCountry;
    SLuint32 mValueEncoding;
    SLuint8 mFilterMask;
    int mKeyFilter;
} IMetadataExtraction;

typedef struct {
    const struct SLMetadataTraversalItf_ *mItf;
    IObject *mThis;
    SLuint32 mIndex;
    SLuint32 mMode;
    SLuint32 mCount;
    SLuint32 mSize;
} IMetadataTraversal;

typedef struct {
    const struct SLMIDIMessageItf_ *mItf;
    IObject *mThis;
    slMetaEventCallback mMetaEventCallback;
    void *mMetaEventContext;
    slMIDIMessageCallback mMessageCallback;
    void *mMessageContext;
    SLuint8 mMessageTypes;
} IMIDIMessage;

typedef struct {
    const struct SLMIDIMuteSoloItf_ *mItf;
    IObject *mThis;
    SLuint16 mChannelMuteMask;
    SLuint16 mChannelSoloMask;
    SLuint32 mTrackMuteMask;
    SLuint32 mTrackSoloMask;
    // const
    SLuint16 mTrackCount;
} IMIDIMuteSolo;

typedef struct {
    const struct SLMIDITempoItf_ *mItf;
    IObject *mThis;
    SLuint32 mTicksPerQuarterNote;
    SLuint32 mMicrosecondsPerQuarterNote;
} IMIDITempo;

typedef struct {
    const struct SLMIDITimeItf_ *mItf;
    IObject *mThis;
    SLuint32 mDuration;
    SLuint32 mPosition;
    SLuint32 mStartTick;
    SLuint32 mNumTicks;
} IMIDITime;

typedef struct {
    const struct SLMuteSoloItf_ *mItf;
    IObject *mThis;
    // fields that were formerly here are now at CAudioPlayer
} IMuteSolo;

#define MAX_TRACK 32        // see mActiveMask

typedef struct {
    const struct SLOutputMixItf_ *mItf;
    IObject *mThis;
    slMixDeviceChangeCallback mCallback;
    void *mContext;
} IOutputMix;

#ifdef USE_OUTPUTMIXEXT
typedef struct {
    const struct SLOutputMixExtItf_ *mItf;
    IObject *mThis;
    unsigned mActiveMask;   // 1 bit per active track
    Track mTracks[MAX_TRACK];
    SLboolean mDestroyRequested;    ///< Mixer to acknowledge application's call to Object::Destroy
} IOutputMixExt;
#endif

typedef struct {
    const struct SLPitchItf_ *mItf;
    IObject *mThis;
    SLpermille mPitch;
    // const
    SLpermille mMinPitch;
    SLpermille mMaxPitch;
} IPitch;

typedef struct Play_interface {
    const struct SLPlayItf_ *mItf;
    IObject *mThis;
    SLuint32 mState;
    // next 2 fields are read-only to application
    SLmillisecond mDuration;
    SLmillisecond mPosition;
    slPlayCallback mCallback;
    void *mContext;
    SLuint32 mEventFlags;
    // the ISeek trick of using a distinct value doesn't work here because it's readable by app
    SLmillisecond mMarkerPosition;
    SLmillisecond mPositionUpdatePeriod; // Zero means do not do position updates (FIXME ~0)
#ifdef USE_OUTPUTMIXEXT
    SLuint32 mFrameUpdatePeriod;         // mPositionUpdatePeriod in frame units
    SLmillisecond mLastSeekPosition;     // Last known accurate position, set at Seek
    SLuint32 mFramesSinceLastSeek;       // Frames mixed since last known accurate position
    SLuint32 mFramesSincePositionUpdate; // Frames mixed since last position update callback
#endif
} IPlay;

typedef struct {
    const struct SLPlaybackRateItf_ *mItf;
    IObject *mThis;
    SLpermille mRate;
    SLuint32 mProperties;
    // const
    SLpermille mMinRate;
    SLpermille mMaxRate;
    SLpermille mStepSize;
    SLuint32 mCapabilities;
} IPlaybackRate;

typedef struct {
    const struct SLPrefetchStatusItf_ *mItf;
    IObject *mThis;
    SLuint32 mStatus;
    SLpermille mLevel;
    slPrefetchCallback mCallback;
    void *mContext;
    SLuint32 mCallbackEventsMask;
    SLpermille mFillUpdatePeriod;
} IPrefetchStatus;

typedef struct {
    const struct SLPresetReverbItf_ *mItf;
    IObject *mThis;
    SLuint16 mPreset;
#if defined(ANDROID) && !defined(USE_BACKPORT)
    effect_descriptor_t mPresetReverbDescriptor;
    android::sp<android::AudioEffect> mPresetReverbEffect;
#endif
} IPresetReverb;

typedef struct {
    const struct SLRatePitchItf_ *mItf;
    IObject *mThis;
    SLpermille mRate;
    // const
    SLpermille mMinRate;
    SLpermille mMaxRate;
} IRatePitch;

typedef struct {
    const struct SLRecordItf_ *mItf;
    IObject *mThis;
    SLuint32 mState;
    SLmillisecond mDurationLimit;
    SLmillisecond mPosition;
    slRecordCallback mCallback;
    void *mContext;
    SLuint32 mCallbackEventsMask;
    SLmillisecond mMarkerPosition;
    SLmillisecond mPositionUpdatePeriod;
} IRecord;

typedef struct {
    const struct SLSeekItf_ *mItf;
    IObject *mThis;
    SLmillisecond mPos;     // mPos != SL_TIME_UNKNOWN means pending seek request
    SLboolean mLoopEnabled;
    SLmillisecond mStartPos;
    SLmillisecond mEndPos;
} ISeek;

typedef struct {
    const struct SLThreadSyncItf_ *mItf;
    IObject *mThis;
    SLboolean mInCriticalSection;
    SLuint32 mWaiting;  // number of threads waiting
    pthread_t mOwner;
} IThreadSync;

typedef struct {
    const struct SLVibraItf_ *mItf;
    IObject *mThis;
    SLboolean mVibrate;
    SLmilliHertz mFrequency;
    SLpermille mIntensity;
} IVibra;

typedef struct {
    const struct SLVirtualizerItf_ *mItf;
    IObject *mThis;
    SLboolean mEnabled;
    SLpermille mStrength;
#if defined(ANDROID) && !defined(USE_BACKPORT)
    effect_descriptor_t mVirtualizerDescriptor;
    android::sp<android::AudioEffect> mVirtualizerEffect;
#endif
} IVirtualizer;

typedef struct {
    const struct SLVisualizationItf_ *mItf;
    IObject *mThis;
    slVisualizationCallback mCallback;
    void *mContext;
    SLmilliHertz mRate;
} IVisualization;

typedef struct /*Volume_interface*/ {
    const struct SLVolumeItf_ *mItf;
    IObject *mThis;
    // Values as specified by the application
    SLmillibel mLevel;
    SLpermille mStereoPosition;
    SLuint8 /*SLboolean*/ mMute;
    SLuint8 /*SLboolean*/ mEnableStereoPosition;
} IVolume;

/* Class structures */

/*typedef*/ struct C3DGroup_struct {
    IObject mObject;
#define INTERFACES_3DGroup 6 // see MPH_to_3DGroup in MPH_to.c for list of interfaces
    SLuint8 mInterfaceStates2[INTERFACES_3DGroup - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    I3DLocation m3DLocation;
    I3DDoppler m3DDoppler;
    I3DSource m3DSource;
    I3DMacroscopic m3DMacroscopic;
    // remaining are per-instance private fields not associated with an interface
    unsigned mMemberMask;   // set of member objects
} /*C3DGroup*/;

#ifdef ANDROID

// FIXME Move these into the I... section above

typedef struct {
    const struct SLAndroidEffectItf_ *mItf;
    IObject *mThis;
    android::KeyedVector<SLuint32, android::AudioEffect* > *mEffects;
} IAndroidEffect;

typedef struct {
    const struct SLAndroidEffectCapabilitiesItf_ *mItf;
    IObject *mThis;
    SLuint32 mNumFx;
    effect_descriptor_t* mFxDescriptors;
} IAndroidEffectCapabilities;

typedef struct {
    const struct SLAndroidEffectSendItf_ *mItf;
    IObject *mThis;
    // only one send per interface for now (1 bus)
    SLboolean mEnabled;
    SLmillibel mSendLevel; //android::KeyedVector<SLuint32, SLmillibel> mSendLevels;
} IAndroidEffectSend;

typedef struct {
    const struct SLAndroidConfigurationItf_ *mItf;
    IObject *mThis;
} IAndroidConfiguration;

#if defined(ANDROID) && !defined(USE_BACKPORT)
// FIXME this include is done here so the effect structures have been defined. Messy.
#include "android_Effect.h"
#endif


/*
 * Used to define the mapping from an OpenSL ES audio player to an Android
 * media framework object
 */
enum AndroidObject_type {
    INVALID_TYPE     =-1,
    MEDIAPLAYER      = 0,
    AUDIOTRACK_PULL  = 1,
    NUM_AUDIOPLAYER_MAP_TYPES
};

enum AndroidObject_state {
    ANDROID_UNINITIALIZED = -1,
    ANDROID_PREPARING,
    ANDROID_READY,
    NUM_ANDROID_STATES
};

#endif  // ANDROID


/*typedef*/ struct CAudioPlayer_struct {
    IObject mObject;
#ifdef ANDROID
#define INTERFACES_AudioPlayer 29 // see MPH_to_AudioPlayer in MPH_to.c for list of interfaces
#else
#define INTERFACES_AudioPlayer 26 // see MPH_to_AudioPlayer in MPH_to.c for list of interfaces
#endif
    SLuint8 mInterfaceStates2[INTERFACES_AudioPlayer - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IPlay mPlay;
    I3DDoppler m3DDoppler;
    I3DGrouping m3DGrouping;
    I3DLocation m3DLocation;
    I3DSource m3DSource;
    IBufferQueue mBufferQueue;
    IEffectSend mEffectSend;
    IMetadataExtraction mMetadataExtraction;
    IMetadataTraversal mMetadataTraversal;
    IPrefetchStatus mPrefetchStatus;
    IRatePitch mRatePitch;
    ISeek mSeek;
    IVolume mVolume;
    IMuteSolo mMuteSolo;
#ifdef ANDROID
    IAndroidEffect mAndroidEffect;
    IAndroidEffectSend mAndroidEffectSend;
    IAndroidConfiguration mAndroidConfiguration;
#endif
    // optional interfaces
    I3DMacroscopic m3DMacroscopic;
    IBassBoost mBassBoost;
    IDynamicSource mDynamicSource;
    IEnvironmentalReverb mEnvironmentalReverb;
    IEqualizer mEqualizer;
    IPitch mPitch;
    IPresetReverb mPresetReverb;
    IPlaybackRate mPlaybackRate;
    IVirtualizer mVirtualizer;
    IVisualization mVisualization;
    // remaining are per-instance private fields not associated with an interface
    DataLocatorFormat mDataSource;
    DataLocatorFormat mDataSink;
    // cached data for this instance
    SLuint8 /*SLboolean*/ mMute;
    // Formerly at IMuteSolo
    SLuint8 mMuteMask;      // Mask for which channels are muted: bit 0=left, 1=right
    SLuint8 mSoloMask;      // Mask for which channels are soloed: bit 0=left, 1=right
    SLuint8 mNumChannels;   // 0 means unknown, then const once it is known, range 1 <= x <= 8
    SLuint32 mSampleRateMilliHz;// 0 means unknown, then const once it is known
    // Formerly at IEffectSend
    /**
     * Dry volume modified by effect send interfaces: SLEffectSendItf and SLAndroidEffectSendItf
     */
    SLmillibel mDirectLevel;
    // implementation-specific data for this instance
#ifdef USE_OUTPUTMIXEXT
    Track *mTrack;
    float mGains[STEREO_CHANNELS];  ///< Computed gain based on volume, mute, solo, stereo position
    SLboolean mDestroyRequested;    ///< Mixer to acknowledge application's call to Object::Destroy
#endif
#ifdef USE_SNDFILE
    struct SndFile mSndFile;
#endif // USE_SNDFILE
#ifdef ANDROID
    android::Mutex          *mpLock;
    enum AndroidObject_type mAndroidObjType;
    enum AndroidObject_state mAndroidObjState;
    /** identifies which group of effects ("session") this player belongs to */
    int mSessionId;
    /** identifies the Android stream type playback will occur on */
    int mStreamType;
    /** plays the PCM data for this player */
    android::AudioTrack *mAudioTrack;
#ifndef USE_BACKPORT
    android::sp<android::SfPlayer> mSfPlayer;
#endif
    /**
     * Amplification (can be attenuation) factor derived for the VolumeLevel
     */
    float mAmplFromVolLevel;
    /**
     * Left/right amplification (can be attenuations) factors derived for the StereoPosition
     */
    float mAmplFromStereoPos[STEREO_CHANNELS];
    /**
     * Attenuation factor derived from direct level
     */
    float mAmplFromDirectLevel;
#endif
} /*CAudioPlayer*/;


/*typedef*/ struct CAudioRecorder_struct {
    // mandated interfaces
    IObject mObject;
#ifdef ANDROID
#define INTERFACES_AudioRecorder 11 // see MPH_to_AudioRecorder in MPH_to.c for list of interfaces
#else
#define INTERFACES_AudioRecorder 9  // see MPH_to_AudioRecorder in MPH_to.c for list of interfaces
#endif
    SLuint8 mInterfaceStates2[INTERFACES_AudioRecorder - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IRecord mRecord;
    IAudioEncoder mAudioEncoder;
    // optional interfaces
    IBassBoost mBassBoost;
    IDynamicSource mDynamicSource;
    IEqualizer mEqualizer;
    IVisualization mVisualization;
    IVolume mVolume;
#ifdef ANDROID
    IBufferQueue mBufferQueue;
    IAndroidConfiguration mAndroidConfiguration;
#endif
    // remaining are per-instance private fields not associated with an interface
    DataLocatorFormat mDataSource;
    DataLocatorFormat mDataSink;
    // cached data for this instance
    SLuint8 mNumChannels;   // 0 means unknown, then const once it is known, range 1 <= x <= 8
    SLuint32 mSampleRateMilliHz;// 0 means unknown, then const once it is known
    // implementation-specific data for this instance
#ifdef ANDROID
    android::AudioRecord *mAudioRecord;
    int mRecordSource;
#endif
} /*CAudioRecorder*/;


typedef struct {
    // mandated implicit interfaces
    IObject mObject;
#ifdef ANDROID
#define INTERFACES_Engine 11 // see MPH_to_Engine in MPH_to.c for list of interfaces
#else
#define INTERFACES_Engine 10 // see MPH_to_Engine in MPH_to.c for list of interfaces
#endif
    SLuint8 mInterfaceStates2[INTERFACES_Engine - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IEngine mEngine;
    IEngineCapabilities mEngineCapabilities;
    IThreadSync mThreadSync;
    // mandated explicit interfaces
    IAudioIODeviceCapabilities mAudioIODeviceCapabilities;
    IAudioDecoderCapabilities mAudioDecoderCapabilities;
    IAudioEncoderCapabilities mAudioEncoderCapabilities;
    I3DCommit m3DCommit;
#ifdef ANDROID
    IAndroidEffectCapabilities mAndroidEffectCapabilities;
#endif
    // optional interfaces
    IDeviceVolume mDeviceVolume;
    // remaining are per-instance private fields not associated with an interface
    pthread_t mSyncThread;
} CEngine;

typedef struct {
    // mandated interfaces
    IObject mObject;
#define INTERFACES_LEDDevice 3 // see MPH_to_LEDDevice in MPH_to.c for list of interfaces
    SLuint8 mInterfaceStates2[INTERFACES_LEDDevice - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    ILEDArray mLEDArray;
    // remaining are per-instance private fields not associated with an interface
    SLuint32 mDeviceID;
} CLEDDevice;

typedef struct {
    // mandated interfaces
    IObject mObject;
#define INTERFACES_Listener 4 // see MPH_to_Listener in MPH_to.c for list of interfaces
    SLuint8 mInterfaceStates2[INTERFACES_Listener - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    I3DDoppler m3DDoppler;
    I3DLocation m3DLocation;
    // remaining are per-instance private fields not associated with an interface
} CListener;

typedef struct {
    // mandated interfaces
    IObject mObject;
#define INTERFACES_MetadataExtractor 5 // see MPH_to_MetadataExtractor in MPH_to.c for list of
                                       // interfaces
    SLuint8 mInterfaceStates2[INTERFACES_MetadataExtractor - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IDynamicSource mDynamicSource;
    IMetadataExtraction mMetadataExtraction;
    IMetadataTraversal mMetadataTraversal;
    // remaining are per-instance private fields not associated with an interface
} CMetadataExtractor;

typedef struct {
    // mandated interfaces
    IObject mObject;

#define INTERFACES_MidiPlayer 29 // see MPH_to_MidiPlayer in MPH_to.c for list of interfaces
    SLuint8 mInterfaceStates2[INTERFACES_MidiPlayer - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IPlay mPlay;
    I3DDoppler m3DDoppler;
    I3DGrouping m3DGrouping;
    I3DLocation m3DLocation;
    I3DSource m3DSource;
    IBufferQueue mBufferQueue;
    IEffectSend mEffectSend;
    IMetadataExtraction mMetadataExtraction;
    IMetadataTraversal mMetadataTraversal;
    IMIDIMessage mMIDIMessage;
    IMIDITime mMIDITime;
    IMIDITempo mMIDITempo;
    IMIDIMuteSolo mMIDIMuteSolo;
    IPrefetchStatus mPrefetchStatus;
    ISeek mSeek;
    IVolume mVolume;
    IMuteSolo mMuteSolo;
    // optional interfaces
    I3DMacroscopic m3DMacroscopic;
    IBassBoost mBassBoost;
    IDynamicSource mDynamicSource;
    IEnvironmentalReverb mEnvironmentalReverb;
    IEqualizer mEqualizer;
    IPitch mPitch;
    IPresetReverb mPresetReverb;
    IPlaybackRate mPlaybackRate;
    IVirtualizer mVirtualizer;
    IVisualization mVisualization;
    // remaining are per-instance private fields not associated with an interface
} CMidiPlayer;

/*typedef*/ struct COutputMix_struct {
    // mandated interfaces
    IObject mObject;
#ifdef ANDROID
#define INTERFACES_OutputMix 12 // see MPH_to_OutputMix in MPH_to.c for list of interfaces
#else
#define INTERFACES_OutputMix 11 // see MPH_to_OutputMix in MPH_to.c for list of interfaces
#endif
    SLuint8 mInterfaceStates2[INTERFACES_OutputMix - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IOutputMix mOutputMix;
#ifdef USE_OUTPUTMIXEXT
    IOutputMixExt mOutputMixExt;
#endif
    IEnvironmentalReverb mEnvironmentalReverb;
    IEqualizer mEqualizer;
    IPresetReverb mPresetReverb;
    IVirtualizer mVirtualizer;
    IVolume mVolume;
    // optional interfaces
    IBassBoost mBassBoost;
    IVisualization mVisualization;
#ifdef ANDROID
    IAndroidEffect mAndroidEffect;
#endif
    // remaining are per-instance private fields not associated with an interface
} /*COutputMix*/;

typedef struct {
    // mandated interfaces
    IObject mObject;
#define INTERFACES_VibraDevice 3 // see MPH_to_VibraDevice in MPH_to.c for list of interfaces
    SLuint8 mInterfaceStates2[INTERFACES_VibraDevice - INTERFACES_Default];
    IDynamicInterfaceManagement mDynamicInterfaceManagement;
    IVibra mVibra;
    // remaining are per-instance private fields not associated with an interface
    SLuint32 mDeviceID;
} CVibraDevice;

struct MPH_init {
    VoidHook mInit;     // called first to initialize the interface, right after object is allocated
    // Each interface is initialized regardless whether it is exposed to application.
    VoidHook mResume;   // called to resume interface after suspension, not currently used
    VoidHook mDeinit;   // called last when object is about to be destroyed
    BoolHook mExpose;   // called after initialization, only if interface is exposed to application
    VoidHook mRemove;   // called by DynamicInterfaceManager::RemoveInterface, and prior to mDeinit
    // will need a suspend hook when suspend is implemented
};

extern /*static*/ int IID_to_MPH(const SLInterfaceID iid);
extern /*static*/ const struct MPH_init MPH_init_table[MPH_MAX];
extern SLresult checkInterfaces(const ClassTable *class__,
    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
    const SLboolean *pInterfaceRequired, unsigned *pExposedMask);
extern IObject *construct(const ClassTable *class__,
    unsigned exposedMask, SLEngineItf engine);
extern const ClassTable *objectIDtoClass(SLuint32 objectID);
extern const struct SLInterfaceID_ SL_IID_array[MPH_MAX];
extern SLuint32 IObjectToObjectID(IObject *object);
extern void IObject_Publish(IObject *this);
extern void IObject_Destroy(SLObjectItf self);

// Map an interface to it's "object ID" (which is really a class ID).
// Note: this operation is undefined on IObject, as it lacks an mThis.
// If you have an IObject, then use IObjectToObjectID directly.

#define InterfaceToObjectID(this) IObjectToObjectID((this)->mThis)

// Map an interface to it's corresponding IObject.
// Note: this operation is undefined on IObject, as it lacks an mThis.
// If you have an IObject, then you're done -- you already have what you need.

#define InterfaceToIObject(this) ((this)->mThis)

#define InterfaceToCAudioPlayer(this) (((CAudioPlayer*)InterfaceToIObject(this)))

#define InterfaceToCAudioRecorder(this) (((CAudioRecorder*)InterfaceToIObject(this)))

#ifdef ANDROID
#include "android_AudioPlayer.h"
#endif

extern SLresult checkDataSource(const SLDataSource *pDataSrc,
        DataLocatorFormat *myDataSourceLocator);
extern SLresult checkDataSink(const SLDataSink *pDataSink, DataLocatorFormat *myDataSinkLocator,
        SLuint32 objType);
extern SLresult checkSourceFormatVsInterfacesCompatibility(
        const DataLocatorFormat *pDataLocatorFormat, const ClassTable *class__,
        unsigned exposedMask);
extern void freeDataLocatorFormat(DataLocatorFormat *dlf);

extern bool C3DGroup_PreDestroy(void *self);

extern SLresult CAudioPlayer_Realize(void *self, SLboolean async);
extern SLresult CAudioPlayer_Resume(void *self, SLboolean async);
extern void CAudioPlayer_Destroy(void *self);
extern bool CAudioPlayer_PreDestroy(void *self);

extern SLresult CAudioRecorder_Realize(void *self, SLboolean async);
extern SLresult CAudioRecorder_Resume(void *self, SLboolean async);
extern void CAudioRecorder_Destroy(void *self);
extern bool CAudioRecorder_PreDestroy(void *self);

extern SLresult CEngine_Realize(void *self, SLboolean async);
extern SLresult CEngine_Resume(void *self, SLboolean async);
extern void CEngine_Destroy(void *self);
extern bool CEngine_PreDestroy(void *self);
extern void CEngine_Destroyed(CEngine *self);

extern SLresult COutputMix_Realize(void *self, SLboolean async);
extern SLresult COutputMix_Resume(void *self, SLboolean async);
extern void COutputMix_Destroy(void *self);
extern bool COutputMix_PreDestroy(void *self);

#ifdef USE_SDL
extern void SDL_open(IEngine *thisEngine);
extern void SDL_close(void);
#endif
#define SL_OBJECT_STATE_REALIZING_1  ((SLuint32) 0x4) // async realize on work queue
#define SL_OBJECT_STATE_REALIZING_2  ((SLuint32) 0x5) // sync realize, or async realize hook
#define SL_OBJECT_STATE_RESUMING_1   ((SLuint32) 0x6) // async resume on work queue
#define SL_OBJECT_STATE_RESUMING_2   ((SLuint32) 0x7) // sync resume, or async resume hook
#define SL_OBJECT_STATE_SUSPENDING   ((SLuint32) 0x8) // suspend in progress
#define SL_OBJECT_STATE_REALIZING_1A ((SLuint32) 0x9) // abort while async realize on work queue
#define SL_OBJECT_STATE_RESUMING_1A  ((SLuint32) 0xA) // abort while async resume on work queue
#define SL_OBJECT_STATE_DESTROYING   ((SLuint32) 0xB) // destroy object when no strong references
extern void *sync_start(void *arg);
extern SLresult err_to_result(int err);

#ifdef __GNUC__
#define ctz __builtin_ctz
#else
extern unsigned ctz(unsigned);
#endif
extern const char * const interface_names[MPH_MAX];
#include "platform.h"

// Attributes

#define ATTR_NONE       ((unsigned) 0x0)      // none
#define ATTR_GAIN       ((unsigned) 0x1 << 0) // player volume, channel mute, channel solo,
                                              // player stereo position, player mute
#define ATTR_TRANSPORT  ((unsigned) 0x1 << 1) // play state, looping
#define ATTR_POSITION   ((unsigned) 0x1 << 2) // requested position (a.k.a. seek position)
#define ATTR_ENQUEUE    ((unsigned) 0x1 << 3) // buffer queue became non-empty and in playing state

#define SL_DATALOCATOR_NULL 0    // application specified a NULL value for pLocator
#define SL_DATAFORMAT_NULL 0     // application specified a NULL or undefined value for pFormat

// Trace debugging

// Always defined, but may be a no-op if trace support is disabled at compile-time
extern void slTraceSetEnabled(unsigned enabled);

#define SL_TRACE_ENTER          0x1
#define SL_TRACE_LEAVE_FAILURE  0x2
#define SL_TRACE_LEAVE_VOID     0x4
#define SL_TRACE_LEAVE_SUCCESS  0x8
#define SL_TRACE_LEAVE          (SL_TRACE_LEAVE_FAILURE | SL_TRACE_LEAVE_VOID | \
                                    SL_TRACE_LEAVE_SUCCESS)
#define SL_TRACE_ALL            (SL_TRACE_ENTER | SL_TRACE_LEAVE)
#ifndef SL_TRACE_DEFAULT
#define SL_TRACE_DEFAULT        (SL_TRACE_LEAVE_FAILURE)
#endif

#ifndef USE_TRACE

#define SL_ENTER_GLOBAL SLresult result;
#define SL_LEAVE_GLOBAL return result;
#define SL_ENTER_INTERFACE SLresult result;
#define SL_LEAVE_INTERFACE return result;
#define SL_ENTER_INTERFACE_VOID
#define SL_LEAVE_INTERFACE_VOID return;

#else

extern void slTraceEnterGlobal(const char *function);
extern void slTraceLeaveGlobal(const char *function, SLresult result);
extern void slTraceEnterInterface(const char *function);
extern void slTraceLeaveInterface(const char *function, SLresult result);
extern void slTraceEnterInterfaceVoid(const char *function);
extern void slTraceLeaveInterfaceVoid(const char *function);
#define SL_ENTER_GLOBAL SLresult result; slTraceEnterGlobal(__FUNCTION__);
#define SL_LEAVE_GLOBAL slTraceLeaveGlobal(__FUNCTION__, result); return result;
#define SL_ENTER_INTERFACE SLresult result; slTraceEnterInterface(__FUNCTION__);
#define SL_LEAVE_INTERFACE slTraceLeaveInterface(__FUNCTION__, result); return result;
#define SL_ENTER_INTERFACE_VOID slTraceEnterInterfaceVoid(__FUNCTION__);
#define SL_LEAVE_INTERFACE_VOID slTraceLeaveInterfaceVoid(__FUNCTION__); return;

#endif

#ifdef USE_OUTPUTMIXEXT

#define SL_PLAYSTATE_STOPPING ((SLuint32) 0x4) // Play::Stop while PLAYING
// If we needed it, could have PLAYING mean mixer is currently reading from front buffer,
// while PLAYABLE would mean application requested PLAYING, but buffer queue is empty

#endif

#ifdef USE_SNDFILE
extern void audioPlayerTransportUpdate(CAudioPlayer *audioPlayer);
#endif

extern SLresult IBufferQueue_Enqueue(SLBufferQueueItf self, const void *pBuffer, SLuint32 size);
extern SLresult IBufferQueue_Clear(SLBufferQueueItf self);
extern SLresult IBufferQueue_RegisterCallback(SLBufferQueueItf self,
    slBufferQueueCallback callback, void *pContext);

extern bool IsInterfaceInitialized(IObject *this, unsigned MPH);
extern SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID);
extern void ReleaseStrongRef(IObject *object);
extern void ReleaseStrongRefAndUnlockExclusive(IObject *object);

extern COutputMix *CAudioPlayer_GetOutputMix(CAudioPlayer *audioPlayer);