IMediaPlayer.cpp revision 040e4a14ef9cafd5d08d9a180e6237fb79687995
1/* 2** 3** Copyright 2008, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include <stdint.h> 19#include <sys/types.h> 20 21#include <binder/Parcel.h> 22 23#include <media/IMediaPlayer.h> 24#include <surfaceflinger/ISurface.h> 25#include <surfaceflinger/Surface.h> 26#include <gui/ISurfaceTexture.h> 27 28namespace android { 29 30enum { 31 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 32 SET_VIDEO_SURFACE, 33 PREPARE_ASYNC, 34 START, 35 STOP, 36 IS_PLAYING, 37 PAUSE, 38 SEEK_TO, 39 GET_CURRENT_POSITION, 40 GET_DURATION, 41 RESET, 42 SET_AUDIO_STREAM_TYPE, 43 SET_LOOPING, 44 SET_VOLUME, 45 INVOKE, 46 SET_METADATA_FILTER, 47 GET_METADATA, 48 SET_AUX_EFFECT_SEND_LEVEL, 49 ATTACH_AUX_EFFECT, 50 SET_VIDEO_SURFACETEXTURE, 51}; 52 53class BpMediaPlayer: public BpInterface<IMediaPlayer> 54{ 55public: 56 BpMediaPlayer(const sp<IBinder>& impl) 57 : BpInterface<IMediaPlayer>(impl) 58 { 59 } 60 61 // disconnect from media player service 62 void disconnect() 63 { 64 Parcel data, reply; 65 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 66 remote()->transact(DISCONNECT, data, &reply); 67 } 68 69 // pass the buffered Surface to the media player service 70 status_t setVideoSurface(const sp<Surface>& surface) 71 { 72 Parcel data, reply; 73 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 74 Surface::writeToParcel(surface, &data); 75 remote()->transact(SET_VIDEO_SURFACE, data, &reply); 76 return reply.readInt32(); 77 } 78 79 // pass the buffered ISurfaceTexture to the media player service 80 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) 81 { 82 Parcel data, reply; 83 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 84 sp<IBinder> b(surfaceTexture->asBinder()); 85 data.writeStrongBinder(b); 86 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); 87 return reply.readInt32(); 88 } 89 90 status_t prepareAsync() 91 { 92 Parcel data, reply; 93 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 94 remote()->transact(PREPARE_ASYNC, data, &reply); 95 return reply.readInt32(); 96 } 97 98 status_t start() 99 { 100 Parcel data, reply; 101 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 102 remote()->transact(START, data, &reply); 103 return reply.readInt32(); 104 } 105 106 status_t stop() 107 { 108 Parcel data, reply; 109 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 110 remote()->transact(STOP, data, &reply); 111 return reply.readInt32(); 112 } 113 114 status_t isPlaying(bool* state) 115 { 116 Parcel data, reply; 117 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 118 remote()->transact(IS_PLAYING, data, &reply); 119 *state = reply.readInt32(); 120 return reply.readInt32(); 121 } 122 123 status_t pause() 124 { 125 Parcel data, reply; 126 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 127 remote()->transact(PAUSE, data, &reply); 128 return reply.readInt32(); 129 } 130 131 status_t seekTo(int msec) 132 { 133 Parcel data, reply; 134 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 135 data.writeInt32(msec); 136 remote()->transact(SEEK_TO, data, &reply); 137 return reply.readInt32(); 138 } 139 140 status_t getCurrentPosition(int* msec) 141 { 142 Parcel data, reply; 143 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 144 remote()->transact(GET_CURRENT_POSITION, data, &reply); 145 *msec = reply.readInt32(); 146 return reply.readInt32(); 147 } 148 149 status_t getDuration(int* msec) 150 { 151 Parcel data, reply; 152 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 153 remote()->transact(GET_DURATION, data, &reply); 154 *msec = reply.readInt32(); 155 return reply.readInt32(); 156 } 157 158 status_t reset() 159 { 160 Parcel data, reply; 161 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 162 remote()->transact(RESET, data, &reply); 163 return reply.readInt32(); 164 } 165 166 status_t setAudioStreamType(int type) 167 { 168 Parcel data, reply; 169 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 170 data.writeInt32(type); 171 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); 172 return reply.readInt32(); 173 } 174 175 status_t setLooping(int loop) 176 { 177 Parcel data, reply; 178 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 179 data.writeInt32(loop); 180 remote()->transact(SET_LOOPING, data, &reply); 181 return reply.readInt32(); 182 } 183 184 status_t setVolume(float leftVolume, float rightVolume) 185 { 186 Parcel data, reply; 187 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 188 data.writeFloat(leftVolume); 189 data.writeFloat(rightVolume); 190 remote()->transact(SET_VOLUME, data, &reply); 191 return reply.readInt32(); 192 } 193 194 status_t invoke(const Parcel& request, Parcel *reply) 195 { 196 // Avoid doing any extra copy. The interface descriptor should 197 // have been set by MediaPlayer.java. 198 return remote()->transact(INVOKE, request, reply); 199 } 200 201 status_t setMetadataFilter(const Parcel& request) 202 { 203 Parcel reply; 204 // Avoid doing any extra copy of the request. The interface 205 // descriptor should have been set by MediaPlayer.java. 206 remote()->transact(SET_METADATA_FILTER, request, &reply); 207 return reply.readInt32(); 208 } 209 210 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 211 { 212 Parcel request; 213 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 214 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 215 request.writeInt32(update_only); 216 request.writeInt32(apply_filter); 217 remote()->transact(GET_METADATA, request, reply); 218 return reply->readInt32(); 219 } 220 221 status_t setAuxEffectSendLevel(float level) 222 { 223 Parcel data, reply; 224 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 225 data.writeFloat(level); 226 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 227 return reply.readInt32(); 228 } 229 230 status_t attachAuxEffect(int effectId) 231 { 232 Parcel data, reply; 233 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 234 data.writeInt32(effectId); 235 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 236 return reply.readInt32(); 237 } 238 239}; 240 241IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 242 243// ---------------------------------------------------------------------- 244 245status_t BnMediaPlayer::onTransact( 246 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 247{ 248 switch(code) { 249 case DISCONNECT: { 250 CHECK_INTERFACE(IMediaPlayer, data, reply); 251 disconnect(); 252 return NO_ERROR; 253 } break; 254 case SET_VIDEO_SURFACE: { 255 CHECK_INTERFACE(IMediaPlayer, data, reply); 256 sp<Surface> surface = Surface::readFromParcel(data); 257 reply->writeInt32(setVideoSurface(surface)); 258 return NO_ERROR; 259 } break; 260 case SET_VIDEO_SURFACETEXTURE: { 261 CHECK_INTERFACE(IMediaPlayer, data, reply); 262 sp<ISurfaceTexture> surfaceTexture = 263 interface_cast<ISurfaceTexture>(data.readStrongBinder()); 264 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); 265 return NO_ERROR; 266 } break; 267 case PREPARE_ASYNC: { 268 CHECK_INTERFACE(IMediaPlayer, data, reply); 269 reply->writeInt32(prepareAsync()); 270 return NO_ERROR; 271 } break; 272 case START: { 273 CHECK_INTERFACE(IMediaPlayer, data, reply); 274 reply->writeInt32(start()); 275 return NO_ERROR; 276 } break; 277 case STOP: { 278 CHECK_INTERFACE(IMediaPlayer, data, reply); 279 reply->writeInt32(stop()); 280 return NO_ERROR; 281 } break; 282 case IS_PLAYING: { 283 CHECK_INTERFACE(IMediaPlayer, data, reply); 284 bool state; 285 status_t ret = isPlaying(&state); 286 reply->writeInt32(state); 287 reply->writeInt32(ret); 288 return NO_ERROR; 289 } break; 290 case PAUSE: { 291 CHECK_INTERFACE(IMediaPlayer, data, reply); 292 reply->writeInt32(pause()); 293 return NO_ERROR; 294 } break; 295 case SEEK_TO: { 296 CHECK_INTERFACE(IMediaPlayer, data, reply); 297 reply->writeInt32(seekTo(data.readInt32())); 298 return NO_ERROR; 299 } break; 300 case GET_CURRENT_POSITION: { 301 CHECK_INTERFACE(IMediaPlayer, data, reply); 302 int msec; 303 status_t ret = getCurrentPosition(&msec); 304 reply->writeInt32(msec); 305 reply->writeInt32(ret); 306 return NO_ERROR; 307 } break; 308 case GET_DURATION: { 309 CHECK_INTERFACE(IMediaPlayer, data, reply); 310 int msec; 311 status_t ret = getDuration(&msec); 312 reply->writeInt32(msec); 313 reply->writeInt32(ret); 314 return NO_ERROR; 315 } break; 316 case RESET: { 317 CHECK_INTERFACE(IMediaPlayer, data, reply); 318 reply->writeInt32(reset()); 319 return NO_ERROR; 320 } break; 321 case SET_AUDIO_STREAM_TYPE: { 322 CHECK_INTERFACE(IMediaPlayer, data, reply); 323 reply->writeInt32(setAudioStreamType(data.readInt32())); 324 return NO_ERROR; 325 } break; 326 case SET_LOOPING: { 327 CHECK_INTERFACE(IMediaPlayer, data, reply); 328 reply->writeInt32(setLooping(data.readInt32())); 329 return NO_ERROR; 330 } break; 331 case SET_VOLUME: { 332 CHECK_INTERFACE(IMediaPlayer, data, reply); 333 reply->writeInt32(setVolume(data.readFloat(), data.readFloat())); 334 return NO_ERROR; 335 } break; 336 case INVOKE: { 337 CHECK_INTERFACE(IMediaPlayer, data, reply); 338 status_t result = invoke(data, reply); 339 return result; 340 } break; 341 case SET_METADATA_FILTER: { 342 CHECK_INTERFACE(IMediaPlayer, data, reply); 343 reply->writeInt32(setMetadataFilter(data)); 344 return NO_ERROR; 345 } break; 346 case GET_METADATA: { 347 CHECK_INTERFACE(IMediaPlayer, data, reply); 348 const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply); 349 reply->setDataPosition(0); 350 reply->writeInt32(retcode); 351 reply->setDataPosition(0); 352 return NO_ERROR; 353 } break; 354 case SET_AUX_EFFECT_SEND_LEVEL: { 355 CHECK_INTERFACE(IMediaPlayer, data, reply); 356 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 357 return NO_ERROR; 358 } break; 359 case ATTACH_AUX_EFFECT: { 360 CHECK_INTERFACE(IMediaPlayer, data, reply); 361 reply->writeInt32(attachAuxEffect(data.readInt32())); 362 return NO_ERROR; 363 } break; 364 default: 365 return BBinder::onTransact(code, data, reply, flags); 366 } 367} 368 369// ---------------------------------------------------------------------------- 370 371}; // namespace android 372