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