397 lines
12 KiB
C++
397 lines
12 KiB
C++
|
/*
|
||
|
**
|
||
|
** Copyright 2008, 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 <stdint.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
#include <binder/Parcel.h>
|
||
|
|
||
|
#include <media/IMediaPlayer.h>
|
||
|
#include <surfaceflinger/ISurface.h>
|
||
|
|
||
|
#include <utils/String8.h>
|
||
|
|
||
|
namespace android {
|
||
|
|
||
|
enum {
|
||
|
DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
|
||
|
SET_VIDEO_SURFACE,
|
||
|
PREPARE_ASYNC,
|
||
|
START,
|
||
|
STOP,
|
||
|
IS_PLAYING,
|
||
|
PAUSE,
|
||
|
SEEK_TO,
|
||
|
GET_CURRENT_POSITION,
|
||
|
GET_DURATION,
|
||
|
RESET,
|
||
|
SET_AUDIO_STREAM_TYPE,
|
||
|
SET_LOOPING,
|
||
|
SET_VOLUME,
|
||
|
INVOKE,
|
||
|
SET_METADATA_FILTER,
|
||
|
GET_METADATA,
|
||
|
SUSPEND,
|
||
|
RESUME,
|
||
|
SET_AUX_EFFECT_SEND_LEVEL,
|
||
|
ATTACH_AUX_EFFECT,
|
||
|
SET_PARAMETERS
|
||
|
};
|
||
|
|
||
|
class BpMediaPlayer: public BpInterface<IMediaPlayer>
|
||
|
{
|
||
|
public:
|
||
|
BpMediaPlayer(const sp<IBinder>& impl)
|
||
|
: BpInterface<IMediaPlayer>(impl)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// disconnect from media player service
|
||
|
void disconnect()
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(DISCONNECT, data, &reply);
|
||
|
}
|
||
|
|
||
|
status_t setVideoSurface(const sp<ISurface>& surface)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
data.writeStrongBinder(surface->asBinder());
|
||
|
remote()->transact(SET_VIDEO_SURFACE, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t prepareAsync()
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(PREPARE_ASYNC, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t start()
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(START, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t stop()
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(STOP, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t isPlaying(bool* state)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(IS_PLAYING, data, &reply);
|
||
|
*state = reply.readInt32();
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t pause()
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(PAUSE, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t seekTo(int msec)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
data.writeInt32(msec);
|
||
|
remote()->transact(SEEK_TO, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t getCurrentPosition(int* msec)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(GET_CURRENT_POSITION, data, &reply);
|
||
|
*msec = reply.readInt32();
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t getDuration(int* msec)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(GET_DURATION, data, &reply);
|
||
|
*msec = reply.readInt32();
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t reset()
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
remote()->transact(RESET, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t setAudioStreamType(int type)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
data.writeInt32(type);
|
||
|
remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t setLooping(int loop)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
data.writeInt32(loop);
|
||
|
remote()->transact(SET_LOOPING, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t setVolume(float leftVolume, float rightVolume)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
data.writeFloat(leftVolume);
|
||
|
data.writeFloat(rightVolume);
|
||
|
remote()->transact(SET_VOLUME, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t invoke(const Parcel& request, Parcel *reply)
|
||
|
{ // Avoid doing any extra copy. The interface descriptor should
|
||
|
// have been set by MediaPlayer.java.
|
||
|
return remote()->transact(INVOKE, request, reply);
|
||
|
}
|
||
|
|
||
|
status_t setMetadataFilter(const Parcel& request)
|
||
|
{
|
||
|
Parcel reply;
|
||
|
// Avoid doing any extra copy of the request. The interface
|
||
|
// descriptor should have been set by MediaPlayer.java.
|
||
|
remote()->transact(SET_METADATA_FILTER, request, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
|
||
|
{
|
||
|
Parcel request;
|
||
|
request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
// TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
|
||
|
request.writeInt32(update_only);
|
||
|
request.writeInt32(apply_filter);
|
||
|
remote()->transact(GET_METADATA, request, reply);
|
||
|
return reply->readInt32();
|
||
|
}
|
||
|
|
||
|
status_t suspend() {
|
||
|
Parcel request;
|
||
|
request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
|
||
|
Parcel reply;
|
||
|
remote()->transact(SUSPEND, request, &reply);
|
||
|
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
|
||
|
status_t resume() {
|
||
|
Parcel request;
|
||
|
request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
|
||
|
Parcel reply;
|
||
|
remote()->transact(RESUME, request, &reply);
|
||
|
|
||
|
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();
|
||
|
}
|
||
|
|
||
|
status_t setParameters(const String8& params)
|
||
|
{
|
||
|
Parcel data, reply;
|
||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||
|
data.writeString8(params);
|
||
|
remote()->transact(SET_PARAMETERS, data, &reply);
|
||
|
return reply.readInt32();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
|
||
|
|
||
|
// ----------------------------------------------------------------------
|
||
|
|
||
|
status_t BnMediaPlayer::onTransact(
|
||
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||
|
{
|
||
|
switch(code) {
|
||
|
case DISCONNECT: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
disconnect();
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SET_VIDEO_SURFACE: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
|
||
|
reply->writeInt32(setVideoSurface(surface));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case PREPARE_ASYNC: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(prepareAsync());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case START: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(start());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case STOP: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(stop());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case IS_PLAYING: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
bool state;
|
||
|
status_t ret = isPlaying(&state);
|
||
|
reply->writeInt32(state);
|
||
|
reply->writeInt32(ret);
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case PAUSE: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(pause());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SEEK_TO: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(seekTo(data.readInt32()));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case GET_CURRENT_POSITION: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
int msec;
|
||
|
status_t ret = getCurrentPosition(&msec);
|
||
|
reply->writeInt32(msec);
|
||
|
reply->writeInt32(ret);
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case GET_DURATION: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
int msec;
|
||
|
status_t ret = getDuration(&msec);
|
||
|
reply->writeInt32(msec);
|
||
|
reply->writeInt32(ret);
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case RESET: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(reset());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SET_AUDIO_STREAM_TYPE: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(setAudioStreamType(data.readInt32()));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SET_LOOPING: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(setLooping(data.readInt32()));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SET_VOLUME: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(setVolume(data.readFloat(), data.readFloat()));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case INVOKE: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
invoke(data, reply);
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SET_METADATA_FILTER: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(setMetadataFilter(data));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case SUSPEND: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(suspend());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case RESUME: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(resume());
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
case GET_METADATA: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply);
|
||
|
reply->setDataPosition(0);
|
||
|
reply->writeInt32(retcode);
|
||
|
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;
|
||
|
case SET_PARAMETERS: {
|
||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||
|
reply->writeInt32(setParameters(data.readString8()));
|
||
|
return NO_ERROR;
|
||
|
} break;
|
||
|
default:
|
||
|
return BBinder::onTransact(code, data, reply, flags);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
}; // namespace android
|