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