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