IMediaPlayer.cpp revision 1173118eace0e9e347cb007f0da817cee87579ed
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 { // Avoid doing any extra copy. The interface descriptor should 196 // have been set by MediaPlayer.java. 197 return remote()->transact(INVOKE, request, reply); 198 } 199 200 status_t setMetadataFilter(const Parcel& request) 201 { 202 Parcel reply; 203 // Avoid doing any extra copy of the request. The interface 204 // descriptor should have been set by MediaPlayer.java. 205 remote()->transact(SET_METADATA_FILTER, request, &reply); 206 return reply.readInt32(); 207 } 208 209 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 210 { 211 Parcel request; 212 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 213 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 214 request.writeInt32(update_only); 215 request.writeInt32(apply_filter); 216 remote()->transact(GET_METADATA, request, reply); 217 return reply->readInt32(); 218 } 219 220 status_t setAuxEffectSendLevel(float level) 221 { 222 Parcel data, reply; 223 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 224 data.writeFloat(level); 225 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 226 return reply.readInt32(); 227 } 228 229 status_t attachAuxEffect(int effectId) 230 { 231 Parcel data, reply; 232 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 233 data.writeInt32(effectId); 234 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 235 return reply.readInt32(); 236 } 237 238}; 239 240IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 241 242// ---------------------------------------------------------------------- 243 244status_t BnMediaPlayer::onTransact( 245 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 246{ 247 switch(code) { 248 case DISCONNECT: { 249 CHECK_INTERFACE(IMediaPlayer, data, reply); 250 disconnect(); 251 return NO_ERROR; 252 } break; 253 case SET_VIDEO_SURFACE: { 254 CHECK_INTERFACE(IMediaPlayer, data, reply); 255 sp<Surface> surface = Surface::readFromParcel(data); 256 reply->writeInt32(setVideoSurface(surface)); 257 return NO_ERROR; 258 } break; 259 case SET_VIDEO_SURFACETEXTURE: { 260 CHECK_INTERFACE(IMediaPlayer, data, reply); 261 sp<ISurfaceTexture> surfaceTexture = 262 interface_cast<ISurfaceTexture>(data.readStrongBinder()); 263 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); 264 return NO_ERROR; 265 } break; 266 case PREPARE_ASYNC: { 267 CHECK_INTERFACE(IMediaPlayer, data, reply); 268 reply->writeInt32(prepareAsync()); 269 return NO_ERROR; 270 } break; 271 case START: { 272 CHECK_INTERFACE(IMediaPlayer, data, reply); 273 reply->writeInt32(start()); 274 return NO_ERROR; 275 } break; 276 case STOP: { 277 CHECK_INTERFACE(IMediaPlayer, data, reply); 278 reply->writeInt32(stop()); 279 return NO_ERROR; 280 } break; 281 case IS_PLAYING: { 282 CHECK_INTERFACE(IMediaPlayer, data, reply); 283 bool state; 284 status_t ret = isPlaying(&state); 285 reply->writeInt32(state); 286 reply->writeInt32(ret); 287 return NO_ERROR; 288 } break; 289 case PAUSE: { 290 CHECK_INTERFACE(IMediaPlayer, data, reply); 291 reply->writeInt32(pause()); 292 return NO_ERROR; 293 } break; 294 case SEEK_TO: { 295 CHECK_INTERFACE(IMediaPlayer, data, reply); 296 reply->writeInt32(seekTo(data.readInt32())); 297 return NO_ERROR; 298 } break; 299 case GET_CURRENT_POSITION: { 300 CHECK_INTERFACE(IMediaPlayer, data, reply); 301 int msec; 302 status_t ret = getCurrentPosition(&msec); 303 reply->writeInt32(msec); 304 reply->writeInt32(ret); 305 return NO_ERROR; 306 } break; 307 case GET_DURATION: { 308 CHECK_INTERFACE(IMediaPlayer, data, reply); 309 int msec; 310 status_t ret = getDuration(&msec); 311 reply->writeInt32(msec); 312 reply->writeInt32(ret); 313 return NO_ERROR; 314 } break; 315 case RESET: { 316 CHECK_INTERFACE(IMediaPlayer, data, reply); 317 reply->writeInt32(reset()); 318 return NO_ERROR; 319 } break; 320 case SET_AUDIO_STREAM_TYPE: { 321 CHECK_INTERFACE(IMediaPlayer, data, reply); 322 reply->writeInt32(setAudioStreamType(data.readInt32())); 323 return NO_ERROR; 324 } break; 325 case SET_LOOPING: { 326 CHECK_INTERFACE(IMediaPlayer, data, reply); 327 reply->writeInt32(setLooping(data.readInt32())); 328 return NO_ERROR; 329 } break; 330 case SET_VOLUME: { 331 CHECK_INTERFACE(IMediaPlayer, data, reply); 332 reply->writeInt32(setVolume(data.readFloat(), data.readFloat())); 333 return NO_ERROR; 334 } break; 335 case INVOKE: { 336 CHECK_INTERFACE(IMediaPlayer, data, reply); 337 invoke(data, reply); 338 return NO_ERROR; 339 } break; 340 case SET_METADATA_FILTER: { 341 CHECK_INTERFACE(IMediaPlayer, data, reply); 342 reply->writeInt32(setMetadataFilter(data)); 343 return NO_ERROR; 344 } break; 345 case GET_METADATA: { 346 CHECK_INTERFACE(IMediaPlayer, data, reply); 347 const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply); 348 reply->setDataPosition(0); 349 reply->writeInt32(retcode); 350 reply->setDataPosition(0); 351 return NO_ERROR; 352 } break; 353 case SET_AUX_EFFECT_SEND_LEVEL: { 354 CHECK_INTERFACE(IMediaPlayer, data, reply); 355 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 356 return NO_ERROR; 357 } break; 358 case ATTACH_AUX_EFFECT: { 359 CHECK_INTERFACE(IMediaPlayer, data, reply); 360 reply->writeInt32(attachAuxEffect(data.readInt32())); 361 return NO_ERROR; 362 } break; 363 default: 364 return BBinder::onTransact(code, data, reply, flags); 365 } 366} 367 368// ---------------------------------------------------------------------------- 369 370}; // namespace android 371