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/core/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 38namespace blink { 39 40SpeechRecognition* SpeechRecognition::create(ExecutionContext* context) 41{ 42 SpeechRecognition* speechRecognition = adoptRefCountedGarbageCollectedWillBeNoop(new SpeechRecognition(context)); 43 speechRecognition->suspendIfNeeded(); 44 return speechRecognition; 45} 46 47void 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 m_finalResults.clear(); 56 m_controller->start(this, m_grammars.get(), m_lang, m_continuous, m_interimResults, m_maxAlternatives); 57 m_started = true; 58} 59 60void SpeechRecognition::stopFunction() 61{ 62 ASSERT(m_controller); 63 if (m_started && !m_stopping) { 64 m_stopping = true; 65 m_controller->stop(this); 66 } 67} 68 69void SpeechRecognition::abort() 70{ 71 ASSERT(m_controller); 72 if (m_started && !m_stopping) { 73 m_stopping = true; 74 m_controller->abort(this); 75 } 76} 77 78void SpeechRecognition::didStartAudio() 79{ 80 dispatchEvent(Event::create(EventTypeNames::audiostart)); 81} 82 83void SpeechRecognition::didStartSound() 84{ 85 dispatchEvent(Event::create(EventTypeNames::soundstart)); 86} 87 88void SpeechRecognition::didStartSpeech() 89{ 90 dispatchEvent(Event::create(EventTypeNames::speechstart)); 91} 92 93void SpeechRecognition::didEndSpeech() 94{ 95 dispatchEvent(Event::create(EventTypeNames::speechend)); 96} 97 98void SpeechRecognition::didEndSound() 99{ 100 dispatchEvent(Event::create(EventTypeNames::soundend)); 101} 102 103void SpeechRecognition::didEndAudio() 104{ 105 dispatchEvent(Event::create(EventTypeNames::audioend)); 106} 107 108void SpeechRecognition::didReceiveResults(const HeapVector<Member<SpeechRecognitionResult> >& newFinalResults, const HeapVector<Member<SpeechRecognitionResult> >& currentInterimResults) 109{ 110 unsigned long resultIndex = m_finalResults.size(); 111 112 for (size_t i = 0; i < newFinalResults.size(); ++i) 113 m_finalResults.append(newFinalResults[i]); 114 115 HeapVector<Member<SpeechRecognitionResult> > results = m_finalResults; 116 for (size_t i = 0; i < currentInterimResults.size(); ++i) 117 results.append(currentInterimResults[i]); 118 119 dispatchEvent(SpeechRecognitionEvent::createResult(resultIndex, results)); 120} 121 122void SpeechRecognition::didReceiveNoMatch(SpeechRecognitionResult* result) 123{ 124 dispatchEvent(SpeechRecognitionEvent::createNoMatch(result)); 125} 126 127void SpeechRecognition::didReceiveError(PassRefPtrWillBeRawPtr<SpeechRecognitionError> error) 128{ 129 dispatchEvent(error); 130 m_started = false; 131} 132 133void SpeechRecognition::didStart() 134{ 135 dispatchEvent(Event::create(EventTypeNames::start)); 136} 137 138void SpeechRecognition::didEnd() 139{ 140 m_started = false; 141 m_stopping = false; 142 if (!m_stoppedByActiveDOMObject) 143 dispatchEvent(Event::create(EventTypeNames::end)); 144} 145 146const AtomicString& SpeechRecognition::interfaceName() const 147{ 148 return EventTargetNames::SpeechRecognition; 149} 150 151ExecutionContext* SpeechRecognition::executionContext() const 152{ 153 return ActiveDOMObject::executionContext(); 154} 155 156void SpeechRecognition::stop() 157{ 158 m_stoppedByActiveDOMObject = true; 159 if (hasPendingActivity()) 160 abort(); 161} 162 163bool SpeechRecognition::hasPendingActivity() const 164{ 165 return m_started; 166} 167 168SpeechRecognition::SpeechRecognition(ExecutionContext* context) 169 : ActiveDOMObject(context) 170 , m_grammars(SpeechGrammarList::create()) // FIXME: The spec is not clear on the default value for the grammars attribute. 171 , m_continuous(false) 172 , m_interimResults(false) 173 , m_maxAlternatives(1) 174 , m_controller(nullptr) 175 , m_stoppedByActiveDOMObject(false) 176 , m_started(false) 177 , m_stopping(false) 178{ 179 Document* document = toDocument(executionContext()); 180 181 Page* page = document->page(); 182 ASSERT(page); 183 184 m_controller = SpeechRecognitionController::from(page); 185 ASSERT(m_controller); 186 187 // FIXME: Need to hook up with Page to get notified when the visibility changes. 188} 189 190SpeechRecognition::~SpeechRecognition() 191{ 192} 193 194void SpeechRecognition::trace(Visitor* visitor) 195{ 196 visitor->trace(m_grammars); 197#if ENABLE(OILPAN) 198 visitor->trace(m_controller); 199#endif 200 visitor->trace(m_finalResults); 201 EventTargetWithInlineData::trace(visitor); 202} 203 204} // namespace blink 205