1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <binder/IServiceManager.h>
18#include <media/PlayerBase.h>
19
20#define max(a, b) ((a) > (b) ? (a) : (b))
21#define min(a, b) ((a) < (b) ? (a) : (b))
22
23namespace android {
24
25//--------------------------------------------------------------------------------------------------
26PlayerBase::PlayerBase() : BnPlayer(),
27        mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
28        mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
29        mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
30{
31    ALOGD("PlayerBase::PlayerBase()");
32    // use checkService() to avoid blocking if audio service is not up yet
33    sp<IBinder> binder = defaultServiceManager()->checkService(String16("audio"));
34    if (binder == 0) {
35        ALOGE("PlayerBase(): binding to audio service failed, service up?");
36    } else {
37        mAudioManager = interface_cast<IAudioManager>(binder);
38    }
39}
40
41
42PlayerBase::~PlayerBase() {
43    ALOGD("PlayerBase::~PlayerBase()");
44    baseDestroy();
45}
46
47void PlayerBase::init(player_type_t playerType, audio_usage_t usage) {
48    if (mAudioManager == 0) {
49                ALOGE("AudioPlayer realize: no audio service, player will not be registered");
50    } else {
51        mPIId = mAudioManager->trackPlayer(playerType, usage, AUDIO_CONTENT_TYPE_UNKNOWN, this);
52    }
53}
54
55void PlayerBase::baseDestroy() {
56    serviceReleasePlayer();
57    if (mAudioManager != 0) {
58        mAudioManager.clear();
59    }
60}
61
62//------------------------------------------------------------------------------
63void PlayerBase::servicePlayerEvent(player_state_t event) {
64    if (mAudioManager != 0) {
65        // only report state change
66        Mutex::Autolock _l(mPlayerStateLock);
67        if (event != mLastReportedEvent
68                && mPIId != PLAYER_PIID_INVALID) {
69            mLastReportedEvent = event;
70            mAudioManager->playerEvent(mPIId, event);
71        }
72    }
73}
74
75void PlayerBase::serviceReleasePlayer() {
76    if (mAudioManager != 0
77            && mPIId != PLAYER_PIID_INVALID) {
78        mAudioManager->releasePlayer(mPIId);
79    }
80}
81
82//FIXME temporary method while some AudioTrack state is outside of this class
83void PlayerBase::reportEvent(player_state_t event) {
84    servicePlayerEvent(event);
85}
86
87status_t PlayerBase::startWithStatus() {
88    status_t status = playerStart();
89    if (status == NO_ERROR) {
90        ALOGD("PlayerBase::start() from IPlayer");
91        servicePlayerEvent(PLAYER_STATE_STARTED);
92    } else {
93        ALOGD("PlayerBase::start() no AudioTrack to start from IPlayer");
94    }
95    return status;
96}
97
98//------------------------------------------------------------------------------
99// Implementation of IPlayer
100void PlayerBase::start() {
101    (void)startWithStatus();
102}
103
104void PlayerBase::pause() {
105    if (playerPause() == NO_ERROR) {
106        ALOGD("PlayerBase::pause() from IPlayer");
107        servicePlayerEvent(PLAYER_STATE_PAUSED);
108    } else {
109        ALOGD("PlayerBase::pause() no AudioTrack to pause from IPlayer");
110    }
111}
112
113
114void PlayerBase::stop() {
115    if (playerStop() == NO_ERROR) {
116        ALOGD("PlayerBase::stop() from IPlayer");
117        servicePlayerEvent(PLAYER_STATE_STOPPED);
118    } else {
119        ALOGD("PlayerBase::stop() no AudioTrack to stop from IPlayer");
120    }
121}
122
123void PlayerBase::setVolume(float vol) {
124    {
125        Mutex::Autolock _l(mSettingsLock);
126        mVolumeMultiplierL = vol;
127        mVolumeMultiplierR = vol;
128    }
129    if (playerSetVolume() == NO_ERROR) {
130        ALOGD("PlayerBase::setVolume() from IPlayer");
131    } else {
132        ALOGD("PlayerBase::setVolume() no AudioTrack for volume control from IPlayer");
133    }
134}
135
136void PlayerBase::setPan(float pan) {
137    {
138        Mutex::Autolock _l(mSettingsLock);
139        pan = min(max(-1.0f, pan), 1.0f);
140        if (pan >= 0.0f) {
141            mPanMultiplierL = 1.0f - pan;
142            mPanMultiplierR = 1.0f;
143        } else {
144            mPanMultiplierL = 1.0f;
145            mPanMultiplierR = 1.0f + pan;
146        }
147    }
148    if (playerSetVolume() == NO_ERROR) {
149        ALOGD("PlayerBase::setPan() from IPlayer");
150    } else {
151        ALOGD("PlayerBase::setPan() no AudioTrack for volume control from IPlayer");
152    }
153}
154
155void PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
156    ALOGW("setStartDelay() is not supported");
157}
158
159void PlayerBase::applyVolumeShaper(
160        const sp<VolumeShaper::Configuration>& configuration  __unused,
161        const sp<VolumeShaper::Operation>& operation __unused) {
162    ALOGW("applyVolumeShaper() is not supported");
163}
164
165status_t PlayerBase::onTransact(
166    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
167{
168    return BnPlayer::onTransact(code, data, reply, flags);
169}
170
171} // namespace android
172