blob: a41fed87471d6eb4cde9c0d82826f75fd1aabf90 [file] [log] [blame]
/*
* Copyright (C) 2017 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.
*/
#include "sles_allinclusive.h"
#include <media/stagefright/foundation/ADebug.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <audiomanager/IPlayer.h>
#include <audiomanager/AudioManager.h>
#include <audiomanager/IAudioManager.h>
#include <binder/IServiceManager.h>
#include "utils/RefBase.h"
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
namespace android {
//--------------------------------------------------------------------------------------------------
TrackPlayerBase::TrackPlayerBase() : BnPlayer(),
mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN),
mSlPlayerVolumeL(1.0f), mSlPlayerVolumeR(1.0f),
mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f)
{
SL_LOGD("TrackPlayerBase::TrackPlayerBase()");
// use checkService() to avoid blocking if audio service is not up yet
sp<IBinder> binder = defaultServiceManager()->checkService(String16("audio"));
if (binder == 0) {
SL_LOGE("TrackPlayerBase(): binding to audio service failed, service up?");
} else {
mAudioManager = interface_cast<IAudioManager>(binder);
}
}
TrackPlayerBase::~TrackPlayerBase() {
SL_LOGV("TrackPlayerBase::~TrackPlayerBase()");
destroy();
}
void TrackPlayerBase::init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage) {
mAudioTrack = pat;
if (mAudioManager == 0) {
SL_LOGE("AudioPlayer realize: no audio service, player will not be registered");
} else {
mPIId = mAudioManager->trackPlayer(playerType, usage, AUDIO_CONTENT_TYPE_UNKNOWN, this);
}
}
void TrackPlayerBase::destroy() {
if (mAudioTrack != 0) {
mAudioTrack->stop();
// Note that there may still be another reference in post-unlock phase of SetPlayState
mAudioTrack.clear();
}
serviceReleasePlayer();
if (mAudioManager != 0) {
mAudioManager.clear();
}
}
void TrackPlayerBase::setSlPlayerVolume(float vl, float vr) {
float tl, tr = 1.0f;
{
Mutex::Autolock _l(mSettingsLock);
mSlPlayerVolumeL = vl;
mSlPlayerVolumeR = vr;
tl = mSlPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
tr = mSlPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
}
if (mAudioTrack != 0) {
mAudioTrack->setVolume(tl, tr);
}
}
//------------------------------------------------------------------------------
void TrackPlayerBase::servicePlayerEvent(player_state_t event) {
if (mAudioManager != 0) {
// only report state change
Mutex::Autolock _l(mPlayerStateLock);
if (event != mLastReportedEvent
&& mPIId != PLAYER_PIID_INVALID) {
mLastReportedEvent = event;
mAudioManager->playerEvent(mPIId, event);
}
}
}
void TrackPlayerBase::serviceReleasePlayer() {
if (mAudioManager != 0
&& mPIId != PLAYER_PIID_INVALID) {
mAudioManager->releasePlayer(mPIId);
}
}
//FIXME temporary method while some AudioTrack state is outside of this class
void TrackPlayerBase::reportEvent(player_state_t event) {
servicePlayerEvent(event);
}
//------------------------------------------------------------------------------
// Implementation of IPlayer
void TrackPlayerBase::start() {
if (mAudioTrack != 0) {
SL_LOGD("TrackPlayerBase::start() from IPlayer");
//FIXME pipe this to SL player, not AudioTrack directly
if (mAudioTrack->start() == NO_ERROR) {
servicePlayerEvent(PLAYER_STATE_STARTED);
}
} else {
SL_LOGD("TrackPlayerBase::start() no AudioTrack to start from IPlayer");
}
}
void TrackPlayerBase::pause() {
if (mAudioTrack != 0) {
SL_LOGD("TrackPlayerBase::pause() from IPlayer");
//FIXME pipe this to SL player, not AudioTrack directly
mAudioTrack->pause();
servicePlayerEvent(PLAYER_STATE_PAUSED);
} else {
SL_LOGD("TrackPlayerBase::pause() no AudioTrack to pause from IPlayer");
}
}
void TrackPlayerBase::stop() {
if (mAudioTrack != 0) {
SL_LOGD("TrackPlayerBase::stop() from IPlayer");
//FIXME pipe this to SL player, not AudioTrack directly
mAudioTrack->stop();
servicePlayerEvent(PLAYER_STATE_STOPPED);
} else {
SL_LOGD("TrackPlayerBase::stop() no AudioTrack to stop from IPlayer");
}
}
void TrackPlayerBase::setVolume(float vol) {
float tl, tr = 1.0f;
{
Mutex::Autolock _l(mSettingsLock);
mVolumeMultiplierL = vol;
mVolumeMultiplierR = vol;
tl = mSlPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
tr = mSlPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
}
if (mAudioTrack != 0) {
SL_LOGD("TrackPlayerBase::setVolume() from IPlayer");
mAudioTrack->setVolume(tl, tr);
} else {
SL_LOGD("TrackPlayerBase::setVolume() no AudioTrack for volume control from IPlayer");
}
}
void TrackPlayerBase::setPan(float pan) {
float tl, tr = 1.0f;
{
Mutex::Autolock _l(mSettingsLock);
pan = min(max(-1.0f, pan), 1.0f);
if (pan >= 0.0f) {
mPanMultiplierL = 1.0f - pan;
mPanMultiplierR = 1.0f;
} else {
mPanMultiplierL = 1.0f;
mPanMultiplierR = 1.0f + pan;
}
tl = mSlPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
tr = mSlPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
}
if (mAudioTrack != 0) {
SL_LOGD("TrackPlayerBase::setPan() from IPlayer");
mAudioTrack->setVolume(tl, tr);
} else {
SL_LOGD("TrackPlayerBase::setPan() no AudioTrack for volume control from IPlayer");
}
}
void TrackPlayerBase::setStartDelayMs(int32_t delayMs) {
//FIXME not supported for SLES
SL_LOGW("setStartDelay() is not supported in OpenSL ES");
}
void TrackPlayerBase::applyVolumeShaper(
const sp<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation) {
if (mAudioTrack != 0) {
SL_LOGD("TrackPlayerBase::applyVolumeShaper() from IPlayer");
VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(configuration, operation);
if (status < 0) { // a non-negative value is the volume shaper id.
SL_LOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
}
} else {
SL_LOGD("TrackPlayerBase::applyVolumeShaper()"
" no AudioTrack for volume control from IPlayer");
}
}
status_t TrackPlayerBase::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
return BnPlayer::onTransact(code, data, reply, flags);
}
} // namespace android