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 "AudioContext.h" 306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "ArrayBuffer.h" 322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "AudioBuffer.h" 332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "JSArrayBuffer.h" 342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "JSAudioBuffer.h" 356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "JSAudioContext.h" 366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include <runtime/Error.h> 376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 382fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockusing namespace JSC; 392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennernamespace WebCore { 416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 422fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockEncodedJSValue JSC_HOST_CALL JSAudioContextConstructor::constructJSAudioContext(ExecState* exec) 436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{ 446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner JSAudioContextConstructor* jsConstructor = static_cast<JSAudioContextConstructor*>(exec->callee()); 456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (!jsConstructor) 466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return throwError(exec, createReferenceError(exec, "AudioContext constructor callee is unavailable")); 476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext(); 496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (!scriptExecutionContext) 506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return throwError(exec, createReferenceError(exec, "AudioContext constructor script execution context is unavailable")); 516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (!scriptExecutionContext->isDocument()) 536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return throwError(exec, createReferenceError(exec, "AudioContext constructor called in a script execution context which is not a document")); 546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Document* document = static_cast<Document*>(scriptExecutionContext); 566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch RefPtr<AudioContext> audioContext; 582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!exec->argumentCount()) { 602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Constructor for default AudioContext which talks to audio hardware. 612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch audioContext = AudioContext::create(document); 622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } else { 632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer. 642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate); 652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (exec->argumentCount() < 3) 662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return throwError(exec, createSyntaxError(exec, "Not enough arguments")); 672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch unsigned numberOfChannels = exec->argument(0).toInt32(exec); 692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch unsigned numberOfFrames = exec->argument(1).toInt32(exec); 702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch float sampleRate = exec->argument(2).toFloat(exec); 712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate); 732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!audioContext.get()) 762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return throwError(exec, createReferenceError(exec, "Error creating AudioContext")); 772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), audioContext.get()))); 792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 812fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockJSValue JSAudioContext::createBuffer(ExecState* exec) 822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (exec->argumentCount() < 2) 842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return throwError(exec, createSyntaxError(exec, "Not enough arguments")); 852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block AudioContext* audioContext = static_cast<AudioContext*>(impl()); 872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(audioContext); 882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // AudioBuffer createBuffer(in ArrayBuffer buffer, in boolean mixToMono); 902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSValue val = exec->argument(0); 912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (val.inherits(&JSArrayBuffer::s_info)) { 922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ArrayBuffer* arrayBuffer = toArrayBuffer(val); 932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(arrayBuffer); 942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (arrayBuffer) { 952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block bool mixToMono = exec->argument(1).toBoolean(exec); 962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block RefPtr<AudioBuffer> audioBuffer = audioContext->createBuffer(arrayBuffer, mixToMono); 982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!audioBuffer.get()) 992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return throwError(exec, createSyntaxError(exec, "Error decoding audio file data")); 1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return toJS(exec, globalObject(), audioBuffer.get()); 1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return jsUndefined(); 1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // AudioBuffer createBuffer(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate); 1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (exec->argumentCount() < 3) 1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return throwError(exec, createSyntaxError(exec, "Not enough arguments")); 1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block unsigned numberOfChannels = exec->argument(0).toInt32(exec); 1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block unsigned numberOfFrames = exec->argument(1).toInt32(exec); 1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float sampleRate = exec->argument(2).toFloat(exec); 1142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block RefPtr<AudioBuffer> audioBuffer = audioContext->createBuffer(numberOfChannels, numberOfFrames, sampleRate); 1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!audioBuffer.get()) 1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return throwError(exec, createSyntaxError(exec, "Error creating AudioBuffer")); 1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return toJS(exec, globalObject(), audioBuffer.get()); 1206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} 1216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} // namespace WebCore 1236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif // ENABLE(WEB_AUDIO) 125