1/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26// must include config.h first for webkit to fiddle with new/delete
27#include "config.h"
28#include "android_npapi.h"
29
30#include "SkTypes.h"
31#include "media/AudioTrack.h"
32
33#include <system/audio.h>
34
35struct ANPAudioTrack {
36    void*                mUser;
37    ANPAudioCallbackProc mProc;
38    android::AudioTrack* mTrack;
39};
40
41static ANPSampleFormat toANPFormat(audio_format_t fm) {
42    switch (fm) {
43        case AUDIO_FORMAT_PCM_16_BIT:
44            return kPCM16Bit_ANPSampleFormat;
45        case AUDIO_FORMAT_PCM_8_BIT:
46            return kPCM8Bit_ANPSampleFormat;
47        default:
48            return kUnknown_ANPSamleFormat;
49    }
50}
51
52static audio_format_t fromANPFormat(ANPSampleFormat fm) {
53    switch (fm) {
54        case kPCM16Bit_ANPSampleFormat:
55            return AUDIO_FORMAT_PCM_16_BIT;
56        case kPCM8Bit_ANPSampleFormat:
57            return AUDIO_FORMAT_PCM_8_BIT;
58        default:
59            return AUDIO_FORMAT_INVALID;
60    }
61}
62
63static void callbackProc(int event, void* user, void* info) {
64    ANPAudioTrack* track = reinterpret_cast<ANPAudioTrack*>(user);
65
66    switch (event) {
67        case android::AudioTrack::EVENT_MORE_DATA: {
68            ANPAudioBuffer dst;
69            android::AudioTrack::Buffer* src;
70
71            src = reinterpret_cast<android::AudioTrack::Buffer*>(info);
72            dst.bufferData      = src->raw;
73            dst.channelCount    = src->channelCount;
74            dst.format          = toANPFormat((audio_format_t) src->format);
75            dst.size            = src->size;
76            track->mProc(kMoreData_ANPAudioEvent, track->mUser, &dst);
77            // return the updated size field
78            src->size = dst.size;
79            break;
80        }
81        case android::AudioTrack::EVENT_UNDERRUN:
82            track->mProc(kUnderRun_ANPAudioEvent, track->mUser, NULL);
83            break;
84        default:
85            SkDebugf("------ unknown audio event for plugin %d\n", event);
86            break;
87    }
88}
89
90static ANPAudioTrack* ANPCreateTrack(uint32_t sampleRate,
91                                     ANPSampleFormat format,
92                                     int channelCount,
93                                     ANPAudioCallbackProc proc,
94                                     void* user) {
95
96    ANPAudioTrack* track = new ANPAudioTrack;
97
98    track->mUser = user;
99    track->mProc = proc;
100    track->mTrack = new android::AudioTrack(AUDIO_STREAM_MUSIC,
101                                            sampleRate,
102                                            fromANPFormat(format),
103                                            audio_channel_out_mask_from_count(channelCount),
104                                            0,  // frameCount
105                                            (audio_output_flags_t) 0, // AUDIO_OUTPUT_FLAG_NONE,
106                                            callbackProc,
107                                            track,
108                                            0);
109
110    if (track->mTrack->initCheck() != 0) {  // failure
111        delete track->mTrack;
112        delete track;
113        track = NULL;
114    }
115    return track;
116}
117
118static void ANPDeleteTrack(ANPAudioTrack* track) {
119    if (track) {
120        delete track->mTrack;
121        delete track;
122    }
123}
124
125static void ANPTrackStart(ANPAudioTrack* track) {
126    track->mTrack->start();
127}
128
129static void ANPTrackPause(ANPAudioTrack* track) {
130    track->mTrack->pause();
131}
132
133static void ANPTrackStop(ANPAudioTrack* track) {
134    track->mTrack->stop();
135}
136
137static bool ANPTrackIsStopped(ANPAudioTrack* track) {
138    return track->mTrack->stopped();
139}
140
141static uint32_t ANPTrackLatency(ANPAudioTrack* track) {
142    return track->mTrack->latency();
143}
144
145///////////////////////////////////////////////////////////////////////////////
146
147void ANPAudioTrackInterfaceV0_Init(ANPInterface* value) {
148    ANPAudioTrackInterfaceV0* si = reinterpret_cast<ANPAudioTrackInterfaceV0*>(value);
149    si->newTrack    = ANPCreateTrack;
150    si->deleteTrack = ANPDeleteTrack;
151    si->start       = ANPTrackStart;
152    si->pause       = ANPTrackPause;
153    si->stop        = ANPTrackStop;
154    si->isStopped   = ANPTrackIsStopped;
155}
156
157void ANPAudioTrackInterfaceV1_Init(ANPInterface* value) {
158    // initialize the functions from the previous interface
159    ANPAudioTrackInterfaceV0_Init(value);
160    // add any new functions or override existing functions
161    ANPAudioTrackInterfaceV1* si = reinterpret_cast<ANPAudioTrackInterfaceV1*>(value);
162    si->trackLatency = ANPTrackLatency;
163}
164