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