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     RESERVED, // was MUTE
     37     PAUSE,
     38     ATTACH_AUX_EFFECT,
     39     ALLOCATE_TIMED_BUFFER,
     40     QUEUE_TIMED_BUFFER,
     41     SET_MEDIA_TIME_TRANSFORM,
     42     SET_PARAMETERS,
     43     GET_TIMESTAMP,
     44     SIGNAL,
     45 };
     46 
     47 class BpAudioTrack : public BpInterface<IAudioTrack>
     48 {
     49 public:
     50     BpAudioTrack(const sp<IBinder>& impl)
     51         : BpInterface<IAudioTrack>(impl)
     52     {
     53     }
     54 
     55     virtual sp<IMemory> getCblk() const
     56     {
     57         Parcel data, reply;
     58         sp<IMemory> cblk;
     59         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
     60         status_t status = remote()->transact(GET_CBLK, data, &reply);
     61         if (status == NO_ERROR) {
     62             cblk = interface_cast<IMemory>(reply.readStrongBinder());
     63         }
     64         return cblk;
     65     }
     66 
     67     virtual status_t start()
     68     {
     69         Parcel data, reply;
     70         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
     71         status_t status = remote()->transact(START, data, &reply);
     72         if (status == NO_ERROR) {
     73             status = reply.readInt32();
     74         } else {
     75             ALOGW("start() error: %s", strerror(-status));
     76         }
     77         return status;
     78     }
     79 
     80     virtual void stop()
     81     {
     82         Parcel data, reply;
     83         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
     84         remote()->transact(STOP, data, &reply);
     85     }
     86 
     87     virtual void flush()
     88     {
     89         Parcel data, reply;
     90         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
     91         remote()->transact(FLUSH, data, &reply);
     92     }
     93 
     94     virtual void pause()
     95     {
     96         Parcel data, reply;
     97         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
     98         remote()->transact(PAUSE, data, &reply);
     99     }
    100 
    101     virtual status_t attachAuxEffect(int effectId)
    102     {
    103         Parcel data, reply;
    104         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    105         data.writeInt32(effectId);
    106         status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
    107         if (status == NO_ERROR) {
    108             status = reply.readInt32();
    109         } else {
    110             ALOGW("attachAuxEffect() error: %s", strerror(-status));
    111         }
    112         return status;
    113     }
    114 
    115     virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) {
    116         Parcel data, reply;
    117         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    118         data.writeInt32(size);
    119         status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER,
    120                                              data, &reply);
    121         if (status == NO_ERROR) {
    122             status = reply.readInt32();
    123             if (status == NO_ERROR) {
    124                 *buffer = interface_cast<IMemory>(reply.readStrongBinder());
    125             }
    126         }
    127         return status;
    128     }
    129 
    130     virtual status_t queueTimedBuffer(const sp<IMemory>& buffer,
    131                                       int64_t pts) {
    132         Parcel data, reply;
    133         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    134         data.writeStrongBinder(buffer->asBinder());
    135         data.writeInt64(pts);
    136         status_t status = remote()->transact(QUEUE_TIMED_BUFFER,
    137                                              data, &reply);
    138         if (status == NO_ERROR) {
    139             status = reply.readInt32();
    140         }
    141         return status;
    142     }
    143 
    144     virtual status_t setMediaTimeTransform(const LinearTransform& xform,
    145                                            int target) {
    146         Parcel data, reply;
    147         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    148         data.writeInt64(xform.a_zero);
    149         data.writeInt64(xform.b_zero);
    150         data.writeInt32(xform.a_to_b_numer);
    151         data.writeInt32(xform.a_to_b_denom);
    152         data.writeInt32(target);
    153         status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM,
    154                                              data, &reply);
    155         if (status == NO_ERROR) {
    156             status = reply.readInt32();
    157         }
    158         return status;
    159     }
    160 
    161     virtual status_t setParameters(const String8& keyValuePairs) {
    162         Parcel data, reply;
    163         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    164         data.writeString8(keyValuePairs);
    165         status_t status = remote()->transact(SET_PARAMETERS, data, &reply);
    166         if (status == NO_ERROR) {
    167             status = reply.readInt32();
    168         }
    169         return status;
    170     }
    171 
    172     virtual status_t getTimestamp(AudioTimestamp& timestamp) {
    173         Parcel data, reply;
    174         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    175         status_t status = remote()->transact(GET_TIMESTAMP, data, &reply);
    176         if (status == NO_ERROR) {
    177             status = reply.readInt32();
    178             if (status == NO_ERROR) {
    179                 timestamp.mPosition = reply.readInt32();
    180                 timestamp.mTime.tv_sec = reply.readInt32();
    181                 timestamp.mTime.tv_nsec = reply.readInt32();
    182             }
    183         }
    184         return status;
    185     }
    186 
    187     virtual void signal() {
    188         Parcel data, reply;
    189         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
    190         remote()->transact(SIGNAL, data, &reply);
    191     }
    192 };
    193 
    194 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
    195 
    196 // ----------------------------------------------------------------------
    197 
    198 status_t BnAudioTrack::onTransact(
    199     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    200 {
    201     switch (code) {
    202         case GET_CBLK: {
    203             CHECK_INTERFACE(IAudioTrack, data, reply);
    204             reply->writeStrongBinder(getCblk()->asBinder());
    205             return NO_ERROR;
    206         } break;
    207         case START: {
    208             CHECK_INTERFACE(IAudioTrack, data, reply);
    209             reply->writeInt32(start());
    210             return NO_ERROR;
    211         } break;
    212         case STOP: {
    213             CHECK_INTERFACE(IAudioTrack, data, reply);
    214             stop();
    215             return NO_ERROR;
    216         } break;
    217         case FLUSH: {
    218             CHECK_INTERFACE(IAudioTrack, data, reply);
    219             flush();
    220             return NO_ERROR;
    221         } break;
    222         case PAUSE: {
    223             CHECK_INTERFACE(IAudioTrack, data, reply);
    224             pause();
    225             return NO_ERROR;
    226         }
    227         case ATTACH_AUX_EFFECT: {
    228             CHECK_INTERFACE(IAudioTrack, data, reply);
    229             reply->writeInt32(attachAuxEffect(data.readInt32()));
    230             return NO_ERROR;
    231         } break;
    232         case ALLOCATE_TIMED_BUFFER: {
    233             CHECK_INTERFACE(IAudioTrack, data, reply);
    234             sp<IMemory> buffer;
    235             status_t status = allocateTimedBuffer(data.readInt32(), &buffer);
    236             reply->writeInt32(status);
    237             if (status == NO_ERROR) {
    238                 reply->writeStrongBinder(buffer->asBinder());
    239             }
    240             return NO_ERROR;
    241         } break;
    242         case QUEUE_TIMED_BUFFER: {
    243             CHECK_INTERFACE(IAudioTrack, data, reply);
    244             sp<IMemory> buffer = interface_cast<IMemory>(
    245                 data.readStrongBinder());
    246             uint64_t pts = data.readInt64();
    247             reply->writeInt32(queueTimedBuffer(buffer, pts));
    248             return NO_ERROR;
    249         } break;
    250         case SET_MEDIA_TIME_TRANSFORM: {
    251             CHECK_INTERFACE(IAudioTrack, data, reply);
    252             LinearTransform xform;
    253             xform.a_zero = data.readInt64();
    254             xform.b_zero = data.readInt64();
    255             xform.a_to_b_numer = data.readInt32();
    256             xform.a_to_b_denom = data.readInt32();
    257             int target = data.readInt32();
    258             reply->writeInt32(setMediaTimeTransform(xform, target));
    259             return NO_ERROR;
    260         } break;
    261         case SET_PARAMETERS: {
    262             CHECK_INTERFACE(IAudioTrack, data, reply);
    263             String8 keyValuePairs(data.readString8());
    264             reply->writeInt32(setParameters(keyValuePairs));
    265             return NO_ERROR;
    266         } break;
    267         case GET_TIMESTAMP: {
    268             CHECK_INTERFACE(IAudioTrack, data, reply);
    269             AudioTimestamp timestamp;
    270             status_t status = getTimestamp(timestamp);
    271             reply->writeInt32(status);
    272             if (status == NO_ERROR) {
    273                 reply->writeInt32(timestamp.mPosition);
    274                 reply->writeInt32(timestamp.mTime.tv_sec);
    275                 reply->writeInt32(timestamp.mTime.tv_nsec);
    276             }
    277             return NO_ERROR;
    278         } break;
    279         case SIGNAL: {
    280             CHECK_INTERFACE(IAudioTrack, data, reply);
    281             signal();
    282             return NO_ERROR;
    283         } break;
    284         default:
    285             return BBinder::onTransact(code, data, reply, flags);
    286     }
    287 }
    288 
    289 }; // namespace android
    290