1 /* 2 * Copyright (C) 2012 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 * * 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 #include "config.h" 27 28 #include "modules/speech/SpeechRecognition.h" 29 30 #include "bindings/v8/ExceptionState.h" 31 #include "core/dom/Document.h" 32 #include "core/dom/ExceptionCode.h" 33 #include "core/page/Page.h" 34 #include "modules/speech/SpeechRecognitionController.h" 35 #include "modules/speech/SpeechRecognitionError.h" 36 #include "modules/speech/SpeechRecognitionEvent.h" 37 38 namespace WebCore { 39 40 PassRefPtr<SpeechRecognition> SpeechRecognition::create(ExecutionContext* context) 41 { 42 RefPtr<SpeechRecognition> speechRecognition(adoptRef(new SpeechRecognition(context))); 43 speechRecognition->suspendIfNeeded(); 44 return speechRecognition.release(); 45 } 46 47 void SpeechRecognition::start(ExceptionState& exceptionState) 48 { 49 ASSERT(m_controller); 50 if (m_started) { 51 exceptionState.throwDOMException(InvalidStateError, "recognition has already started."); 52 return; 53 } 54 55 setPendingActivity(this); 56 m_finalResults.clear(); 57 m_controller->start(this, m_grammars.get(), m_lang, m_continuous, m_interimResults, m_maxAlternatives); 58 m_started = true; 59 } 60 61 void SpeechRecognition::stopFunction() 62 { 63 ASSERT(m_controller); 64 if (m_started && !m_stopping) { 65 m_stopping = true; 66 m_controller->stop(this); 67 } 68 } 69 70 void SpeechRecognition::abort() 71 { 72 ASSERT(m_controller); 73 if (m_started && !m_stopping) { 74 m_stopping = true; 75 m_controller->abort(this); 76 } 77 } 78 79 void SpeechRecognition::didStartAudio() 80 { 81 dispatchEvent(Event::create(EventTypeNames::audiostart)); 82 } 83 84 void SpeechRecognition::didStartSound() 85 { 86 dispatchEvent(Event::create(EventTypeNames::soundstart)); 87 } 88 89 void SpeechRecognition::didStartSpeech() 90 { 91 dispatchEvent(Event::create(EventTypeNames::speechstart)); 92 } 93 94 void SpeechRecognition::didEndSpeech() 95 { 96 dispatchEvent(Event::create(EventTypeNames::speechend)); 97 } 98 99 void SpeechRecognition::didEndSound() 100 { 101 dispatchEvent(Event::create(EventTypeNames::soundend)); 102 } 103 104 void SpeechRecognition::didEndAudio() 105 { 106 dispatchEvent(Event::create(EventTypeNames::audioend)); 107 } 108 109 void SpeechRecognition::didReceiveResults(const Vector<RefPtr<SpeechRecognitionResult> >& newFinalResults, const Vector<RefPtr<SpeechRecognitionResult> >& currentInterimResults) 110 { 111 unsigned long resultIndex = m_finalResults.size(); 112 113 for (size_t i = 0; i < newFinalResults.size(); ++i) 114 m_finalResults.append(newFinalResults[i]); 115 116 Vector<RefPtr<SpeechRecognitionResult> > results = m_finalResults; 117 for (size_t i = 0; i < currentInterimResults.size(); ++i) 118 results.append(currentInterimResults[i]); 119 120 dispatchEvent(SpeechRecognitionEvent::createResult(resultIndex, results)); 121 } 122 123 void SpeechRecognition::didReceiveNoMatch(PassRefPtr<SpeechRecognitionResult> result) 124 { 125 dispatchEvent(SpeechRecognitionEvent::createNoMatch(result)); 126 } 127 128 void SpeechRecognition::didReceiveError(PassRefPtr<SpeechRecognitionError> error) 129 { 130 dispatchEvent(error); 131 m_started = false; 132 } 133 134 void SpeechRecognition::didStart() 135 { 136 dispatchEvent(Event::create(EventTypeNames::start)); 137 } 138 139 void SpeechRecognition::didEnd() 140 { 141 m_started = false; 142 m_stopping = false; 143 if (!m_stoppedByActiveDOMObject) 144 dispatchEvent(Event::create(EventTypeNames::end)); 145 unsetPendingActivity(this); 146 } 147 148 const AtomicString& SpeechRecognition::interfaceName() const 149 { 150 return EventTargetNames::SpeechRecognition; 151 } 152 153 ExecutionContext* SpeechRecognition::executionContext() const 154 { 155 return ActiveDOMObject::executionContext(); 156 } 157 158 void SpeechRecognition::stop() 159 { 160 m_stoppedByActiveDOMObject = true; 161 if (hasPendingActivity()) 162 abort(); 163 } 164 165 SpeechRecognition::SpeechRecognition(ExecutionContext* context) 166 : ActiveDOMObject(context) 167 , m_grammars(SpeechGrammarList::create()) // FIXME: The spec is not clear on the default value for the grammars attribute. 168 , m_continuous(false) 169 , m_interimResults(false) 170 , m_maxAlternatives(1) 171 , m_controller(0) 172 , m_stoppedByActiveDOMObject(false) 173 , m_started(false) 174 , m_stopping(false) 175 { 176 ScriptWrappable::init(this); 177 Document* document = toDocument(executionContext()); 178 179 Page* page = document->page(); 180 ASSERT(page); 181 182 m_controller = SpeechRecognitionController::from(page); 183 ASSERT(m_controller); 184 185 // FIXME: Need to hook up with Page to get notified when the visibility changes. 186 } 187 188 SpeechRecognition::~SpeechRecognition() 189 { 190 } 191 192 } // namespace WebCore 193