IMediaPlayer.cpp revision 2729ea9262ca60d93047e984739887cfc89e82eb
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 <utils/Parcel.h>
22
23#include <media/IMediaPlayer.h>
24#include <ui/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    GET_VIDEO_SIZE,
37    SEEK_TO,
38    GET_CURRENT_POSITION,
39    GET_DURATION,
40    RESET,
41    SET_AUDIO_STREAM_TYPE,
42    SET_LOOPING,
43    SET_VOLUME
44};
45
46class BpMediaPlayer: public BpInterface<IMediaPlayer>
47{
48public:
49    BpMediaPlayer(const sp<IBinder>& impl)
50        : BpInterface<IMediaPlayer>(impl)
51    {
52    }
53
54    // disconnect from media player service
55    void disconnect()
56    {
57        Parcel data, reply;
58        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
59        remote()->transact(DISCONNECT, data, &reply);
60    }
61
62    status_t setVideoSurface(const sp<ISurface>& surface)
63    {
64        Parcel data, reply;
65        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
66        data.writeStrongBinder(surface->asBinder());
67        remote()->transact(SET_VIDEO_SURFACE, data, &reply);
68        return reply.readInt32();
69    }
70
71    status_t prepareAsync()
72    {
73        Parcel data, reply;
74        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
75        remote()->transact(PREPARE_ASYNC, data, &reply);
76        return reply.readInt32();
77    }
78
79    status_t start()
80    {
81        Parcel data, reply;
82        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
83        remote()->transact(START, data, &reply);
84        return reply.readInt32();
85    }
86
87    status_t stop()
88    {
89        Parcel data, reply;
90        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
91        remote()->transact(STOP, data, &reply);
92        return reply.readInt32();
93    }
94
95    status_t isPlaying(bool* state)
96    {
97        Parcel data, reply;
98        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
99        remote()->transact(IS_PLAYING, data, &reply);
100        *state = reply.readInt32();
101        return reply.readInt32();
102    }
103
104    status_t pause()
105    {
106        Parcel data, reply;
107        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
108        remote()->transact(PAUSE, data, &reply);
109        return reply.readInt32();
110    }
111
112    status_t getVideoSize(int* w, int* h)
113    {
114        Parcel data, reply;
115        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
116        remote()->transact(GET_VIDEO_SIZE, data, &reply);
117        *w = reply.readInt32();
118        *h = reply.readInt32();
119        return reply.readInt32();
120    }
121
122    status_t seekTo(int msec)
123    {
124        Parcel data, reply;
125        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
126        data.writeInt32(msec);
127        remote()->transact(SEEK_TO, data, &reply);
128        return reply.readInt32();
129    }
130
131    status_t getCurrentPosition(int* msec)
132    {
133        Parcel data, reply;
134        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
135        remote()->transact(GET_CURRENT_POSITION, data, &reply);
136        *msec = reply.readInt32();
137        return reply.readInt32();
138    }
139
140    status_t getDuration(int* msec)
141    {
142        Parcel data, reply;
143        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
144        remote()->transact(GET_DURATION, data, &reply);
145        *msec = reply.readInt32();
146        return reply.readInt32();
147    }
148
149    status_t reset()
150    {
151        Parcel data, reply;
152        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
153        remote()->transact(RESET, data, &reply);
154        return reply.readInt32();
155    }
156
157    status_t setAudioStreamType(int type)
158    {
159        Parcel data, reply;
160        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
161        data.writeInt32(type);
162        remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
163        return reply.readInt32();
164    }
165
166    status_t setLooping(int loop)
167    {
168        Parcel data, reply;
169        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
170        data.writeInt32(loop);
171        remote()->transact(SET_LOOPING, data, &reply);
172        return reply.readInt32();
173    }
174
175    status_t setVolume(float leftVolume, float rightVolume)
176    {
177        Parcel data, reply;
178        data.writeFloat(leftVolume);
179        data.writeFloat(rightVolume);
180        remote()->transact(SET_VOLUME, data, &reply);
181        return reply.readInt32();
182    }
183};
184
185IMPLEMENT_META_INTERFACE(MediaPlayer, "android.hardware.IMediaPlayer");
186
187// ----------------------------------------------------------------------
188
189#define CHECK_INTERFACE(interface, data, reply) \
190        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
191            LOGW("Call incorrectly routed to " #interface); \
192            return PERMISSION_DENIED; \
193        } } while (0)
194
195status_t BnMediaPlayer::onTransact(
196    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
197{
198    switch(code) {
199        case DISCONNECT: {
200            CHECK_INTERFACE(IMediaPlayer, data, reply);
201            disconnect();
202            return NO_ERROR;
203        } break;
204        case SET_VIDEO_SURFACE: {
205            CHECK_INTERFACE(IMediaPlayer, data, reply);
206            sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
207            reply->writeInt32(setVideoSurface(surface));
208            return NO_ERROR;
209        } break;
210        case PREPARE_ASYNC: {
211            CHECK_INTERFACE(IMediaPlayer, data, reply);
212            reply->writeInt32(prepareAsync());
213            return NO_ERROR;
214        } break;
215        case START: {
216            CHECK_INTERFACE(IMediaPlayer, data, reply);
217            reply->writeInt32(start());
218            return NO_ERROR;
219        } break;
220        case STOP: {
221            CHECK_INTERFACE(IMediaPlayer, data, reply);
222            reply->writeInt32(stop());
223            return NO_ERROR;
224        } break;
225        case IS_PLAYING: {
226            CHECK_INTERFACE(IMediaPlayer, data, reply);
227            bool state;
228            status_t ret = isPlaying(&state);
229            reply->writeInt32(state);
230            reply->writeInt32(ret);
231            return NO_ERROR;
232        } break;
233        case PAUSE: {
234            CHECK_INTERFACE(IMediaPlayer, data, reply);
235            reply->writeInt32(pause());
236            return NO_ERROR;
237        } break;
238        case GET_VIDEO_SIZE: {
239            CHECK_INTERFACE(IMediaPlayer, data, reply);
240            int w, h;
241            status_t ret = getVideoSize(&w, &h);
242            reply->writeInt32(w);
243            reply->writeInt32(h);
244            reply->writeInt32(ret);
245            return NO_ERROR;
246        } break;
247        case SEEK_TO: {
248            CHECK_INTERFACE(IMediaPlayer, data, reply);
249            reply->writeInt32(seekTo(data.readInt32()));
250            return NO_ERROR;
251        } break;
252        case GET_CURRENT_POSITION: {
253            CHECK_INTERFACE(IMediaPlayer, data, reply);
254            int msec;
255            status_t ret = getCurrentPosition(&msec);
256            reply->writeInt32(msec);
257            reply->writeInt32(ret);
258            return NO_ERROR;
259        } break;
260        case GET_DURATION: {
261            CHECK_INTERFACE(IMediaPlayer, data, reply);
262            int msec;
263            status_t ret = getDuration(&msec);
264            reply->writeInt32(msec);
265            reply->writeInt32(ret);
266            return NO_ERROR;
267        } break;
268        case RESET: {
269            CHECK_INTERFACE(IMediaPlayer, data, reply);
270            reply->writeInt32(reset());
271            return NO_ERROR;
272        } break;
273        case SET_AUDIO_STREAM_TYPE: {
274            CHECK_INTERFACE(IMediaPlayer, data, reply);
275            reply->writeInt32(setAudioStreamType(data.readInt32()));
276            return NO_ERROR;
277        } break;
278        case SET_LOOPING: {
279            CHECK_INTERFACE(IMediaPlayer, data, reply);
280            reply->writeInt32(setLooping(data.readInt32()));
281            return NO_ERROR;
282        } break;
283        case SET_VOLUME: {
284            reply->writeInt32(setVolume(data.readFloat(), data.readFloat()));
285            return NO_ERROR;
286        } break;
287        default:
288            return BBinder::onTransact(code, data, reply, flags);
289    }
290}
291
292// ----------------------------------------------------------------------------
293
294}; // namespace android
295
296