Move webaudio to Modules/webaudio/
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AsyncAudioDecoder.cpp
1 /*
2  * Copyright (C) 2011, Google Inc. All rights reserved.
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  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  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 APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #if ENABLE(WEB_AUDIO)
28
29 #include "AsyncAudioDecoder.h"
30
31 #include "AudioBuffer.h"
32 #include "AudioBufferCallback.h"
33 #include <wtf/ArrayBuffer.h>
34 #include <wtf/MainThread.h>
35 #include <wtf/OwnPtr.h>
36 #include <wtf/PassOwnPtr.h>
37
38 namespace WebCore {
39
40 AsyncAudioDecoder::AsyncAudioDecoder()
41 {
42     // Start worker thread.
43     MutexLocker lock(m_threadCreationMutex);
44     m_threadID = createThread(AsyncAudioDecoder::threadEntry, this, "Audio Decoder");
45 }
46
47 AsyncAudioDecoder::~AsyncAudioDecoder()
48 {
49     m_queue.kill();
50     
51     // Stop thread.
52     waitForThreadCompletion(m_threadID);
53     m_threadID = 0;
54 }
55
56 void AsyncAudioDecoder::decodeAsync(ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback)
57 {
58     ASSERT(isMainThread());
59     ASSERT(audioData);
60     if (!audioData)
61         return;
62
63     OwnPtr<DecodingTask> decodingTask = DecodingTask::create(audioData, sampleRate, successCallback, errorCallback);
64     m_queue.append(decodingTask.release()); // note that ownership of the task is effectively taken by the queue.
65 }
66
67 // Asynchronously decode in this thread.
68 void AsyncAudioDecoder::threadEntry(void* threadData)
69 {
70     ASSERT(threadData);
71     AsyncAudioDecoder* decoder = reinterpret_cast<AsyncAudioDecoder*>(threadData);
72     decoder->runLoop();
73 }
74
75 void AsyncAudioDecoder::runLoop()
76 {
77     ASSERT(!isMainThread());
78
79     {
80         // Wait for until we have m_threadID established before starting the run loop.
81         MutexLocker lock(m_threadCreationMutex);
82     }
83
84     // Keep running decoding tasks until we're killed.
85     while (OwnPtr<DecodingTask> decodingTask = m_queue.waitForMessage()) {
86         // Let the task take care of its own ownership.
87         // See DecodingTask::notifyComplete() for cleanup.
88         decodingTask.leakPtr()->decode();
89     }
90 }
91
92 PassOwnPtr<AsyncAudioDecoder::DecodingTask> AsyncAudioDecoder::DecodingTask::create(ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback)
93 {
94     return adoptPtr(new DecodingTask(audioData, sampleRate, successCallback, errorCallback));
95 }
96
97 AsyncAudioDecoder::DecodingTask::DecodingTask(ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback)
98     : m_audioData(audioData)
99     , m_sampleRate(sampleRate)
100     , m_successCallback(successCallback)
101     , m_errorCallback(errorCallback)
102 {
103 }
104
105 void AsyncAudioDecoder::DecodingTask::decode()
106 {
107     ASSERT(m_audioData.get());
108     if (!m_audioData.get())
109         return;
110
111     // Do the actual decoding and invoke the callback.
112     m_audioBuffer = AudioBuffer::createFromAudioFileData(m_audioData->data(), m_audioData->byteLength(), false, sampleRate());
113     
114     // Decoding is finished, but we need to do the callbacks on the main thread.
115     callOnMainThread(notifyCompleteDispatch, this);
116 }
117
118 void AsyncAudioDecoder::DecodingTask::notifyCompleteDispatch(void* userData)
119 {
120     AsyncAudioDecoder::DecodingTask* task = reinterpret_cast<AsyncAudioDecoder::DecodingTask*>(userData);
121     ASSERT(task);
122     if (!task)
123         return;
124
125     task->notifyComplete();
126 }
127
128 void AsyncAudioDecoder::DecodingTask::notifyComplete()
129 {
130     if (audioBuffer() && successCallback())
131         successCallback()->handleEvent(audioBuffer());
132     else if (errorCallback())
133         errorCallback()->handleEvent(audioBuffer());
134
135     // Our ownership was given up in AsyncAudioDecoder::runLoop()
136     // Make sure to clean up here.
137     delete this;
138 }
139
140 } // namespace WebCore
141
142 #endif // ENABLE(WEB_AUDIO)