/* ** ** 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 #include #include #include #include #include #include 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, SET_AUX_EFFECT_SEND_LEVEL, ATTACH_AUX_EFFECT, SET_VIDEO_SURFACETEXTURE, SET_PARAMETER, GET_PARAMETER, }; class BpMediaPlayer: public BpInterface { public: BpMediaPlayer(const sp& impl) : BpInterface(impl) { } // disconnect from media player service void disconnect() { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); remote()->transact(DISCONNECT, data, &reply); } // pass the buffered Surface to the media player service status_t setVideoSurface(const sp& surface) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); Surface::writeToParcel(surface, &data); remote()->transact(SET_VIDEO_SURFACE, data, &reply); return reply.readInt32(); } // pass the buffered ISurfaceTexture to the media player service status_t setVideoSurfaceTexture(const sp& surfaceTexture) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); sp b(surfaceTexture->asBinder()); data.writeStrongBinder(b); remote()->transact(SET_VIDEO_SURFACETEXTURE, 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 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 setParameter(int key, const Parcel& request) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); data.writeInt32(key); if (request.dataSize() > 0) { data.appendFrom(const_cast(&request), 0, request.dataSize()); } remote()->transact(SET_PARAMETER, data, &reply); return reply.readInt32(); } status_t getParameter(int key, Parcel *reply) { Parcel data; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); data.writeInt32(key); return remote()->transact(GET_PARAMETER, data, reply); } }; 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 surface = Surface::readFromParcel(data); reply->writeInt32(setVideoSurface(surface)); return NO_ERROR; } break; case SET_VIDEO_SURFACETEXTURE: { CHECK_INTERFACE(IMediaPlayer, data, reply); sp surfaceTexture = interface_cast(data.readStrongBinder()); reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); 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); float leftVolume = data.readFloat(); float rightVolume = data.readFloat(); reply->writeInt32(setVolume(leftVolume, rightVolume)); return NO_ERROR; } break; case INVOKE: { CHECK_INTERFACE(IMediaPlayer, data, reply); status_t result = invoke(data, reply); return result; } break; case SET_METADATA_FILTER: { CHECK_INTERFACE(IMediaPlayer, data, reply); reply->writeInt32(setMetadataFilter(data)); return NO_ERROR; } break; case GET_METADATA: { CHECK_INTERFACE(IMediaPlayer, data, reply); bool update_only = static_cast(data.readInt32()); bool apply_filter = static_cast(data.readInt32()); const status_t retcode = getMetadata(update_only, apply_filter, 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_PARAMETER: { CHECK_INTERFACE(IMediaPlayer, data, reply); int key = data.readInt32(); Parcel request; if (data.dataAvail() > 0) { request.appendFrom( const_cast(&data), data.dataPosition(), data.dataAvail()); } request.setDataPosition(0); reply->writeInt32(setParameter(key, request)); return NO_ERROR; } break; case GET_PARAMETER: { CHECK_INTERFACE(IMediaPlayer, data, reply); return getParameter(data.readInt32(), reply); } break; default: return BBinder::onTransact(code, data, reply, flags); } } // ---------------------------------------------------------------------------- }; // namespace android