Home | History | Annotate | Download | only in libmedia
      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 
     29 namespace android {
     30 
     31 enum {
     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 
     44 class BpAudioTrack : public BpInterface<IAudioTrack>
     45 {
     46 public:
     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 
    167 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
    168 
    169 // ----------------------------------------------------------------------
    170 
    171 status_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