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