16b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner/*
26b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * Copyright (C) 2010, Google Inc. All rights reserved.
36b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
46b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * Redistribution and use in source and binary forms, with or without
56b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * modification, are permitted provided that the following conditions
66b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * are met:
76b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * 1.  Redistributions of source code must retain the above copyright
86b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *    notice, this list of conditions and the following disclaimer.
96b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * 2.  Redistributions in binary form must reproduce the above copyright
106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *    notice, this list of conditions and the following disclaimer in the
116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *    documentation and/or other materials provided with the distribution.
126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner */
246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "config.h"
266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#if ENABLE(WEB_AUDIO)
286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "V8AudioContext.h"
306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "ArrayBuffer.h"
322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "AudioBuffer.h"
336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioContext.h"
346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "Frame.h"
352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "V8ArrayBuffer.h"
362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "V8AudioBuffer.h"
372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "V8Binding.h"
386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "V8Proxy.h"
396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennernamespace WebCore {
416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerv8::Handle<v8::Value> V8AudioContext::constructorCallback(const v8::Arguments& args)
436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    INC_STATS("DOM.AudioContext.Contructor");
456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!frame)
486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return throwError("AudioContext constructor associated frame is unavailable", V8Proxy::ReferenceError);
496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Document* document = frame->document();
516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!document)
526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return throwError("AudioContext constructor associated document is unavailable", V8Proxy::ReferenceError);
536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<AudioContext> audioContext;
552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!args.Length()) {
572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Constructor for default AudioContext which talks to audio hardware.
582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        audioContext = AudioContext::create(document);
592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer.
612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (args.Length() < 3)
632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return throwError("Not enough arguments", V8Proxy::SyntaxError);
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool ok = false;
662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned numberOfChannels = toInt32(args[0], ok);
682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!ok)
692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return throwError("Invalid number of channels", V8Proxy::SyntaxError);
702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned numberOfFrames = toInt32(args[1], ok);
722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!ok)
732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return throwError("Invalid number of frames", V8Proxy::SyntaxError);
742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        float sampleRate = toFloat(args[2]);
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate);
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!audioContext.get())
812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return throwError("Error creating AudioContext", V8Proxy::SyntaxError);
826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Transform the holder into a wrapper object for the audio context.
846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    V8DOMWrapper::setDOMWrapper(args.Holder(), &info, audioContext.get());
856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    audioContext->ref();
866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return args.Holder();
886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
902fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockv8::Handle<v8::Value> V8AudioContext::createBufferCallback(const v8::Arguments& args)
912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (args.Length() < 2)
932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return throwError("Not enough arguments", V8Proxy::SyntaxError);
942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    AudioContext* audioContext = toNative(args.Holder());
962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(audioContext);
972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    v8::Handle<v8::Value> arg = args[0];
992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // AudioBuffer createBuffer(in ArrayBuffer buffer, in boolean mixToMono);
1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (V8ArrayBuffer::HasInstance(arg)) {
1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(object);
1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ASSERT(arrayBuffer);
1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (arrayBuffer) {
1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            bool mixToMono = args[1]->ToBoolean()->Value();
1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            RefPtr<AudioBuffer> audioBuffer = audioContext->createBuffer(arrayBuffer, mixToMono);
1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (!audioBuffer.get())
1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                return throwError("Error decoding audio file data", V8Proxy::SyntaxError);
1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return toV8(audioBuffer.get());
1142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return v8::Undefined();
1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // AudioBuffer createBuffer(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (args.Length() < 3)
1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return throwError("Not enough arguments", V8Proxy::SyntaxError);
1222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    bool ok = false;
1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unsigned numberOfChannels = toInt32(args[0], ok);
1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!ok)
1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return throwError("Invalid number of channels", V8Proxy::SyntaxError);
1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unsigned numberOfFrames = toInt32(args[1], ok);
1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!ok)
1312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return throwError("Invalid number of frames", V8Proxy::SyntaxError);
1322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float sampleRate = toFloat(args[2]);
1342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RefPtr<AudioBuffer> audioBuffer = audioContext->createBuffer(numberOfChannels, numberOfFrames, sampleRate);
1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!audioBuffer.get())
1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return throwError("Error creating AudioBuffer", V8Proxy::SyntaxError);
1382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return toV8(audioBuffer.get());
1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} // namespace WebCore
1436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif // ENABLE(WEB_AUDIO)
145