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