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