blob: 0ea9b07353fbc8e3e4f9646c2149ef50e2d13be9 [file] [log] [blame]
/*
* Copyright 2008, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// must include config.h first for webkit to fiddle with new/delete
#include "config.h"
#include "android_npapi.h"
#include "SkTypes.h"
#include "media/AudioTrack.h"
#include <system/audio.h>
struct ANPAudioTrack {
void* mUser;
ANPAudioCallbackProc mProc;
android::AudioTrack* mTrack;
int mChannelCount;
};
static ANPSampleFormat toANPFormat(audio_format_t fm) {
switch (fm) {
case AUDIO_FORMAT_PCM_16_BIT:
return kPCM16Bit_ANPSampleFormat;
case AUDIO_FORMAT_PCM_8_BIT:
return kPCM8Bit_ANPSampleFormat;
default:
return kUnknown_ANPSamleFormat;
}
}
static audio_format_t fromANPFormat(ANPSampleFormat fm) {
switch (fm) {
case kPCM16Bit_ANPSampleFormat:
return AUDIO_FORMAT_PCM_16_BIT;
case kPCM8Bit_ANPSampleFormat:
return AUDIO_FORMAT_PCM_8_BIT;
default:
return AUDIO_FORMAT_INVALID;
}
}
static void callbackProc(int event, void* user, void* info) {
ANPAudioTrack* track = reinterpret_cast<ANPAudioTrack*>(user);
switch (event) {
case android::AudioTrack::EVENT_MORE_DATA: {
ANPAudioBuffer dst;
android::AudioTrack::Buffer* src;
src = reinterpret_cast<android::AudioTrack::Buffer*>(info);
dst.bufferData = src->raw;
dst.channelCount = track->mChannelCount;
dst.format = toANPFormat(AUDIO_FORMAT_PCM_16_BIT);
dst.size = src->size;
track->mProc(kMoreData_ANPAudioEvent, track->mUser, &dst);
// return the updated size field
src->size = dst.size;
break;
}
case android::AudioTrack::EVENT_UNDERRUN:
track->mProc(kUnderRun_ANPAudioEvent, track->mUser, NULL);
break;
default:
SkDebugf("------ unknown audio event for plugin %d\n", event);
break;
}
}
static ANPAudioTrack* ANPCreateTrack(uint32_t sampleRate,
ANPSampleFormat format,
int channelCount,
ANPAudioCallbackProc proc,
void* user) {
ANPAudioTrack* track = new ANPAudioTrack;
track->mUser = user;
track->mProc = proc;
track->mTrack = new android::AudioTrack(AUDIO_STREAM_MUSIC,
sampleRate,
fromANPFormat(format),
audio_channel_out_mask_from_count(channelCount),
0, // frameCount
(audio_output_flags_t) 0, // AUDIO_OUTPUT_FLAG_NONE,
callbackProc,
track,
0);
track->mChannelCount = channelCount;
if (track->mTrack->initCheck() != 0) { // failure
delete track->mTrack;
delete track;
track = NULL;
}
return track;
}
static void ANPDeleteTrack(ANPAudioTrack* track) {
if (track) {
delete track->mTrack;
delete track;
}
}
static void ANPTrackStart(ANPAudioTrack* track) {
track->mTrack->start();
}
static void ANPTrackPause(ANPAudioTrack* track) {
track->mTrack->pause();
}
static void ANPTrackStop(ANPAudioTrack* track) {
track->mTrack->stop();
}
static bool ANPTrackIsStopped(ANPAudioTrack* track) {
return track->mTrack->stopped();
}
static uint32_t ANPTrackLatency(ANPAudioTrack* track) {
return track->mTrack->latency();
}
///////////////////////////////////////////////////////////////////////////////
void ANPAudioTrackInterfaceV0_Init(ANPInterface* value) {
ANPAudioTrackInterfaceV0* si = reinterpret_cast<ANPAudioTrackInterfaceV0*>(value);
si->newTrack = ANPCreateTrack;
si->deleteTrack = ANPDeleteTrack;
si->start = ANPTrackStart;
si->pause = ANPTrackPause;
si->stop = ANPTrackStop;
si->isStopped = ANPTrackIsStopped;
}
void ANPAudioTrackInterfaceV1_Init(ANPInterface* value) {
// initialize the functions from the previous interface
ANPAudioTrackInterfaceV0_Init(value);
// add any new functions or override existing functions
ANPAudioTrackInterfaceV1* si = reinterpret_cast<ANPAudioTrackInterfaceV1*>(value);
si->trackLatency = ANPTrackLatency;
}