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