IMediaPlayer.cpp revision 1173118eace0e9e347cb007f0da817cee87579ed
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    { // Avoid doing any extra copy. The interface descriptor should
196      // have been set by MediaPlayer.java.
197        return remote()->transact(INVOKE, request, reply);
198    }
199
200    status_t setMetadataFilter(const Parcel& request)
201    {
202        Parcel reply;
203        // Avoid doing any extra copy of the request. The interface
204        // descriptor should have been set by MediaPlayer.java.
205        remote()->transact(SET_METADATA_FILTER, request, &reply);
206        return reply.readInt32();
207    }
208
209    status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
210    {
211        Parcel request;
212        request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
213        // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
214        request.writeInt32(update_only);
215        request.writeInt32(apply_filter);
216        remote()->transact(GET_METADATA, request, reply);
217        return reply->readInt32();
218    }
219
220    status_t setAuxEffectSendLevel(float level)
221    {
222        Parcel data, reply;
223        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
224        data.writeFloat(level);
225        remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
226        return reply.readInt32();
227    }
228
229    status_t attachAuxEffect(int effectId)
230    {
231        Parcel data, reply;
232        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
233        data.writeInt32(effectId);
234        remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
235        return reply.readInt32();
236    }
237
238};
239
240IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
241
242// ----------------------------------------------------------------------
243
244status_t BnMediaPlayer::onTransact(
245    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
246{
247    switch(code) {
248        case DISCONNECT: {
249            CHECK_INTERFACE(IMediaPlayer, data, reply);
250            disconnect();
251            return NO_ERROR;
252        } break;
253        case SET_VIDEO_SURFACE: {
254            CHECK_INTERFACE(IMediaPlayer, data, reply);
255            sp<Surface> surface = Surface::readFromParcel(data);
256            reply->writeInt32(setVideoSurface(surface));
257            return NO_ERROR;
258        } break;
259        case SET_VIDEO_SURFACETEXTURE: {
260            CHECK_INTERFACE(IMediaPlayer, data, reply);
261            sp<ISurfaceTexture> surfaceTexture =
262                    interface_cast<ISurfaceTexture>(data.readStrongBinder());
263            reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
264            return NO_ERROR;
265        } break;
266        case PREPARE_ASYNC: {
267            CHECK_INTERFACE(IMediaPlayer, data, reply);
268            reply->writeInt32(prepareAsync());
269            return NO_ERROR;
270        } break;
271        case START: {
272            CHECK_INTERFACE(IMediaPlayer, data, reply);
273            reply->writeInt32(start());
274            return NO_ERROR;
275        } break;
276        case STOP: {
277            CHECK_INTERFACE(IMediaPlayer, data, reply);
278            reply->writeInt32(stop());
279            return NO_ERROR;
280        } break;
281        case IS_PLAYING: {
282            CHECK_INTERFACE(IMediaPlayer, data, reply);
283            bool state;
284            status_t ret = isPlaying(&state);
285            reply->writeInt32(state);
286            reply->writeInt32(ret);
287            return NO_ERROR;
288        } break;
289        case PAUSE: {
290            CHECK_INTERFACE(IMediaPlayer, data, reply);
291            reply->writeInt32(pause());
292            return NO_ERROR;
293        } break;
294        case SEEK_TO: {
295            CHECK_INTERFACE(IMediaPlayer, data, reply);
296            reply->writeInt32(seekTo(data.readInt32()));
297            return NO_ERROR;
298        } break;
299        case GET_CURRENT_POSITION: {
300            CHECK_INTERFACE(IMediaPlayer, data, reply);
301            int msec;
302            status_t ret = getCurrentPosition(&msec);
303            reply->writeInt32(msec);
304            reply->writeInt32(ret);
305            return NO_ERROR;
306        } break;
307        case GET_DURATION: {
308            CHECK_INTERFACE(IMediaPlayer, data, reply);
309            int msec;
310            status_t ret = getDuration(&msec);
311            reply->writeInt32(msec);
312            reply->writeInt32(ret);
313            return NO_ERROR;
314        } break;
315        case RESET: {
316            CHECK_INTERFACE(IMediaPlayer, data, reply);
317            reply->writeInt32(reset());
318            return NO_ERROR;
319        } break;
320        case SET_AUDIO_STREAM_TYPE: {
321            CHECK_INTERFACE(IMediaPlayer, data, reply);
322            reply->writeInt32(setAudioStreamType(data.readInt32()));
323            return NO_ERROR;
324        } break;
325        case SET_LOOPING: {
326            CHECK_INTERFACE(IMediaPlayer, data, reply);
327            reply->writeInt32(setLooping(data.readInt32()));
328            return NO_ERROR;
329        } break;
330        case SET_VOLUME: {
331            CHECK_INTERFACE(IMediaPlayer, data, reply);
332            reply->writeInt32(setVolume(data.readFloat(), data.readFloat()));
333            return NO_ERROR;
334        } break;
335        case INVOKE: {
336            CHECK_INTERFACE(IMediaPlayer, data, reply);
337            invoke(data, reply);
338            return NO_ERROR;
339        } break;
340        case SET_METADATA_FILTER: {
341            CHECK_INTERFACE(IMediaPlayer, data, reply);
342            reply->writeInt32(setMetadataFilter(data));
343            return NO_ERROR;
344        } break;
345        case GET_METADATA: {
346            CHECK_INTERFACE(IMediaPlayer, data, reply);
347            const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply);
348            reply->setDataPosition(0);
349            reply->writeInt32(retcode);
350            reply->setDataPosition(0);
351            return NO_ERROR;
352        } break;
353        case SET_AUX_EFFECT_SEND_LEVEL: {
354            CHECK_INTERFACE(IMediaPlayer, data, reply);
355            reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
356            return NO_ERROR;
357        } break;
358        case ATTACH_AUX_EFFECT: {
359            CHECK_INTERFACE(IMediaPlayer, data, reply);
360            reply->writeInt32(attachAuxEffect(data.readInt32()));
361            return NO_ERROR;
362        } break;
363        default:
364            return BBinder::onTransact(code, data, reply, flags);
365    }
366}
367
368// ----------------------------------------------------------------------------
369
370}; // namespace android
371