Home | History | Annotate | Download | only in speech
      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 SpeechRecognition* SpeechRecognition::create(ExecutionContext* context)
     41 {
     42     SpeechRecognition* speechRecognition = adoptRefCountedGarbageCollectedWillBeNoop(new SpeechRecognition(context));
     43     speechRecognition->suspendIfNeeded();
     44     return speechRecognition;
     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     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 
     60 void 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 
     69 void 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 
     78 void SpeechRecognition::didStartAudio()
     79 {
     80     dispatchEvent(Event::create(EventTypeNames::audiostart));
     81 }
     82 
     83 void SpeechRecognition::didStartSound()
     84 {
     85     dispatchEvent(Event::create(EventTypeNames::soundstart));
     86 }
     87 
     88 void SpeechRecognition::didStartSpeech()
     89 {
     90     dispatchEvent(Event::create(EventTypeNames::speechstart));
     91 }
     92 
     93 void SpeechRecognition::didEndSpeech()
     94 {
     95     dispatchEvent(Event::create(EventTypeNames::speechend));
     96 }
     97 
     98 void SpeechRecognition::didEndSound()
     99 {
    100     dispatchEvent(Event::create(EventTypeNames::soundend));
    101 }
    102 
    103 void SpeechRecognition::didEndAudio()
    104 {
    105     dispatchEvent(Event::create(EventTypeNames::audioend));
    106 }
    107 
    108 void 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 
    122 void SpeechRecognition::didReceiveNoMatch(SpeechRecognitionResult* result)
    123 {
    124     dispatchEvent(SpeechRecognitionEvent::createNoMatch(result));
    125 }
    126 
    127 void SpeechRecognition::didReceiveError(PassRefPtrWillBeRawPtr<SpeechRecognitionError> error)
    128 {
    129     dispatchEvent(error);
    130     m_started = false;
    131 }
    132 
    133 void SpeechRecognition::didStart()
    134 {
    135     dispatchEvent(Event::create(EventTypeNames::start));
    136 }
    137 
    138 void SpeechRecognition::didEnd()
    139 {
    140     m_started = false;
    141     m_stopping = false;
    142     if (!m_stoppedByActiveDOMObject)
    143         dispatchEvent(Event::create(EventTypeNames::end));
    144 }
    145 
    146 const AtomicString& SpeechRecognition::interfaceName() const
    147 {
    148     return EventTargetNames::SpeechRecognition;
    149 }
    150 
    151 ExecutionContext* SpeechRecognition::executionContext() const
    152 {
    153     return ActiveDOMObject::executionContext();
    154 }
    155 
    156 void SpeechRecognition::stop()
    157 {
    158     m_stoppedByActiveDOMObject = true;
    159     if (hasPendingActivity())
    160         abort();
    161 }
    162 
    163 bool SpeechRecognition::hasPendingActivity() const
    164 {
    165     return m_started;
    166 }
    167 
    168 SpeechRecognition::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     ScriptWrappable::init(this);
    180     Document* document = toDocument(executionContext());
    181 
    182     Page* page = document->page();
    183     ASSERT(page);
    184 
    185     m_controller = SpeechRecognitionController::from(page);
    186     ASSERT(m_controller);
    187 
    188     // FIXME: Need to hook up with Page to get notified when the visibility changes.
    189 }
    190 
    191 SpeechRecognition::~SpeechRecognition()
    192 {
    193 }
    194 
    195 void SpeechRecognition::trace(Visitor* visitor)
    196 {
    197     visitor->trace(m_grammars);
    198 #if ENABLE(OILPAN)
    199     visitor->trace(m_controller);
    200 #endif
    201     visitor->trace(m_finalResults);
    202     EventTargetWithInlineData::trace(visitor);
    203 }
    204 
    205 } // namespace WebCore
    206