/*
* 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;
/** aux effect the AudioTrack will be attached to if aux send enabled */
android::sp<android::AudioEffect> mAuxEffect;
/** send level to aux effect, there's a single aux bus, so there's a single level */
SLmillibel mAuxSendLevel;
#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
#ifndef ANDROID
extern void *sync_start(void *arg);
#endif
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);