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