IMediaPlayer.cpp revision 0a5ca668c6f7d45706e9aec4a1dfec0aacc6d233
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 27namespace android { 28 29enum { 30 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 31 SET_VIDEO_SURFACE, 32 PREPARE_ASYNC, 33 START, 34 STOP, 35 IS_PLAYING, 36 PAUSE, 37 SEEK_TO, 38 GET_CURRENT_POSITION, 39 GET_DURATION, 40 RESET, 41 SET_AUDIO_STREAM_TYPE, 42 SET_LOOPING, 43 SET_VOLUME, 44 INVOKE, 45 SET_METADATA_FILTER, 46 GET_METADATA, 47 SET_AUX_EFFECT_SEND_LEVEL, 48 ATTACH_AUX_EFFECT 49}; 50 51class BpMediaPlayer: public BpInterface<IMediaPlayer> 52{ 53public: 54 BpMediaPlayer(const sp<IBinder>& impl) 55 : BpInterface<IMediaPlayer>(impl) 56 { 57 } 58 59 // disconnect from media player service 60 void disconnect() 61 { 62 Parcel data, reply; 63 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 64 remote()->transact(DISCONNECT, data, &reply); 65 } 66 67 status_t setVideoSurface(const sp<Surface>& surface) 68 { 69 Parcel data, reply; 70 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 71 Surface::writeToParcel(surface, &data); 72 remote()->transact(SET_VIDEO_SURFACE, data, &reply); 73 return reply.readInt32(); 74 } 75 76 status_t prepareAsync() 77 { 78 Parcel data, reply; 79 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 80 remote()->transact(PREPARE_ASYNC, data, &reply); 81 return reply.readInt32(); 82 } 83 84 status_t start() 85 { 86 Parcel data, reply; 87 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 88 remote()->transact(START, data, &reply); 89 return reply.readInt32(); 90 } 91 92 status_t stop() 93 { 94 Parcel data, reply; 95 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 96 remote()->transact(STOP, data, &reply); 97 return reply.readInt32(); 98 } 99 100 status_t isPlaying(bool* state) 101 { 102 Parcel data, reply; 103 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 104 remote()->transact(IS_PLAYING, data, &reply); 105 *state = reply.readInt32(); 106 return reply.readInt32(); 107 } 108 109 status_t pause() 110 { 111 Parcel data, reply; 112 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 113 remote()->transact(PAUSE, data, &reply); 114 return reply.readInt32(); 115 } 116 117 status_t seekTo(int msec) 118 { 119 Parcel data, reply; 120 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 121 data.writeInt32(msec); 122 remote()->transact(SEEK_TO, data, &reply); 123 return reply.readInt32(); 124 } 125 126 status_t getCurrentPosition(int* msec) 127 { 128 Parcel data, reply; 129 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 130 remote()->transact(GET_CURRENT_POSITION, data, &reply); 131 *msec = reply.readInt32(); 132 return reply.readInt32(); 133 } 134 135 status_t getDuration(int* msec) 136 { 137 Parcel data, reply; 138 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 139 remote()->transact(GET_DURATION, data, &reply); 140 *msec = reply.readInt32(); 141 return reply.readInt32(); 142 } 143 144 status_t reset() 145 { 146 Parcel data, reply; 147 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 148 remote()->transact(RESET, data, &reply); 149 return reply.readInt32(); 150 } 151 152 status_t setAudioStreamType(int type) 153 { 154 Parcel data, reply; 155 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 156 data.writeInt32(type); 157 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); 158 return reply.readInt32(); 159 } 160 161 status_t setLooping(int loop) 162 { 163 Parcel data, reply; 164 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 165 data.writeInt32(loop); 166 remote()->transact(SET_LOOPING, data, &reply); 167 return reply.readInt32(); 168 } 169 170 status_t setVolume(float leftVolume, float rightVolume) 171 { 172 Parcel data, reply; 173 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 174 data.writeFloat(leftVolume); 175 data.writeFloat(rightVolume); 176 remote()->transact(SET_VOLUME, data, &reply); 177 return reply.readInt32(); 178 } 179 180 status_t invoke(const Parcel& request, Parcel *reply) 181 { // Avoid doing any extra copy. The interface descriptor should 182 // have been set by MediaPlayer.java. 183 return remote()->transact(INVOKE, request, reply); 184 } 185 186 status_t setMetadataFilter(const Parcel& request) 187 { 188 Parcel reply; 189 // Avoid doing any extra copy of the request. The interface 190 // descriptor should have been set by MediaPlayer.java. 191 remote()->transact(SET_METADATA_FILTER, request, &reply); 192 return reply.readInt32(); 193 } 194 195 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 196 { 197 Parcel request; 198 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 199 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 200 request.writeInt32(update_only); 201 request.writeInt32(apply_filter); 202 remote()->transact(GET_METADATA, request, reply); 203 return reply->readInt32(); 204 } 205 206 status_t setAuxEffectSendLevel(float level) 207 { 208 Parcel data, reply; 209 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 210 data.writeFloat(level); 211 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 212 return reply.readInt32(); 213 } 214 215 status_t attachAuxEffect(int effectId) 216 { 217 Parcel data, reply; 218 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 219 data.writeInt32(effectId); 220 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 221 return reply.readInt32(); 222 } 223}; 224 225IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 226 227// ---------------------------------------------------------------------- 228 229status_t BnMediaPlayer::onTransact( 230 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 231{ 232 switch(code) { 233 case DISCONNECT: { 234 CHECK_INTERFACE(IMediaPlayer, data, reply); 235 disconnect(); 236 return NO_ERROR; 237 } break; 238 case SET_VIDEO_SURFACE: { 239 CHECK_INTERFACE(IMediaPlayer, data, reply); 240 sp<Surface> surface = Surface::readFromParcel(data); 241 reply->writeInt32(setVideoSurface(surface)); 242 return NO_ERROR; 243 } break; 244 case PREPARE_ASYNC: { 245 CHECK_INTERFACE(IMediaPlayer, data, reply); 246 reply->writeInt32(prepareAsync()); 247 return NO_ERROR; 248 } break; 249 case START: { 250 CHECK_INTERFACE(IMediaPlayer, data, reply); 251 reply->writeInt32(start()); 252 return NO_ERROR; 253 } break; 254 case STOP: { 255 CHECK_INTERFACE(IMediaPlayer, data, reply); 256 reply->writeInt32(stop()); 257 return NO_ERROR; 258 } break; 259 case IS_PLAYING: { 260 CHECK_INTERFACE(IMediaPlayer, data, reply); 261 bool state; 262 status_t ret = isPlaying(&state); 263 reply->writeInt32(state); 264 reply->writeInt32(ret); 265 return NO_ERROR; 266 } break; 267 case PAUSE: { 268 CHECK_INTERFACE(IMediaPlayer, data, reply); 269 reply->writeInt32(pause()); 270 return NO_ERROR; 271 } break; 272 case SEEK_TO: { 273 CHECK_INTERFACE(IMediaPlayer, data, reply); 274 reply->writeInt32(seekTo(data.readInt32())); 275 return NO_ERROR; 276 } break; 277 case GET_CURRENT_POSITION: { 278 CHECK_INTERFACE(IMediaPlayer, data, reply); 279 int msec; 280 status_t ret = getCurrentPosition(&msec); 281 reply->writeInt32(msec); 282 reply->writeInt32(ret); 283 return NO_ERROR; 284 } break; 285 case GET_DURATION: { 286 CHECK_INTERFACE(IMediaPlayer, data, reply); 287 int msec; 288 status_t ret = getDuration(&msec); 289 reply->writeInt32(msec); 290 reply->writeInt32(ret); 291 return NO_ERROR; 292 } break; 293 case RESET: { 294 CHECK_INTERFACE(IMediaPlayer, data, reply); 295 reply->writeInt32(reset()); 296 return NO_ERROR; 297 } break; 298 case SET_AUDIO_STREAM_TYPE: { 299 CHECK_INTERFACE(IMediaPlayer, data, reply); 300 reply->writeInt32(setAudioStreamType(data.readInt32())); 301 return NO_ERROR; 302 } break; 303 case SET_LOOPING: { 304 CHECK_INTERFACE(IMediaPlayer, data, reply); 305 reply->writeInt32(setLooping(data.readInt32())); 306 return NO_ERROR; 307 } break; 308 case SET_VOLUME: { 309 CHECK_INTERFACE(IMediaPlayer, data, reply); 310 reply->writeInt32(setVolume(data.readFloat(), data.readFloat())); 311 return NO_ERROR; 312 } break; 313 case INVOKE: { 314 CHECK_INTERFACE(IMediaPlayer, data, reply); 315 invoke(data, reply); 316 return NO_ERROR; 317 } break; 318 case SET_METADATA_FILTER: { 319 CHECK_INTERFACE(IMediaPlayer, data, reply); 320 reply->writeInt32(setMetadataFilter(data)); 321 return NO_ERROR; 322 } break; 323 case GET_METADATA: { 324 CHECK_INTERFACE(IMediaPlayer, data, reply); 325 const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply); 326 reply->setDataPosition(0); 327 reply->writeInt32(retcode); 328 reply->setDataPosition(0); 329 return NO_ERROR; 330 } break; 331 case SET_AUX_EFFECT_SEND_LEVEL: { 332 CHECK_INTERFACE(IMediaPlayer, data, reply); 333 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 334 return NO_ERROR; 335 } break; 336 case ATTACH_AUX_EFFECT: { 337 CHECK_INTERFACE(IMediaPlayer, data, reply); 338 reply->writeInt32(attachAuxEffect(data.readInt32())); 339 return NO_ERROR; 340 } break; 341 default: 342 return BBinder::onTransact(code, data, reply, flags); 343 } 344} 345 346// ---------------------------------------------------------------------------- 347 348}; // namespace android 349