am 7070b365: Added support for auxiliary audio effects to AudioTrack and MediaPlayer.
Merge commit '7070b36549d511d6627538c73dfbab23fbae5b43' into gingerbread-plus-aosp * commit '7070b36549d511d6627538c73dfbab23fbae5b43': Added support for auxiliary audio effects to AudioTrack and MediaPlayer.
This commit is contained in:
@@ -360,6 +360,7 @@ android_media_AudioTrack_start(JNIEnv *env, jobject thiz)
|
||||
if (lpTrack == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for start()");
|
||||
return;
|
||||
}
|
||||
|
||||
lpTrack->start();
|
||||
@@ -375,6 +376,7 @@ android_media_AudioTrack_stop(JNIEnv *env, jobject thiz)
|
||||
if (lpTrack == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for stop()");
|
||||
return;
|
||||
}
|
||||
|
||||
lpTrack->stop();
|
||||
@@ -390,6 +392,7 @@ android_media_AudioTrack_pause(JNIEnv *env, jobject thiz)
|
||||
if (lpTrack == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for pause()");
|
||||
return;
|
||||
}
|
||||
|
||||
lpTrack->pause();
|
||||
@@ -405,6 +408,7 @@ android_media_AudioTrack_flush(JNIEnv *env, jobject thiz)
|
||||
if (lpTrack == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for flush()");
|
||||
return;
|
||||
}
|
||||
|
||||
lpTrack->flush();
|
||||
@@ -419,6 +423,7 @@ android_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, j
|
||||
if (lpTrack == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for setVolume()");
|
||||
return;
|
||||
}
|
||||
|
||||
lpTrack->setVolume(leftVol, rightVol);
|
||||
@@ -515,6 +520,7 @@ static jint android_media_AudioTrack_native_write(JNIEnv *env, jobject thiz,
|
||||
if (lpTrack == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for write()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get the pointer for the audio data from the java array
|
||||
@@ -801,6 +807,36 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi
|
||||
return minBuffSize;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static void
|
||||
android_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
|
||||
{
|
||||
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
|
||||
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
|
||||
if (lpTrack == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
|
||||
return;
|
||||
}
|
||||
|
||||
lpTrack->setAuxEffectSendLevel(level);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env, jobject thiz,
|
||||
jint effectId) {
|
||||
|
||||
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
|
||||
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
|
||||
|
||||
if (lpTrack) {
|
||||
return android_media_translateErrorCode( lpTrack->attachAuxEffect(effectId) );
|
||||
} else {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Unable to retrieve AudioTrack pointer for attachAuxEffect()");
|
||||
return AUDIOTRACK_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -837,6 +873,10 @@ static JNINativeMethod gMethods[] = {
|
||||
"(I)I", (void *)android_media_AudioTrack_get_output_sample_rate},
|
||||
{"native_get_min_buff_size",
|
||||
"(III)I", (void *)android_media_AudioTrack_get_min_buff_size},
|
||||
{"native_setAuxEffectSendLevel",
|
||||
"(F)V", (void *)android_media_AudioTrack_setAuxEffectSendLevel},
|
||||
{"native_attachAuxEffect",
|
||||
"(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -261,8 +261,8 @@ public:
|
||||
/* set the send level for this track. An auxiliary effect should be attached
|
||||
* to the track with attachEffect(). Level must be <= 1.0.
|
||||
*/
|
||||
status_t setSendLevel(float level);
|
||||
void getSendLevel(float* level);
|
||||
status_t setAuxEffectSendLevel(float level);
|
||||
void getAuxEffectSendLevel(float* level);
|
||||
|
||||
/* set sample rate for this track, mostly used for games' sound effects
|
||||
*/
|
||||
@@ -479,6 +479,7 @@ private:
|
||||
uint32_t mUpdatePeriod;
|
||||
uint32_t mFlags;
|
||||
int mSessionId;
|
||||
int mAuxEffectId;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
|
||||
virtual status_t suspend() = 0;
|
||||
virtual status_t resume() = 0;
|
||||
virtual status_t setAuxEffectSendLevel(float level) = 0;
|
||||
virtual status_t attachAuxEffect(int effectId) = 0;
|
||||
|
||||
// Invoke a generic method on the player by using opaque parcels
|
||||
// for the request and reply.
|
||||
|
||||
@@ -173,6 +173,8 @@ public:
|
||||
status_t resume();
|
||||
status_t setAudioSessionId(int sessionId);
|
||||
int getAudioSessionId();
|
||||
status_t setAuxEffectSendLevel(float level);
|
||||
status_t attachAuxEffect(int effectId);
|
||||
private:
|
||||
void clear_l();
|
||||
status_t seekTo_l(int msec);
|
||||
@@ -200,6 +202,7 @@ private:
|
||||
int mVideoWidth;
|
||||
int mVideoHeight;
|
||||
int mAudioSessionId;
|
||||
float mSendLevel;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -963,6 +963,65 @@ public class AudioTrack
|
||||
return native_reload_static();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Audio effects management
|
||||
//--------------------
|
||||
|
||||
/**
|
||||
* Attaches an auxiliary effect to the audio track. A typical auxiliary effect is a
|
||||
* reverberation effect which can be applied on any sound source that directs a certain
|
||||
* amount of its energy to this effect. This amount is defined by setAuxEffectSendLevel().
|
||||
* {@see #setAuxEffectSendLevel(float)}.
|
||||
// TODO when AudioEffect are unhidden
|
||||
* <p>After creating an auxiliary effect (e.g. {_at_link android.media.EnvironmentalReverb}),
|
||||
* retrieve its ID with {_at_link android.media.AudioEffect#getId()} and use it when calling
|
||||
* this method to attach the audio track to the effect.
|
||||
* <p>To detach the effect from the audio track, call this method with a null effect id.
|
||||
*
|
||||
* @param effectId system wide unique id of the effect to attach
|
||||
* @return error code or success, see {@link #SUCCESS},
|
||||
* {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE}
|
||||
// FIXME: unhide.
|
||||
* @hide
|
||||
*/
|
||||
public int attachAuxEffect(int effectId) {
|
||||
if (mState != STATE_INITIALIZED) {
|
||||
return ERROR_INVALID_OPERATION;
|
||||
}
|
||||
return native_attachAuxEffect(effectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the send level of the audio track to the attached auxiliary effect
|
||||
* {@see #attachAuxEffect(int)}. The level value range is 0 to 1.0.
|
||||
* <p>By default the send level is 0, so even if an effect is attached to the player
|
||||
* this method must be called for the effect to be applied.
|
||||
* <p>Note that the passed level value is a raw scalar. UI controls should be scaled
|
||||
* logarithmically: the gain applied by audio framework ranges from -72dB to 0dB,
|
||||
* so an appropriate conversion from linear UI input x to level is:
|
||||
* x == 0 -> level = 0
|
||||
* 0 < x <= R -> level = 10^(72*(x-R)/20/R)
|
||||
*
|
||||
* @param level send level scalar
|
||||
* @return error code or success, see {@link #SUCCESS},
|
||||
* {@link #ERROR_INVALID_OPERATION}
|
||||
// FIXME: unhide.
|
||||
* @hide
|
||||
*/
|
||||
public int setAuxEffectSendLevel(float level) {
|
||||
if (mState != STATE_INITIALIZED) {
|
||||
return ERROR_INVALID_OPERATION;
|
||||
}
|
||||
// clamp the level
|
||||
if (level < getMinVolume()) {
|
||||
level = getMinVolume();
|
||||
}
|
||||
if (level > getMaxVolume()) {
|
||||
level = getMaxVolume();
|
||||
}
|
||||
native_setAuxEffectSendLevel(level);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Interface definitions
|
||||
@@ -1123,6 +1182,9 @@ public class AudioTrack
|
||||
|
||||
private native final int native_get_session_id();
|
||||
|
||||
private native final int native_attachAuxEffect(int effectId);
|
||||
private native final void native_setAuxEffectSendLevel(float level);
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Utility methods
|
||||
//------------------
|
||||
|
||||
@@ -423,7 +423,7 @@ import java.lang.ref.WeakReference;
|
||||
* <td>Successful invoke of this method in a valid state transfers the
|
||||
* object to the <em>Stopped</em> state. Calling this method in an
|
||||
* invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
|
||||
* <tr><td>setAudioSessionId </p></td>
|
||||
* <tr><td>setAudioSessionId </p></td>
|
||||
* <td>{Idle} </p></td>
|
||||
* <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
|
||||
* Error} </p></td>
|
||||
@@ -434,6 +434,15 @@ import java.lang.ref.WeakReference;
|
||||
* <td>{} </p></td>
|
||||
* <td>This method can be called in any state and calling it does not change
|
||||
* the object state. </p></td></tr>
|
||||
* <tr><td>attachAuxEffect </p></td>
|
||||
* <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} </p></td>
|
||||
* <td>{Idle, Error} </p></td>
|
||||
* <td>This method must be called after setDataSource.
|
||||
* Calling it does not change the object state. </p></td></tr>
|
||||
* <tr><td>setAuxEffectSendLevel </p></td>
|
||||
* <td>any</p></td>
|
||||
* <td>{} </p></td>
|
||||
* <td>Calling this method does not change the object state. </p></td></tr>
|
||||
*
|
||||
* </table>
|
||||
*
|
||||
@@ -1187,7 +1196,7 @@ public class MediaPlayer
|
||||
* @throws IllegalStateException if it is called in an invalid state
|
||||
*
|
||||
// FIXME: unhide.
|
||||
// FIXME: link to AudioEffect class when public.
|
||||
// TODO when AudioEffect is unhidden
|
||||
* @hide
|
||||
*/
|
||||
public native void setAudioSessionId(int sessionId) throws IllegalArgumentException, IllegalStateException;
|
||||
@@ -1202,6 +1211,41 @@ public class MediaPlayer
|
||||
*/
|
||||
public native int getAudioSessionId();
|
||||
|
||||
/**
|
||||
* Attaches an auxiliary effect to the player. A typical auxiliary effect is a reverberation
|
||||
* effect which can be applied on any sound source that directs a certain amount of its
|
||||
* energy to this effect. This amount is defined by setAuxEffectSendLevel().
|
||||
* {@see #setAuxEffectSendLevel(float)}.
|
||||
// TODO when AudioEffect is unhidden
|
||||
* <p>After creating an auxiliary effect (e.g. {_at_link android.media.EnvironmentalReverb}),
|
||||
* retrieve its ID with {_at_link android.media.AudioEffect#getId()} and use it when calling
|
||||
* this method to attach the player to the effect.
|
||||
* <p>To detach the effect from the player, call this method with a null effect id.
|
||||
* <p>This method must be called after one of the overloaded <code> setDataSource </code>
|
||||
* methods.
|
||||
*
|
||||
* @param effectId system wide unique id of the effect to attach
|
||||
// FIXME: unhide.
|
||||
* @hide
|
||||
*/
|
||||
public native void attachAuxEffect(int effectId);
|
||||
|
||||
/**
|
||||
* Sets the send level of the player to the attached auxiliary effect
|
||||
* {@see #attachAuxEffect(int)}. The level value range is 0 to 1.0.
|
||||
* <p>By default the send level is 0, so even if an effect is attached to the player
|
||||
* this method must be called for the effect to be applied.
|
||||
* <p>Note that the passed level value is a raw scalar. UI controls should be scaled
|
||||
* logarithmically: the gain applied by audio framework ranges from -72dB to 0dB,
|
||||
* so an appropriate conversion from linear UI input x to level is:
|
||||
* x == 0 -> level = 0
|
||||
* 0 < x <= R -> level = 10^(72*(x-R)/20/R)
|
||||
* @param level send level scalar
|
||||
// FIXME: unhide.
|
||||
* @hide
|
||||
*/
|
||||
public native void setAuxEffectSendLevel(float level);
|
||||
|
||||
/**
|
||||
* @param request Parcel destinated to the media player. The
|
||||
* Interface token must be set to the IMediaPlayer
|
||||
|
||||
@@ -714,6 +714,28 @@ static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject
|
||||
return mp->getAudioSessionId();
|
||||
}
|
||||
|
||||
static void
|
||||
android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level)
|
||||
{
|
||||
LOGV("setAuxEffectSendLevel: level %f", level);
|
||||
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
|
||||
if (mp == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL );
|
||||
}
|
||||
|
||||
static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz, jint effectId) {
|
||||
LOGV("attachAuxEffect(): %d", sessionId);
|
||||
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
|
||||
if (mp == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
@@ -748,6 +770,8 @@ static JNINativeMethod gMethods[] = {
|
||||
{"native_suspend_resume", "(Z)I", (void *)android_media_MediaPlayer_native_suspend_resume},
|
||||
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
|
||||
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
|
||||
{"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
|
||||
{"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
|
||||
};
|
||||
|
||||
static const char* const kClassPathName = "android/media/MediaPlayer";
|
||||
|
||||
@@ -209,6 +209,7 @@ status_t AudioTrack::set(
|
||||
mFrameCount = frameCount;
|
||||
mNotificationFramesReq = notificationFrames;
|
||||
mSessionId = sessionId;
|
||||
mAuxEffectId = 0;
|
||||
|
||||
// create the IAudioTrack
|
||||
status_t status = createTrack(streamType, sampleRate, format, channelCount,
|
||||
@@ -458,8 +459,9 @@ void AudioTrack::getVolume(float* left, float* right)
|
||||
}
|
||||
}
|
||||
|
||||
status_t AudioTrack::setSendLevel(float level)
|
||||
status_t AudioTrack::setAuxEffectSendLevel(float level)
|
||||
{
|
||||
LOGV("setAuxEffectSendLevel(%f)", level);
|
||||
if (level > 1.0f) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
@@ -471,7 +473,7 @@ status_t AudioTrack::setSendLevel(float level)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void AudioTrack::getSendLevel(float* level)
|
||||
void AudioTrack::getAuxEffectSendLevel(float* level)
|
||||
{
|
||||
if (level != NULL) {
|
||||
*level = mSendLevel;
|
||||
@@ -637,7 +639,12 @@ int AudioTrack::getSessionId()
|
||||
|
||||
status_t AudioTrack::attachAuxEffect(int effectId)
|
||||
{
|
||||
return mAudioTrack->attachAuxEffect(effectId);
|
||||
LOGV("attachAuxEffect(%d)", effectId);
|
||||
status_t status = mAudioTrack->attachAuxEffect(effectId);
|
||||
if (status == NO_ERROR) {
|
||||
mAuxEffectId = effectId;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -752,6 +759,7 @@ status_t AudioTrack::createTrack(
|
||||
|
||||
mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000);
|
||||
mCblk->sendLevel = uint16_t(mSendLevel * 0x1000);
|
||||
mAudioTrack->attachAuxEffect(mAuxEffectId);
|
||||
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
|
||||
mCblk->waitTimeMs = 0;
|
||||
mRemainingFrames = mNotificationFramesAct;
|
||||
|
||||
@@ -45,6 +45,8 @@ enum {
|
||||
GET_METADATA,
|
||||
SUSPEND,
|
||||
RESUME,
|
||||
SET_AUX_EFFECT_SEND_LEVEL,
|
||||
ATTACH_AUX_EFFECT
|
||||
};
|
||||
|
||||
class BpMediaPlayer: public BpInterface<IMediaPlayer>
|
||||
@@ -221,6 +223,24 @@ public:
|
||||
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
status_t setAuxEffectSendLevel(float level)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||||
data.writeFloat(level);
|
||||
remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
status_t attachAuxEffect(int effectId)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||||
data.writeInt32(effectId);
|
||||
remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
|
||||
@@ -339,6 +359,16 @@ status_t BnMediaPlayer::onTransact(
|
||||
reply->setDataPosition(0);
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case SET_AUX_EFFECT_SEND_LEVEL: {
|
||||
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||
reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case ATTACH_AUX_EFFECT: {
|
||||
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||
reply->writeInt32(attachAuxEffect(data.readInt32()));
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
default:
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
@@ -270,6 +270,7 @@ status_t MediaPlayer::start()
|
||||
MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
|
||||
mPlayer->setLooping(mLoop);
|
||||
mPlayer->setVolume(mLeftVolume, mRightVolume);
|
||||
mPlayer->setAuxEffectSendLevel(mSendLevel);
|
||||
mCurrentState = MEDIA_PLAYER_STARTED;
|
||||
status_t ret = mPlayer->start();
|
||||
if (ret != NO_ERROR) {
|
||||
@@ -523,6 +524,31 @@ int MediaPlayer::getAudioSessionId()
|
||||
return mAudioSessionId;
|
||||
}
|
||||
|
||||
status_t MediaPlayer::setAuxEffectSendLevel(float level)
|
||||
{
|
||||
LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
|
||||
Mutex::Autolock _l(mLock);
|
||||
mSendLevel = level;
|
||||
if (mPlayer != 0) {
|
||||
return mPlayer->setAuxEffectSendLevel(level);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t MediaPlayer::attachAuxEffect(int effectId)
|
||||
{
|
||||
LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
|
||||
Mutex::Autolock _l(mLock);
|
||||
if (mPlayer == 0 ||
|
||||
(mCurrentState & MEDIA_PLAYER_IDLE) ||
|
||||
(mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
|
||||
LOGE("attachAuxEffect called in state %d", mCurrentState);
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
return mPlayer->attachAuxEffect(effectId);
|
||||
}
|
||||
|
||||
void MediaPlayer::notify(int msg, int ext1, int ext2)
|
||||
{
|
||||
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
|
||||
|
||||
@@ -329,6 +329,10 @@ status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& a
|
||||
snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
|
||||
mMsecsPerFrame, mLatency);
|
||||
result.append(buffer);
|
||||
snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
|
||||
mAuxEffectId, mSendLevel);
|
||||
result.append(buffer);
|
||||
|
||||
::write(fd, result.string(), result.size());
|
||||
if (mTrack != 0) {
|
||||
mTrack->dump(fd, args);
|
||||
@@ -1093,6 +1097,21 @@ status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolu
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
|
||||
{
|
||||
LOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
|
||||
Mutex::Autolock l(mLock);
|
||||
if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
|
||||
{
|
||||
LOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
|
||||
Mutex::Autolock l(mLock);
|
||||
if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
|
||||
{
|
||||
@@ -1285,6 +1304,8 @@ MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
|
||||
mRightVolume = 1.0;
|
||||
mLatency = 0;
|
||||
mMsecsPerFrame = 0;
|
||||
mAuxEffectId = 0;
|
||||
mSendLevel = 0.0;
|
||||
setMinBufferCount();
|
||||
}
|
||||
|
||||
@@ -1417,10 +1438,13 @@ status_t MediaPlayerService::AudioOutput::open(
|
||||
|
||||
LOGV("setVolume");
|
||||
t->setVolume(mLeftVolume, mRightVolume);
|
||||
|
||||
mMsecsPerFrame = 1.e3 / (float) sampleRate;
|
||||
mLatency = t->latency();
|
||||
mTrack = t;
|
||||
return NO_ERROR;
|
||||
|
||||
t->setAuxEffectSendLevel(mSendLevel);
|
||||
return t->attachAuxEffect(mAuxEffectId);;
|
||||
}
|
||||
|
||||
void MediaPlayerService::AudioOutput::start()
|
||||
@@ -1428,6 +1452,7 @@ void MediaPlayerService::AudioOutput::start()
|
||||
LOGV("start");
|
||||
if (mTrack) {
|
||||
mTrack->setVolume(mLeftVolume, mRightVolume);
|
||||
mTrack->setAuxEffectSendLevel(mSendLevel);
|
||||
mTrack->start();
|
||||
}
|
||||
}
|
||||
@@ -1481,6 +1506,26 @@ void MediaPlayerService::AudioOutput::setVolume(float left, float right)
|
||||
}
|
||||
}
|
||||
|
||||
status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
|
||||
{
|
||||
LOGV("setAuxEffectSendLevel(%f)", level);
|
||||
mSendLevel = level;
|
||||
if (mTrack) {
|
||||
return mTrack->setAuxEffectSendLevel(level);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
|
||||
{
|
||||
LOGV("attachAuxEffect(%d)", effectId);
|
||||
mAuxEffectId = effectId;
|
||||
if (mTrack) {
|
||||
return mTrack->attachAuxEffect(effectId);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// static
|
||||
void MediaPlayerService::AudioOutput::CallbackWrapper(
|
||||
int event, void *cookie, void *info) {
|
||||
|
||||
@@ -91,6 +91,8 @@ class MediaPlayerService : public BnMediaPlayerService
|
||||
virtual void close();
|
||||
void setAudioStreamType(int streamType) { mStreamType = streamType; }
|
||||
void setVolume(float left, float right);
|
||||
status_t setAuxEffectSendLevel(float level);
|
||||
status_t attachAuxEffect(int effectId);
|
||||
virtual status_t dump(int fd, const Vector<String16>& args) const;
|
||||
|
||||
static bool isOnEmulator();
|
||||
@@ -109,7 +111,8 @@ class MediaPlayerService : public BnMediaPlayerService
|
||||
float mMsecsPerFrame;
|
||||
uint32_t mLatency;
|
||||
int mSessionId;
|
||||
|
||||
float mSendLevel;
|
||||
int mAuxEffectId;
|
||||
static bool mIsOnEmulator;
|
||||
static int mMinBufferCount; // 12 for emulator; otherwise 4
|
||||
|
||||
@@ -221,6 +224,8 @@ private:
|
||||
Parcel *reply);
|
||||
virtual status_t suspend();
|
||||
virtual status_t resume();
|
||||
virtual status_t setAuxEffectSendLevel(float level);
|
||||
virtual status_t attachAuxEffect(int effectId);
|
||||
|
||||
sp<MediaPlayerBase> createPlayer(player_type playerType);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user