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