18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright 2008, The Android Open Source Project
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
163298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// must include config.h first for webkit to fiddle with new/delete
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "android_npapi.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
30a47ab5294213cca2741f453b450b02666e08cac8Patrick Scott#include "SkTypes.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "media/AudioTrack.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3373721b27032fa99cefeffd85bc62787f8895636aDima Zavin#include <system/audio.h>
34ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct ANPAudioTrack {
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void*                mUser;
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ANPAudioCallbackProc mProc;
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    android::AudioTrack* mTrack;
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
41aec70f340dd665e5c3bf3ef7aed3bae2fe55996dGlenn Kastenstatic ANPSampleFormat toANPFormat(audio_format_t fm) {
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (fm) {
43ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin        case AUDIO_FORMAT_PCM_16_BIT:
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return kPCM16Bit_ANPSampleFormat;
45ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin        case AUDIO_FORMAT_PCM_8_BIT:
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return kPCM8Bit_ANPSampleFormat;
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        default:
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return kUnknown_ANPSamleFormat;
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
52aec70f340dd665e5c3bf3ef7aed3bae2fe55996dGlenn Kastenstatic audio_format_t fromANPFormat(ANPSampleFormat fm) {
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (fm) {
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case kPCM16Bit_ANPSampleFormat:
55ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin            return AUDIO_FORMAT_PCM_16_BIT;
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case kPCM8Bit_ANPSampleFormat:
57ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin            return AUDIO_FORMAT_PCM_8_BIT;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        default:
59ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin            return AUDIO_FORMAT_INVALID;
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
63131e4ececc5afb847b251dc85fff81e1cb41a94aGlenn Kastenstatic void callbackProc(int event, void* user, void* info) {
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ANPAudioTrack* track = reinterpret_cast<ANPAudioTrack*>(user);
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (event) {
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case android::AudioTrack::EVENT_MORE_DATA: {
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ANPAudioBuffer dst;
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            android::AudioTrack::Buffer* src;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            src = reinterpret_cast<android::AudioTrack::Buffer*>(info);
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            dst.bufferData      = src->raw;
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            dst.channelCount    = src->channelCount;
745a2206b6d2861a63585471a526dda333f68d3ebcGlenn Kasten            dst.format          = toANPFormat((audio_format_t) src->format);
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            dst.size            = src->size;
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            track->mProc(kMoreData_ANPAudioEvent, track->mUser, &dst);
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // return the updated size field
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            src->size = dst.size;
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case android::AudioTrack::EVENT_UNDERRUN:
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            track->mProc(kUnderRun_ANPAudioEvent, track->mUser, NULL);
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        default:
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            SkDebugf("------ unknown audio event for plugin %d\n", event);
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic ANPAudioTrack* ANPCreateTrack(uint32_t sampleRate,
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                     ANPSampleFormat format,
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                     int channelCount,
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                     ANPAudioCallbackProc proc,
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                     void* user) {
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ANPAudioTrack* track = new ANPAudioTrack;
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    track->mUser = user;
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    track->mProc = proc;
100ae523aafcb7b5f04cd5ad61ab37e546ca7ca6df2Dima Zavin    track->mTrack = new android::AudioTrack(AUDIO_STREAM_MUSIC,
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                            sampleRate,
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                            fromANPFormat(format),
1034700ce519e61bebe0435ca117d2ea24d78eae63fGlenn Kasten                                            audio_channel_out_mask_from_count(channelCount),
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                            0,  // frameCount
105356edf790717717a9f3b88deb7b80941fb052923Eric Laurent                                            (audio_output_flags_t) 0, // AUDIO_OUTPUT_FLAG_NONE,
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                            callbackProc,
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                            track,
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                            0);
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (track->mTrack->initCheck() != 0) {  // failure
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete track->mTrack;
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete track;
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        track = NULL;
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return track;
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void ANPDeleteTrack(ANPAudioTrack* track) {
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (track) {
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete track->mTrack;
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete track;
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void ANPTrackStart(ANPAudioTrack* track) {
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    track->mTrack->start();
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void ANPTrackPause(ANPAudioTrack* track) {
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    track->mTrack->pause();
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void ANPTrackStop(ANPAudioTrack* track) {
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    track->mTrack->stop();
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool ANPTrackIsStopped(ANPAudioTrack* track) {
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return track->mTrack->stopped();
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14149bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenbergerstatic uint32_t ANPTrackLatency(ANPAudioTrack* track) {
14249bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger    return track->mTrack->latency();
14349bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger}
14449bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ANPAudioTrackInterfaceV0_Init(ANPInterface* value) {
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ANPAudioTrackInterfaceV0* si = reinterpret_cast<ANPAudioTrackInterfaceV0*>(value);
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    si->newTrack    = ANPCreateTrack;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    si->deleteTrack = ANPDeleteTrack;
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    si->start       = ANPTrackStart;
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    si->pause       = ANPTrackPause;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    si->stop        = ANPTrackStop;
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    si->isStopped   = ANPTrackIsStopped;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15649bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger
15749bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenbergervoid ANPAudioTrackInterfaceV1_Init(ANPInterface* value) {
15849bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger    // initialize the functions from the previous interface
15949bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger    ANPAudioTrackInterfaceV0_Init(value);
16049bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger    // add any new functions or override existing functions
16149bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger    ANPAudioTrackInterfaceV1* si = reinterpret_cast<ANPAudioTrackInterfaceV1*>(value);
16249bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger    si->trackLatency = ANPTrackLatency;
16349bf866973cb3b2a6c74c0eab864e9562e4cbab1Derek Sollenberger}
164