1/*
2**
3** Copyright 2007, 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#define LOG_TAG "IAudioTrack"
19//#define LOG_NDEBUG 0
20#include <utils/Log.h>
21
22#include <stdint.h>
23#include <sys/types.h>
24
25#include <binder/Parcel.h>
26
27#include <media/IAudioTrack.h>
28
29namespace android {
30
31enum {
32    GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
33    START,
34    STOP,
35    FLUSH,
36    MUTE,
37    PAUSE,
38    ATTACH_AUX_EFFECT,
39    ALLOCATE_TIMED_BUFFER,
40    QUEUE_TIMED_BUFFER,
41    SET_MEDIA_TIME_TRANSFORM,
42};
43
44class BpAudioTrack : public BpInterface<IAudioTrack>
45{
46public:
47    BpAudioTrack(const sp<IBinder>& impl)
48        : BpInterface<IAudioTrack>(impl)
49    {
50    }
51
52    virtual sp<IMemory> getCblk() const
53    {
54        Parcel data, reply;
55        sp<IMemory> cblk;
56        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
57        status_t status = remote()->transact(GET_CBLK, data, &reply);
58        if (status == NO_ERROR) {
59            cblk = interface_cast<IMemory>(reply.readStrongBinder());
60        }
61        return cblk;
62    }
63
64    virtual status_t start()
65    {
66        Parcel data, reply;
67        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
68        status_t status = remote()->transact(START, data, &reply);
69        if (status == NO_ERROR) {
70            status = reply.readInt32();
71        } else {
72            ALOGW("start() error: %s", strerror(-status));
73        }
74        return status;
75    }
76
77    virtual void stop()
78    {
79        Parcel data, reply;
80        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
81        remote()->transact(STOP, data, &reply);
82    }
83
84    virtual void flush()
85    {
86        Parcel data, reply;
87        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
88        remote()->transact(FLUSH, data, &reply);
89    }
90
91    virtual void mute(bool e)
92    {
93        Parcel data, reply;
94        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
95        data.writeInt32(e);
96        remote()->transact(MUTE, data, &reply);
97    }
98
99    virtual void pause()
100    {
101        Parcel data, reply;
102        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
103        remote()->transact(PAUSE, data, &reply);
104    }
105
106    virtual status_t attachAuxEffect(int effectId)
107    {
108        Parcel data, reply;
109        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
110        data.writeInt32(effectId);
111        status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
112        if (status == NO_ERROR) {
113            status = reply.readInt32();
114        } else {
115            ALOGW("attachAuxEffect() error: %s", strerror(-status));
116        }
117        return status;
118    }
119
120    virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) {
121        Parcel data, reply;
122        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
123        data.writeInt32(size);
124        status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER,
125                                             data, &reply);
126        if (status == NO_ERROR) {
127            status = reply.readInt32();
128            if (status == NO_ERROR) {
129                *buffer = interface_cast<IMemory>(reply.readStrongBinder());
130            }
131        }
132        return status;
133    }
134
135    virtual status_t queueTimedBuffer(const sp<IMemory>& buffer,
136                                      int64_t pts) {
137        Parcel data, reply;
138        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
139        data.writeStrongBinder(buffer->asBinder());
140        data.writeInt64(pts);
141        status_t status = remote()->transact(QUEUE_TIMED_BUFFER,
142                                             data, &reply);
143        if (status == NO_ERROR) {
144            status = reply.readInt32();
145        }
146        return status;
147    }
148
149    virtual status_t setMediaTimeTransform(const LinearTransform& xform,
150                                           int target) {
151        Parcel data, reply;
152        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
153        data.writeInt64(xform.a_zero);
154        data.writeInt64(xform.b_zero);
155        data.writeInt32(xform.a_to_b_numer);
156        data.writeInt32(xform.a_to_b_denom);
157        data.writeInt32(target);
158        status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM,
159                                             data, &reply);
160        if (status == NO_ERROR) {
161            status = reply.readInt32();
162        }
163        return status;
164    }
165};
166
167IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
168
169// ----------------------------------------------------------------------
170
171status_t BnAudioTrack::onTransact(
172    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
173{
174    switch (code) {
175        case GET_CBLK: {
176            CHECK_INTERFACE(IAudioTrack, data, reply);
177            reply->writeStrongBinder(getCblk()->asBinder());
178            return NO_ERROR;
179        } break;
180        case START: {
181            CHECK_INTERFACE(IAudioTrack, data, reply);
182            reply->writeInt32(start());
183            return NO_ERROR;
184        } break;
185        case STOP: {
186            CHECK_INTERFACE(IAudioTrack, data, reply);
187            stop();
188            return NO_ERROR;
189        } break;
190        case FLUSH: {
191            CHECK_INTERFACE(IAudioTrack, data, reply);
192            flush();
193            return NO_ERROR;
194        } break;
195        case MUTE: {
196            CHECK_INTERFACE(IAudioTrack, data, reply);
197            mute( data.readInt32() );
198            return NO_ERROR;
199        } break;
200        case PAUSE: {
201            CHECK_INTERFACE(IAudioTrack, data, reply);
202            pause();
203            return NO_ERROR;
204        }
205        case ATTACH_AUX_EFFECT: {
206            CHECK_INTERFACE(IAudioTrack, data, reply);
207            reply->writeInt32(attachAuxEffect(data.readInt32()));
208            return NO_ERROR;
209        } break;
210        case ALLOCATE_TIMED_BUFFER: {
211            CHECK_INTERFACE(IAudioTrack, data, reply);
212            sp<IMemory> buffer;
213            status_t status = allocateTimedBuffer(data.readInt32(), &buffer);
214            reply->writeInt32(status);
215            if (status == NO_ERROR) {
216                reply->writeStrongBinder(buffer->asBinder());
217            }
218            return NO_ERROR;
219        } break;
220        case QUEUE_TIMED_BUFFER: {
221            CHECK_INTERFACE(IAudioTrack, data, reply);
222            sp<IMemory> buffer = interface_cast<IMemory>(
223                data.readStrongBinder());
224            uint64_t pts = data.readInt64();
225            reply->writeInt32(queueTimedBuffer(buffer, pts));
226            return NO_ERROR;
227        } break;
228        case SET_MEDIA_TIME_TRANSFORM: {
229            CHECK_INTERFACE(IAudioTrack, data, reply);
230            LinearTransform xform;
231            xform.a_zero = data.readInt64();
232            xform.b_zero = data.readInt64();
233            xform.a_to_b_numer = data.readInt32();
234            xform.a_to_b_denom = data.readInt32();
235            int target = data.readInt32();
236            reply->writeInt32(setMediaTimeTransform(xform, target));
237            return NO_ERROR;
238        } break;
239        default:
240            return BBinder::onTransact(code, data, reply, flags);
241    }
242}
243
244}; // namespace android
245