summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/extensions/api/extension_api.json194
-rw-r--r--chrome/common/extensions/docs/experimental.html1
-rw-r--r--chrome/common/extensions/docs/experimental.tts.html1285
-rw-r--r--chrome/common/extensions/docs/experimental.ttsEngine.html1468
-rw-r--r--chrome/common/extensions/docs/static/experimental.tts.html233
-rw-r--r--chrome/common/extensions/docs/static/experimental.ttsEngine.html152
-rw-r--r--chrome/common/extensions/extension.cc42
-rw-r--r--chrome/common/extensions/extension.h3
-rw-r--r--chrome/common/extensions/extension_constants.cc27
-rw-r--r--chrome/common/extensions/extension_constants.h14
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc29
11 files changed, 2948 insertions, 500 deletions
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index ac3510e..6458211 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -508,6 +508,76 @@
},
{
"namespace": "experimental.tts",
+ "types": [
+ {
+ "id": "TtsEvent",
+ "type": "object",
+ "description": "An event from the TTS engine to communicate the status of an utterance.",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["start", "end", "word", "sentence", "marker", "interrupted", "cancelled", "error"],
+ "description": "The message can be 'start' when this utterance is begun to be spoken, 'word' when a word boundary is reached, 'sentence' when a sentence boundary is reached, 'marker' when an SSML mark element is reached, 'end' when the end of the utterance is reached, 'interrupted' when the utterance is stopped or interrupted before reaching the end, 'cancelled' when it's removed from the queue before ever being synthesized, and 'error' when any other error occurs. Clients will always receive 'end', 'cancelled', 'interrupted', or 'error', and other events will depend on the engine."
+ },
+ "charIndex": {
+ "type": "number",
+ "optional": true,
+ "description": "The index of the current character in the utterance."
+ },
+ "errorMessage": {
+ "type": "string",
+ "description": "The error message, if the message is 'error'.",
+ "optional": true
+ },
+ "srcId": {
+ "type": "number",
+ "description": "An ID unique to the calling function's context so that events can get routed back to the correct tts.speak call.",
+ "nodoc": true,
+ "optional": true
+ },
+ "isFinalEvent": {
+ "type": "boolean",
+ "description": "True if this is the final event that will be sent to this handler.",
+ "nodoc": true,
+ "optional": true
+ }
+ }
+ },
+ {
+ "id": "TtsVoice",
+ "type": "object",
+ "description": "A description of a voice available for speech synthesis.",
+ "properties": {
+ "voiceName": {
+ "type": "string",
+ "optional": true,
+ "description": "The name of the voice."
+ },
+ "lang": {
+ "type": "string",
+ "optional": true,
+ "description": "The language that this voice supports, in the form <language>-<region>. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc."
+ },
+ "gender": {
+ "type": "string",
+ "optional": true,
+ "description": "This voice's gender.",
+ "enum": ["male", "female"]
+ },
+ "extensionId": {
+ "type": "string",
+ "optional": true,
+ "description": "The ID of the extension providing this voice."
+ },
+ "eventTypes": {
+ "type": "array",
+ "items": {"type": "string"},
+ "optional": true,
+ "description": "All of the callback event types that this voice is capable of sending."
+ }
+ }
+ }
+ ],
"functions": [
{
"name": "speak",
@@ -517,7 +587,7 @@
{
"type": "string",
"name": "utterance",
- "description": "The text to speak. May include SSML markup."
+ "description": "The text to speak, either plaintext or a complete well-formed SSML document. Speech engines that do not support SSML will strip away the tags and speak the text. The maximum length of the text is 32,768 characters."
},
{
"type": "object",
@@ -535,10 +605,15 @@
"optional": true,
"description": "The name of the voice to use for synthesis. If empty, uses any available voice."
},
- "locale": {
+ "extensionId": {
+ "type": "string",
+ "optional": true,
+ "description": "The specific extension ID of the speech engine to use, if known."
+ },
+ "lang": {
"type": "string",
"optional": true,
- "description": "The language and optional region code that specify the language and dialect to be used for synthesis, in the form <language>-<region>. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc."
+ "description": "The language to be used for synthesis, in the form <language>-<region>. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc."
},
"gender": {
"type": "string",
@@ -549,16 +624,16 @@
"rate": {
"type": "number",
"optional": true,
- "minimum": 0,
- "maximum": 1,
- "description": "Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest, with a default of 0.5."
+ "minimum": 0.1,
+ "maximum": 10,
+ "description": "Speaking rate relative to the default rate for this voice. 1.0 is the default rate, normally around 180 to 220 words per minute, 2.0 would be twice as fast, and 0.5 would be half as fast. Values below 0.1 or above 10.0 are strictly disallowed, but many voices will constrain the minimum and maximum rates further - i.e. a particular voice may not actually speak faster than 3 times normal even if you specify a value larger than 3.0."
},
"pitch": {
"type": "number",
"optional": true,
"minimum": 0,
- "maximum": 1,
- "description": "Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 0.5."
+ "maximum": 2,
+ "description": "Speaking pitch between 0 and 2 inclusive, with 0 being lowest and 1 being highest, with 1.0 being the default pitch of this particular voice."
},
"volume": {
"type": "number",
@@ -566,6 +641,30 @@
"minimum": 0,
"maximum": 1,
"description": "Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0."
+ },
+ "requiredEventTypes": {
+ "type": "array",
+ "items": {"type": "string"},
+ "optional": true,
+ "description": "The TTS event types the voice must support. If missing, this criteria will not be used to filter voices."
+ },
+ "desiredEventTypes": {
+ "type": "array",
+ "items": {"type": "string"},
+ "optional": true,
+ "description": "The TTS event types that should be sent. If missing, all event types will be sent."
+ },
+ "onevent": {
+ "type": "function",
+ "optional": true,
+ "description": "This function is called with events that occur in the process of speaking the utterance.",
+ "parameters": [
+ {
+ "name": "event",
+ "$ref": "TtsEvent",
+ "description": "The update event from the text-to-speech engine indicating the status of this utterance."
+ }
+ ]
}
}
},
@@ -573,7 +672,7 @@
"type": "function",
"name": "callback",
"optional": true,
- "description": "This function is called when speaking is finished.",
+ "description": "Called right away, before speech finishes. Check chrome.extension.lastError to make sure there were no errors. Use options.onevent to get more detailed feedback.",
"parameters": []
}
]
@@ -604,19 +703,44 @@
]
},
{
- "name": "speakCompleted",
+ "name": "getVoices",
+ "type": "function",
+ "description": "Get an array of all available voices.",
+ "parameters": [
+ {
+ "type": "function",
+ "name": "callback",
+ "optional": true,
+ "parameters": [
+ {
+ "type": "array",
+ "name": "voices",
+ "items": { "$ref": "TtsVoice" },
+ "description": "Array of $ref:TtsVoice objects representing the available voices for speech synthesis."
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "namespace": "experimental.ttsEngine",
+ "functions": [
+ {
+ "name": "sendTtsEvent",
"nodoc": true,
"type": "function",
- "description": "A callback passed to the onSpeak event.",
+ "description": "Route a TTS event from a speech engine to a client.",
"parameters": [
{
"type": "integer",
"name": "requestId"
},
{
- "type": "string",
- "optional": "true",
- "name": "errorMessage"
+ "name": "event",
+ "$ref": "TtsEvent",
+ "description": "The update event from the text-to-speech engine indicating the status of this utterance."
}
]
}
@@ -630,7 +754,7 @@
{
"type": "string",
"name": "utterance",
- "description": "The text to speak. This may include SSML, so if your engine does not support SSML, you should strip out all XML markup and synthesize only the underlying text content."
+ "description": "The text to speak. This may include SSML, so if your engine does not support SSML, you should strip out all XML markup and synthesize only the underlying text content. This is guaranteed to be no more than 32,768 characters. If this engine does not support speaking that many characters at a time, the utterance should be split into smaller chunks and queued internally without returning an error."
},
{
"type": "object",
@@ -642,10 +766,10 @@
"optional": true,
"description": "The name of the voice to use for synthesis."
},
- "locale": {
+ "lang": {
"type": "string",
"optional": true,
- "description": "The language and region code that specify the language and dialect to be used for synthesis, in the form <language>-<region>, e.g. en-US, en-GB, fr-CA, zh-CN, etc."
+ "description": "The language to be used for synthesis, in the form <language>-<region>, e.g. en-US, en-GB, fr-CA, zh-CN, etc."
},
"gender": {
"type": "string",
@@ -656,36 +780,35 @@
"rate": {
"type": "number",
"optional": true,
- "minimum": 0,
- "maximum": 1,
- "description": "Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest."
+ "minimum": 0.1,
+ "maximum": 10.0,
+ "description": "Speaking rate relative to the default rate for this voice. 1.0 is the default rate, normally around 180 to 220 words per minute, 2.0 would be twice as fast, and 0.5 would be half as fast. This value is guaranteed to be between 0.1 and 10.0, inclusive. When a voice does not support this full range of rates, the actual rate should be clipped to the range that is supported without returning an error."
},
"pitch": {
"type": "number",
"optional": true,
"minimum": 0,
- "maximum": 1,
- "description": "Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest."
+ "maximum": 2,
+ "description": "Speaking pitch between 0 and 2 inclusive, with 0 being lowest and 1 being highest, with 1.0 being the default pitch of this particular voice."
},
"volume": {
"type": "number",
"optional": true,
"minimum": 0,
"maximum": 1,
- "description": "Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest."
+ "description": "Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0."
}
}
},
{
+ "name": "sendTtsEvent",
"type": "function",
- "name": "callback",
- "description": "You must call this function when speaking is finished.",
+ "description": "Call this function with events that occur in the process of speaking the utterance.",
"parameters": [
{
- "type": "string",
- "name": "error",
- "optional": true,
- "description": "Error message, which will be returned to the caller in chrome.extension.lastError."
+ "name": "event",
+ "$ref": "TtsEvent",
+ "description": "The event from the text-to-speech engine indicating the status of this utterance."
}
]
}
@@ -695,6 +818,19 @@
"name": "onStop",
"type": "function",
"description": "Fired when a call is made to tts.stop and this extension may be in the middle of speaking. If an extension receives a call to onStop and speech is already stopped, it should do nothing (not raise an error)."
+ },
+ {
+ "name": "onEvent",
+ "type": "function",
+ "nodoc": true,
+ "parameters": [
+ {
+ "name": "event",
+ "$ref": "TtsEvent",
+ "description": "The event from the text-to-speech engine indicating the status of this utterance."
+ }
+ ],
+ "description": "Used to pass events back to the function calling speak()."
}
]
},
diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html
index 5ac04c5..cd536c5 100644
--- a/chrome/common/extensions/docs/experimental.html
+++ b/chrome/common/extensions/docs/experimental.html
@@ -331,6 +331,7 @@ on the following experimental APIs:
<a href="experimental.processes.html">experimental.processes</a></li><li>
<a href="experimental.sidebar.html">experimental.sidebar</a></li><li>
<a href="experimental.tts.html">experimental.tts</a></li><li>
+ <a href="experimental.ttsEngine.html">experimental.ttsEngine</a></li><li>
<a href="experimental.webNavigation.html">experimental.webNavigation</a></li><li>
<a href="experimental.webRequest.html">experimental.webRequest</a></li>
</ul>
diff --git a/chrome/common/extensions/docs/experimental.tts.html b/chrome/common/extensions/docs/experimental.tts.html
index fb487cd..e3fb2b0 100644
--- a/chrome/common/extensions/docs/experimental.tts.html
+++ b/chrome/common/extensions/docs/experimental.tts.html
@@ -272,6 +272,13 @@
</li>
</ol>
</li><li>
+ <a href="#events">Listening to events</a>
+ <ol>
+ <li style="display: none; ">
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li><li>
<a href="#ssml">SSML markup</a>
<ol>
<li style="display: none; ">
@@ -279,7 +286,7 @@
</li>
</ol>
</li><li>
- <a href="#provider">Implementing a speech provider</a>
+ <a href="#choosing_voice">Choosing a voice</a>
<ol>
<li style="display: none; ">
<a>h3Name</a>
@@ -301,31 +308,31 @@
<a href="#global-methods">Methods</a>
<ol>
<li>
+ <a href="#method-getVoices">getVoices</a>
+ </li><li>
<a href="#method-isSpeaking">isSpeaking</a>
</li><li>
<a href="#method-speak">speak</a>
- </li><li style="display: none; ">
- <a href="#method-anchor">methodName</a>
</li><li>
<a href="#method-stop">stop</a>
</li>
</ol>
</li>
- <li>
- <a href="#global-events">Events</a>
+ <li style="display: none; ">
+ <a>Events</a>
<ol>
<li>
- <a href="#event-onSpeak">onSpeak</a>
- </li><li>
- <a href="#event-onStop">onStop</a>
+ <a href="#event-anchor">eventName</a>
</li>
</ol>
</li>
- <li style="display: none; ">
+ <li>
<a href="#types">Types</a>
<ol>
<li>
- <a href="#id-anchor">id</a>
+ <a href="#type-TtsEvent">TtsEvent</a>
+ </li><li>
+ <a href="#type-TtsVoice">TtsVoice</a>
</li>
</ol>
</li>
@@ -343,8 +350,10 @@
<!-- STATIC CONTENT PLACEHOLDER -->
<div id="static"><p id="classSummary">
Use the <code>chrome.experimental.tts</code> module to play synthesized
-text-to-speech (TTS) from your extension or packaged app, or to register
-as a speech provider for other extensions and packaged apps that want to speak.
+text-to-speech (TTS) from your extension or packaged app.
+See also the related
+<a href="experimental.ttsEngine.html">experimental.ttsEngine</a>
+module which allows an extension to implement a speech engine.
</p>
<p class="note"><b>Give us feedback:</b> If you have suggestions,
@@ -362,7 +371,7 @@ group.</p>
5), Mac OS X, and Chrome OS, using speech synthesis capabilities
provided by the operating system. On all platforms, the user can
install extensions that register themselves as alternative speech
-synthesis providers.</p>
+engines.</p>
<h2 id="generating_speech">Generating speech</h2>
@@ -371,122 +380,163 @@ packaged app to speak. For example:</p>
<pre>chrome.experimental.tts.speak('Hello, world.');</pre>
+<p>To stop speaking immediately, just call <code>stop()</code>:
+
+</p><pre>chrome.experimental.tts.stop();</pre>
+
<p>You can provide options that control various properties of the speech,
such as its rate, pitch, and more. For example:</p>
-<pre>chrome.experimental.tts.speak('Hello, world.', {'rate': 0.8});</pre>
+<pre>chrome.experimental.tts.speak('Hello, world.', {'rate': 2.0});</pre>
-<p>It's also a good idea to specify the locale so that a synthesizer
+<p>It's also a good idea to specify the language so that a synthesizer
supporting that language (and regional dialect, if applicable) is chosen.</p>
<pre>chrome.experimental.tts.speak(
- 'Hello, world.',
- {
- 'locale': 'en-US',
- 'rate': 0.8
- });</pre>
+ 'Hello, world.', {'lang': 'en-US', 'rate': 2.0});</pre>
-<p>Not all speech engines will support all options.</p>
+<p>By default, each call to <code>speak()</code> will interrupt any
+ongoing speech and speak immediately. To determine if a call would be
+interrupting anything, you can call <code>isSpeaking()</code>, or
+you can use the <code>enqueue</code> option to cause this utterance to
+be added to a queue of utterances that will be spoken when the current
+utterance has finished.
-<p>You can also pass a callback function that will be called when the
-speech has finished. For example, suppose we have an image on our page
-displaying a picture of a face with a closed mouth. We could open the mouth
-while speaking, and close it when done.</p>
-
-<pre>faceImage.src = 'open_mouth.png';
+</p><pre>chrome.experimental.tts.speak(
+ 'Speak this first.');
chrome.experimental.tts.speak(
- 'Hello, world.', null, function() {
- faceImage.src = 'closed_mouth.png';
- });
+ 'Speak this next, when the first sentence is done.', {'enqueue': true});
</pre>
-<p>To stop speaking immediately, just call <code>stop()</code>. Call
-<code>isSpeaking()</code> to find out if a TTS engine is currently speaking.</p>
+<p>A complete description of all options can be found in the
+<a href="#method-speak">speak() method documentation</a> below.
+Not all speech engines will support all options.</p>
+
+<p>To catch errors and make sure you're calling <code>speak()</code>
+correctly, pass a callback function that takes no arguments. Inside
+the callback, check
+<a href="extension.html#property-lastError">chrome.extension.lastError</a>
+to see if there were any errors.</p>
+
+<pre>chrome.experimental.tts.speak(
+ utterance,
+ options,
+ function() {
+ if (chrome.extension.lastError) {
+ console.log('Error: ' + chrome.extension.lastError.message);
+ }
+ });</pre>
-<p>You can check to see if an error occurred by checking
-<code>chrome.extension.lastError</code> inside the callback function.</p>
+<p>The callback returns right away, before the speech engine has started
+generating speech. The purpose of the callback is to alert you to syntax
+errors in your use of the TTS API, not all possible errors that might occur
+in the process of synthesizing and outputting speech. To catch these errors
+too, you need to use an event listener, described below.
-<h2 id="ssml">SSML markup</h2>
+</p><h2 id="events">Listening to events</h2>
+
+<p>To get more real-time information about the status of synthesized speech,
+pass an event listener in the options to <code>speak()</code>, like this:</p>
+
+<pre>chrome.experimental.tts.speak(
+ utterance,
+ {
+ 'onevent': function(event) {
+ console.log('Event ' + event.type ' at position ' + event.charIndex);
+ if (event.type == 'error') {
+ console.log('Error: ' + event.errorMessage);
+ }
+ }
+ },
+ callback);</pre>
+
+<p>Each event includes an event type, the character index of the current
+speech relative to the utterance, and for error events, an optional
+error message. The event types are:</p>
+
+<ul>
+ <li><code>'start'</code>: the engine has started speaking the utterance.
+ </li><li><code>'word'</code>: a word boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ </li><li><code>'sentence'</code>: a sentence boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ </li><li><code>'marker'</code>: an SSML marker was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ </li><li><code>'end'</code>: the engine has finished speaking the utterance.
+ </li><li><code>'interrupted'</code>: this utterance was interrupted by another
+ call to <code>speak()</code> or <code>stop()</code> and did not
+ finish.
+ </li><li><code>'cancelled'</code>: this utterance was queued, but then
+ cancelled by another call to <code>speak()</code> or
+ <code>stop()</code> and never began to speak at all.
+ </li><li><code>'error'</code>: An engine-specific error occurred and
+ this utterance cannot be spoken.
+ Check <code>event.errorMessage</code> for details.
+</li></ul>
+
+<p>Four of the event types, <code>'end'</code>, <code>'interrupted'</code>,
+<code>'cancelled'</code>, and <code>'error'</code>, are <i>final</i>. After
+one of those events is received, this utterance will no longer speak and
+no new events from this utterance will be received.</p>
+
+<p>Some TTS engines may not support all event types, and some may not even
+support any events at all. To require that the speech engine used sends
+the events you're interested in, you can pass a list of event types in
+the <code>requiredEventTypes</code> member of the options object, or use
+<code>getVoices</code> to choose a voice that has the events you need.
+Both are documented below.
+
+</p><h2 id="ssml">SSML markup</h2>
<p>Utterances used in this API may include markup using the
<a href="http://www.w3.org/TR/speech-synthesis">Speech Synthesis Markup
-Language (SSML)</a>. For example:
+Language (SSML)</a>. If you use SSML, the first argument to
+<code>speak()</code> should be a complete SSML document with an XML
+header and a top-level <code>&lt;speak&gt;</code> tag, not a document
+fragment.
+
+For example:
-</p><pre>chrome.experimental.tts.speak('The &lt;emphasis&gt;second&lt;/emphasis&gt; word of this sentence was emphasized.');</pre>
+</p><pre>chrome.experimental.tts.speak(
+ '&lt;?xml version="1.0"?&gt;' +
+ '&lt;speak&gt;' +
+ ' The &lt;emphasis&gt;second&lt;/emphasis&gt; ' +
+ ' word of this sentence was emphasized.' +
+ '&lt;/speak&gt;');</pre>
<p>Not all speech engines will support all SSML tags, and some may not support
-SSML at all, but all engines are expected to ignore any SSML they don't
+SSML at all, but all engines are required to ignore any SSML they don't
support and still speak the underlying text.</p>
-<h2 id="provider">Implementing a speech provider</h2>
-
-<p>An extension can register itself as a speech provider. By doing so, it
-can intercept some or all calls to functions such as
-<code>speak()</code> and <code>stop()</code> and provide an alternate
-implementation. Extensions are free to use any available web technology
-to provide speech, including streaming audio from a server, HTML5 audio,
-Native Client, or Flash. An extension could even do something different
-with the utterances, like display closed captions in a pop-up window or
-send them as log messages to a remote server.</p>
-
-<p>To provide TTS, an extension must first declare all voices it provides
-in the extension manifest, like this:</p>
-
-<pre>{
- "name": "My TTS Provider",
- "version": "1.0",
- <b>"permissions": ["experimental"]
- "tts": {
- "voices": [
- {
- "voiceName": "Alice",
- "locale": "en-US",
- "gender": "female"
- },
- {
- "voiceName": "Pat",
- "locale": "en-US"
+<h2 id="choosing_voice">Choosing a voice</h2>
+
+<p>By default, Chrome will choose the most appropriate voice for each
+utterance you want to speak, based on the language and gender. On most
+Windows, Mac OS X, and Chrome OS systems, speech synthesis provided by
+the operating system should be able to speak any text in at least one
+language. Some users may have a variety of voices available, though,
+from their operating system and from speech engines implemented by other
+Chrome extensions. In those cases, you can implement custom code to choose
+the appropriate voice, or present the user with a list of choices.</p>
+
+<p>To get a list of all voices, call <code>getVoices()</code> and pass it
+a function that receives an array of <code>TtsVoice</code> objects as its
+argument:</p>
+
+<pre>chrome.experimental.tts.getVoices(
+ function(voices) {
+ for (var i = 0; i &lt; voices.length; i++) {
+ console.log('Voice ' + i + ':');
+ console.log(' name: ' + voices[i].voiceName);
+ console.log(' lang: ' + voices[i].lang);
+ console.log(' gender: ' + voices[i].gender);
+ console.log(' extension id: ' + voices[i].extensionId);
+ console.log(' event types: ' + voices[i].eventTypes);
}
- ]
- },</b>
- "background_page": "background.html",
-}</pre>
-
-<p>An extension can specify any number of voices. The three
-parameters—<code>voiceName</code>, <code>locale</code>,
-and <code>gender</code>—are all optional. If they are all unspecified,
-the extension will handle all speech from all clients. If any of them
-are specified, they can be used to filter speech requests. For
-example, if a voice only supports French, it should set the locale to
-'fr' (or something more specific like 'fr-FR') so that only utterances
-in that locale are routed to that extension.</p>
-
-<p>To handle speech calls, the extension should register listeners
-for <code>onSpeak</code> and <code>onStop</code>, like this:</p>
-
-<pre>var speakListener = function(utterance, options, callback) {
- ...
- callback();
-};
-var stopListener = function() {
- ...
-};
-chrome.experimental.tts.onSpeak.addListener(speakListener);
-chrome.experimental.tts.onStop.addListener(stopListener);</pre>
-
-<p class="warning"><b>Important:</b> Don't forget to call the callback
-function from your speak listener!</p>
-
-<p>If an extension does not register listeners for both
-<code>onSpeak</code> and <code>onStop</code>, it will not intercept any
-speech calls, regardless of what is in the manifest.
-
-</p><p>The decision of whether or not to send a given speech request to an
-extension is based solely on whether the extension supports the given voice
-parameters in its manifest and has registered listeners
-for <code>onSpeak</code> and <code>onStop</code>. In other words,
-there's no way for an extension to receive a speech request and
-dynamically decide whether to handle it or not.</p>
+ });</pre>
</div>
<!-- API PAGE -->
@@ -519,6 +569,213 @@ dynamically decide whether to handle it or not.</p>
<!-- iterates over all functions -->
<div class="apiItem">
+ <a name="method-getVoices"></a> <!-- method-anchor -->
+ <h4>getVoices</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.tts.getVoices</span>(<span class="optional"><span style="display: none; ">, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Get an array of all available voices.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p style="display: none; ">
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>array of TtsVoice voices</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>voices</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span>
+ <span>
+ <a href="experimental.tts.html#type-TtsVoice">TtsVoice</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span></span>
+ </span>
+ <span style="display: none; ">paramType</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Array of <a href="experimental.tts.html#type-TtsVoice">TtsVoice</a> objects representing the available voices for speech synthesis.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
<a name="method-isSpeaking"></a> <!-- method-anchor -->
<h4>isSpeaking</h4>
@@ -763,7 +1020,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The text to speak. May include SSML markup.</dd>
+ <dd>The text to speak, either plaintext or a complete well-formed SSML document. Speech engines that do not support SSML will strip away the tags and speak the text. The maximum length of the text is 32,768 characters.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -984,7 +1241,7 @@ dynamically decide whether to handle it or not.</p>
</div><div>
<div>
<dt>
- <var>locale</var>
+ <var>extensionId</var>
<em>
<!-- TYPE -->
@@ -1012,7 +1269,75 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The language and optional region code that specify the language and dialect to be used for synthesis, in the form &lt;language&gt;-&lt;region&gt;. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc.</dd>
+ <dd>The specific extension ID of the speech engine to use, if known.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>lang</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The language to be used for synthesis, in the form &lt;language&gt;-&lt;region&gt;. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1148,7 +1473,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest, with a default of 0.5.</dd>
+ <dd>Speaking rate relative to the default rate for this voice. 1.0 is the default rate, normally around 180 to 220 words per minute, 2.0 would be twice as fast, and 0.5 would be half as fast. Values below 0.1 or above 10.0 are strictly disallowed, but many voices will constrain the minimum and maximum rates further - i.e. a particular voice may not actually speak faster than 3 times normal even if you specify a value larger than 3.0.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1216,7 +1541,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 0.5.</dd>
+ <dd>Speaking pitch between 0 and 2 inclusive, with 0 being lowest and 1 being highest, with 1.0 being the default pitch of this particular voice.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1321,6 +1646,65 @@ dynamically decide whether to handle it or not.</p>
</dd>
</div>
+ </div><div>
+ <div>
+ <dt>
+ <var>requiredEventTypes</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span>
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span></span>
+ </span>
+ <span style="display: none; ">paramType</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The TTS event types the voice must support. If missing, this criteria will not be used to filter voices.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
</div>
</dl>
</dd>
@@ -1341,10 +1725,10 @@ dynamically decide whether to handle it or not.</p>
</dd>
</div>
- </div><div>
- <div>
+ </div><div>
+ <div>
<dt>
- <var>callback</var>
+ <var>desiredEventTypes</var>
<em>
<!-- TYPE -->
@@ -1357,10 +1741,21 @@ dynamically decide whether to handle it or not.</p>
<a> Type</a>
</span>
<span>
+ <span>
+ array of <span><span>
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>function</span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span></span>
+ </span>
+ <span style="display: none; ">paramType</span>
<span style="display: none; "></span>
</span>
</span>
@@ -1372,7 +1767,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>This function is called when speaking is finished.</dd>
+ <dd>The TTS event types that should be sent. If missing, all event types will be sent.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1409,79 +1804,242 @@ dynamically decide whether to handle it or not.</p>
</dd>
</div>
- </div>
- </dl>
+ </div><div>
+ <div>
+ <dt>
+ <var>onevent</var>
+ <em>
- <!-- RETURNS -->
- <h4 style="display: none; ">Returns</h4>
- <dl>
- <div style="display: none; ">
- <div>
- </div>
- </div>
- </dl>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
- <!-- CALLBACK -->
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>This function is called with events that occur in the process of speaking the utterance.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
<div>
- <div>
- <h4>Callback function</h4>
- <p style="display: none; ">
- The callback <em>parameter</em> should specify a function
- that looks like this:
- </p>
- <p>
- If you specify the <em>callback</em> parameter, it should
- specify a function that looks like this:
- </p>
+ </div>
+ </div>
+ </dl>
+ </dd>
- <!-- Note: intentionally longer 80 columns -->
- <pre>function(<span></span>) <span class="subdued">{...}</span>;</pre>
- <dl>
- <div style="display: none; ">
- <div>
- </div>
- </div>
- </dl>
- </div>
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd>
+ <div>
+ <h5>Parameters</h5>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>event</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.tts.html#type-TtsEvent">TtsEvent</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
</div>
- <!-- MIN_VERSION -->
- <p style="display: none; ">
- This function was added in version <b><span></span></b>.
- If you require this function, the manifest key
- <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
- can ensure that your extension won't be run in an earlier browser version.
- </p>
- </div> <!-- /description -->
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The update event from the text-to-speech engine indicating the status of this utterance.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
- </div><div class="apiItem" style="display: none; ">
- <a></a> <!-- method-anchor -->
- <h4>method name</h4>
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
- <div class="summary"><span>void</span>
- <!-- Note: intentionally longer 80 columns -->
- <span>chrome.module.methodName</span>(<span><span>, </span><span></span>
- <var><span></span></var></span>)</div>
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
- <div class="description">
- <p class="todo">Undocumented.</p>
- <p>
- A description from the json schema def of the function goes here.
- </p>
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
- <!-- PARAMETERS -->
- <h4>Parameters</h4>
- <dl>
- <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
<div>
- </div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Called right away, before speech finishes. Check chrome.extension.lastError to make sure there were no errors. Use options.onevent to get more detailed feedback.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
</div>
</dl>
<!-- RETURNS -->
- <h4>Returns</h4>
+ <h4 style="display: none; ">Returns</h4>
<dl>
- <div>
+ <div style="display: none; ">
<div>
</div>
</div>
@@ -1491,7 +2049,7 @@ dynamically decide whether to handle it or not.</p>
<div>
<div>
<h4>Callback function</h4>
- <p>
+ <p style="display: none; ">
The callback <em>parameter</em> should specify a function
that looks like this:
</p>
@@ -1501,9 +2059,9 @@ dynamically decide whether to handle it or not.</p>
</p>
<!-- Note: intentionally longer 80 columns -->
- <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+ <pre>function(<span></span>) <span class="subdued">{...}</span>;</pre>
<dl>
- <div>
+ <div style="display: none; ">
<div>
</div>
</div>
@@ -1512,7 +2070,7 @@ dynamically decide whether to handle it or not.</p>
</div>
<!-- MIN_VERSION -->
- <p>
+ <p style="display: none; ">
This function was added in version <b><span></span></b>.
If you require this function, the manifest key
<a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
@@ -1589,22 +2147,24 @@ dynamically decide whether to handle it or not.</p>
</div> <!-- /apiGroup -->
<!-- EVENTS -->
- <div id="eventsTemplate" class="apiGroup">
- <a name="global-events"></a>
+ <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+ <a></a>
<h3>Events</h3>
<!-- iterates over all events -->
<div class="apiItem">
- <a name="event-onSpeak"></a>
- <h4>onSpeak</h4>
+ <a></a>
+ <h4>event name</h4>
<div class="summary">
<!-- Note: intentionally longer 80 columns -->
- <span class="subdued">chrome.experimental.tts.</span><span>onSpeak</span><span class="subdued">.addListener</span>(function(<span>string utterance, object options, function callback</span>) <span class="subdued">{...}</span><span></span>));
+ <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span><span>, Type opt_param1, Type opt_param2</span>));
</div>
<div class="description">
- <p class="todo" style="display: none; ">Undocumented.</p>
- <p>Called when the user makes a call to tts.speak and the options matches one of the tts_voices from this extension's manifest.</p>
+ <p class="todo">Undocumented.</p>
+ <p>
+ A description from the json schema def of the event goes here.
+ </p>
<!-- LISTENER PARAMETERS -->
<div>
@@ -1612,8 +2172,49 @@ dynamically decide whether to handle it or not.</p>
<dl>
<div>
<div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- EXTRA PARAMETERS -->
+ <div>
+ <h4>Extra parameters to addListener</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- LISTENER RETURN VALUE -->
+ <h4>Listener returns</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /description -->
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- TYPES -->
+ <div class="apiGroup">
+ <a name="types"></a>
+ <h3 id="types">Types</h3>
+
+ <!-- iterates over all types -->
+ <div class="apiItem">
+ <a name="type-TtsEvent"></a>
+ <h4>TtsEvent</h4>
+
+ <div>
<dt>
- <var>utterance</var>
+ <var style="display: none; ">paramName</var>
<em>
<!-- TYPE -->
@@ -1629,7 +2230,7 @@ dynamically decide whether to handle it or not.</p>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>string</span>
+ <span>object</span>
<span style="display: none; "></span>
</span>
</span>
@@ -1641,7 +2242,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The text to speak. This may include SSML, so if your engine does not support SSML, you should strip out all XML markup and synthesize only the underlying text content.</dd>
+ <dd>An event from the TTS engine to communicate the status of an utterance.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1653,42 +2254,19 @@ dynamically decide whether to handle it or not.</p>
</dd>
<!-- OBJECT PROPERTIES -->
- <dd style="display: none; ">
+ <dd>
<dl>
<div>
<div>
- </div>
- </div>
- </dl>
- </dd>
-
- <!-- OBJECT METHODS -->
- <dd style="display: none; ">
- <div></div>
- </dd>
-
- <!-- OBJECT EVENT FIELDS -->
- <dd style="display: none; ">
- <div></div>
- </dd>
-
- <!-- FUNCTION PARAMETERS -->
- <dd style="display: none; ">
- <div></div>
- </dd>
-
- </div>
- </div><div>
- <div>
<dt>
- <var>options</var>
+ <var>type</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional" style="display: none; ">optional</span>
- <span class="enum" style="display: none; ">enumerated</span>
+ <span class="enum">enumerated</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -1697,8 +2275,8 @@ dynamically decide whether to handle it or not.</p>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>object</span>
- <span style="display: none; "></span>
+ <span>string</span>
+ <span>["start", "end", "word", "sentence", "marker", "interrupted", "cancelled", "error"]</span>
</span>
</span>
)
@@ -1709,7 +2287,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The speak options.</dd>
+ <dd>The message can be 'start' when this utterance is begun to be spoken, 'word' when a word boundary is reached, 'sentence' when a sentence boundary is reached, 'marker' when an SSML mark element is reached, 'end' when the end of the utterance is reached, 'interrupted' when the utterance is stopped or interrupted before reaching the end, 'cancelled' when it's removed from the queue before ever being synthesized, and 'error' when any other error occurs. Clients will always receive 'end', 'cancelled', 'interrupted', or 'error', and other events will depend on the engine.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1721,12 +2299,35 @@ dynamically decide whether to handle it or not.</p>
</dd>
<!-- OBJECT PROPERTIES -->
- <dd>
+ <dd style="display: none; ">
<dl>
<div>
<div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
<dt>
- <var>voiceName</var>
+ <var>charIndex</var>
<em>
<!-- TYPE -->
@@ -1742,7 +2343,7 @@ dynamically decide whether to handle it or not.</p>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>string</span>
+ <span>number</span>
<span style="display: none; "></span>
</span>
</span>
@@ -1754,7 +2355,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The name of the voice to use for synthesis.</dd>
+ <dd>The index of the current character in the utterance.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1794,7 +2395,7 @@ dynamically decide whether to handle it or not.</p>
</div><div>
<div>
<dt>
- <var>locale</var>
+ <var>errorMessage</var>
<em>
<!-- TYPE -->
@@ -1822,7 +2423,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The language and region code that specify the language and dialect to be used for synthesis, in the form <language>-<region>, e.g. en-US, en-GB, fr-CA, zh-CN, etc.</region></language></dd>
+ <dd>The error message, if the message is 'error'.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1859,17 +2460,86 @@ dynamically decide whether to handle it or not.</p>
</dd>
</div>
- </div><div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+
+ </div><div class="apiItem">
+ <a name="type-TtsVoice"></a>
+ <h4>TtsVoice</h4>
+
+ <div>
+ <dt>
+ <var style="display: none; ">paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>A description of a voice available for speech synthesis.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
<div>
<dt>
- <var>gender</var>
+ <var>voiceName</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
- <span class="enum">enumerated</span>
+ <span class="enum" style="display: none; ">enumerated</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -1879,7 +2549,7 @@ dynamically decide whether to handle it or not.</p>
array of <span><span></span></span>
</span>
<span>string</span>
- <span>["male", "female"]</span>
+ <span style="display: none; "></span>
</span>
</span>
)
@@ -1890,7 +2560,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Gender of voice for synthesized speech.</dd>
+ <dd>The name of the voice.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1930,7 +2600,7 @@ dynamically decide whether to handle it or not.</p>
</div><div>
<div>
<dt>
- <var>rate</var>
+ <var>lang</var>
<em>
<!-- TYPE -->
@@ -1946,7 +2616,7 @@ dynamically decide whether to handle it or not.</p>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>number</span>
+ <span>string</span>
<span style="display: none; "></span>
</span>
</span>
@@ -1958,7 +2628,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest.</dd>
+ <dd>The language that this voice supports, in the form &lt;language&gt;-&lt;region&gt;. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1998,14 +2668,14 @@ dynamically decide whether to handle it or not.</p>
</div><div>
<div>
<dt>
- <var>pitch</var>
+ <var>gender</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
- <span class="enum" style="display: none; ">enumerated</span>
+ <span class="enum">enumerated</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2014,8 +2684,8 @@ dynamically decide whether to handle it or not.</p>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>number</span>
- <span style="display: none; "></span>
+ <span>string</span>
+ <span>["male", "female"]</span>
</span>
</span>
)
@@ -2026,7 +2696,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest.</dd>
+ <dd>This voice's gender.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2066,7 +2736,7 @@ dynamically decide whether to handle it or not.</p>
</div><div>
<div>
<dt>
- <var>volume</var>
+ <var>extensionId</var>
<em>
<!-- TYPE -->
@@ -2082,7 +2752,7 @@ dynamically decide whether to handle it or not.</p>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>number</span>
+ <span>string</span>
<span style="display: none; "></span>
</span>
</span>
@@ -2094,7 +2764,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest.</dd>
+ <dd>The ID of the extension providing this voice.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2131,46 +2801,37 @@ dynamically decide whether to handle it or not.</p>
</dd>
</div>
- </div>
- </dl>
- </dd>
-
- <!-- OBJECT METHODS -->
- <dd style="display: none; ">
- <div></div>
- </dd>
-
- <!-- OBJECT EVENT FIELDS -->
- <dd style="display: none; ">
- <div></div>
- </dd>
-
- <!-- FUNCTION PARAMETERS -->
- <dd style="display: none; ">
- <div></div>
- </dd>
-
- </div>
- </div><div>
- <div>
+ </div><div>
+ <div>
<dt>
- <var>callback</var>
+ <var>eventTypes</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional" style="display: none; ">optional</span>
+ <span class="optional">optional</span>
<span class="enum" style="display: none; ">enumerated</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
</span>
<span>
+ <span>
+ array of <span><span>
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>function</span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span></span>
+ </span>
+ <span style="display: none; ">paramType</span>
<span style="display: none; "></span>
</span>
</span>
@@ -2182,7 +2843,7 @@ dynamically decide whether to handle it or not.</p>
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>You must call this function when speaking is finished.</dd>
+ <dd>All of the callback event types that this voice is capable of sending.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2219,92 +2880,26 @@ dynamically decide whether to handle it or not.</p>
</dd>
</div>
- </div>
- </dl>
- </div>
-
- <!-- EXTRA PARAMETERS -->
- <div style="display: none; ">
- <h4>Extra parameters to addListener</h4>
- <dl>
- <div>
- <div>
- </div>
- </div>
- </dl>
- </div>
-
- <!-- LISTENER RETURN VALUE -->
- <h4 style="display: none; ">Listener returns</h4>
- <dl>
- <div style="display: none; ">
- <div>
- </div>
- </div>
- </dl>
-
- </div> <!-- /description -->
- </div><div class="apiItem">
- <a name="event-onStop"></a>
- <h4>onStop</h4>
-
- <div class="summary">
- <!-- Note: intentionally longer 80 columns -->
- <span class="subdued">chrome.experimental.tts.</span><span>onStop</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span><span></span>));
</div>
+ </dl>
+ </dd>
- <div class="description">
- <p class="todo" style="display: none; ">Undocumented.</p>
- <p>Fired when a call is made to tts.stop and this extension may be in the middle of speaking. If an extension receives a call to onStop and speech is already stopped, it should do nothing (not raise an error).</p>
-
- <!-- LISTENER PARAMETERS -->
- <div style="display: none; ">
- <h4>Listener parameters</h4>
- <dl>
- <div>
- <div>
- </div>
- </div>
- </dl>
- </div>
-
- <!-- EXTRA PARAMETERS -->
- <div style="display: none; ">
- <h4>Extra parameters to addListener</h4>
- <dl>
- <div>
- <div>
- </div>
- </div>
- </dl>
- </div>
-
- <!-- LISTENER RETURN VALUE -->
- <h4 style="display: none; ">Listener returns</h4>
- <dl>
- <div style="display: none; ">
- <div>
- </div>
- </div>
- </dl>
-
- </div> <!-- /description -->
- </div> <!-- /apiItem -->
-
- </div> <!-- /apiGroup -->
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
- <!-- TYPES -->
- <div class="apiGroup" style="display: none; ">
- <a name="types"></a>
- <h3 id="types">Types</h3>
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
- <!-- iterates over all types -->
- <div class="apiItem">
- <a></a>
- <h4>type name</h4>
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
- <div>
- </div>
+ </div>
</div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.ttsEngine.html b/chrome/common/extensions/docs/experimental.ttsEngine.html
new file mode 100644
index 0000000..d92354f
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.ttsEngine.html
@@ -0,0 +1,1468 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+ 1) The <head> information in this page is significant, should be uniform
+ across api docs and should be edited only with knowledge of the
+ templating mechanism.
+ 3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+ browser, it will be re-generated from the template, json schema and
+ authored overview content.
+ 4) The <body>.innerHTML is also generated by an offline step so that this
+ page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+ <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+ <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+ </script>
+ <script type="text/javascript" src="js/api_page_generator.js"></script>
+ <script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
+ <title>chrome.experimental.ttsEngine - Google Chrome Extensions - Google Code</title></head>
+ <body> <div id="gc-container" class="labs">
+ <div id="devModeWarning">
+ You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+ </div>
+ <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+ <!-- In particular, sub-templates that recurse, must be used by allowing
+ jstemplate to make a copy of the template in this section which
+ are not operated on by way of the jsskip="true" -->
+ <div style="display:none">
+
+ <!-- VALUE -->
+ <div id="valueTemplate">
+ <dt>
+ <var>paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd>
+ Description of this parameter from the json schema.
+ </dd>
+ <dd>
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd>
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd>
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd>
+ <div></div>
+ </dd>
+
+ </div> <!-- /VALUE -->
+
+ <div id="functionParametersTemplate">
+ <h5>Parameters</h5>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div> <!-- /SUBTEMPLATES -->
+
+ <a id="top"></a>
+ <div id="skipto">
+ <a href="#gc-pagecontent">Skip to page content</a>
+ <a href="#gc-toc">Skip to main navigation</a>
+ </div>
+ <!-- API HEADER -->
+ <table id="header" width="100%" cellspacing="0" border="0">
+ <tbody><tr>
+ <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+ <td valign="middle" width="100%" style="padding-left:0.6em;">
+ <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+ <div id="gsc-search-box">
+ <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+ <input type="hidden" name="ie" value="UTF-8">
+ <input type="text" name="q" value="" size="55">
+ <input class="gsc-search-button" type="submit" name="sa" value="Search">
+ <br>
+ <span class="greytext">e.g. "page action" or "tabs"</span>
+ </div>
+ </form>
+
+ <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+ <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+ </td>
+ </tr>
+ </tbody></table>
+
+ <div id="codesiteContent" class="">
+
+ <a id="gc-topnav-anchor"></a>
+ <div id="gc-topnav">
+ <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+ <ul id="home" class="gc-topnav-tabs">
+ <li id="home_link">
+ <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+ </li>
+ <li id="docs_link">
+ <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+ </li>
+ <li id="faq_link">
+ <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+ </li>
+ <li id="samples_link">
+ <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+ </li>
+ <li id="group_link">
+ <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+ </li>
+ </ul>
+ </div> <!-- end gc-topnav -->
+
+ <div class="g-section g-tpl-170">
+ <!-- SIDENAV -->
+ <div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li><a href="getstarted.html">Getting Started</a></li>
+ <li><a href="overview.html">Overview</a></li>
+ <li><a href="whats_new.html">What's New?</a></li>
+ <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+ <ul>
+ <li>Browser UI
+ <ul>
+ <li><a href="browserAction.html">Browser Actions</a></li>
+ <li><a href="contextMenus.html">Context Menus</a></li>
+ <li><a href="notifications.html">Desktop Notifications</a></li>
+ <li><a href="omnibox.html">Omnibox</a></li>
+ <li><a href="options.html">Options Pages</a></li>
+ <li><a href="override.html">Override Pages</a></li>
+ <li><a href="pageAction.html">Page Actions</a></li>
+ </ul>
+ </li>
+ <li>Browser Interaction
+ <ul>
+ <li><a href="bookmarks.html">Bookmarks</a></li>
+ <li><a href="cookies.html">Cookies</a></li>
+ <li><a href="events.html">Events</a></li>
+ <li><a href="history.html">History</a></li>
+ <li><a href="management.html">Management</a></li>
+ <li><a href="tabs.html">Tabs</a></li>
+ <li><a href="windows.html">Windows</a></li>
+ </ul>
+ </li>
+ <li>Implementation
+ <ul>
+ <li><a href="a11y.html">Accessibility</a></li>
+ <li><a href="background_pages.html">Background Pages</a></li>
+ <li><a href="content_scripts.html">Content Scripts</a></li>
+ <li><a href="xhr.html">Cross-Origin XHR</a></li>
+ <li><a href="idle.html">Idle</a></li>
+ <li><a href="i18n.html">Internationalization</a></li>
+ <li><a href="messaging.html">Message Passing</a></li>
+ <li><a href="npapi.html">NPAPI Plugins</a></li>
+ </ul>
+ </li>
+ <li>Finishing
+ <ul>
+ <li><a href="hosting.html">Hosting</a></li>
+ <li><a href="external_extensions.html">Other Deployment Options</a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+ <li><h2><a href="tutorials.html">Tutorials</a></h2>
+ <ul>
+ <li><a href="tut_debugging.html">Debugging</a></li>
+ <li><a href="tut_analytics.html">Google Analytics</a></li>
+ <li><a href="tut_oauth.html">OAuth</a></li>
+ </ul>
+ </li>
+ <li><h2>Reference</h2>
+ <ul>
+ <li>Formats
+ <ul>
+ <li><a href="manifest.html">Manifest Files</a></li>
+ <li><a href="match_patterns.html">Match Patterns</a></li>
+ </ul>
+ </li>
+ <li><a href="permission_warnings.html">Permission Warnings</a></li>
+ <li><a href="api_index.html">chrome.* APIs</a></li>
+ <li><a href="api_other.html">Other APIs</a></li>
+ </ul>
+ </li>
+ <li><h2><a href="samples.html">Samples</a></h2></li>
+ <div class="line"> </div>
+ <li><h2>More</h2>
+ <ul>
+ <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+ <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+ <li><a href="themes.html">Themes</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <script>
+ initToggles();
+ </script>
+
+ <div class="g-unit" id="gc-pagecontent">
+ <div id="pageTitle">
+ <h1 class="page_title">chrome.experimental.ttsEngine</h1>
+ </div>
+ <!-- TABLE OF CONTENTS -->
+ <div id="toc">
+ <h2>Contents</h2>
+ <ol>
+ <li>
+ <a href="#overview">Overview</a>
+ <ol>
+ <li style="display: none; ">
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li><li>
+ <a href="#manifest">Manifest</a>
+ <ol>
+ <li style="display: none; ">
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li><li>
+ <a href="#handling_speech_events">Handling Speech Events</a>
+ <ol>
+ <li style="display: none; ">
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#apiReference">API reference: chrome.experimental.ttsEngine</a>
+ <ol>
+ <li style="display: none; ">
+ <a href="#properties">Properties</a>
+ <ol>
+ <li>
+ <a href="#property-anchor">propertyName</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#global-methods">Methods</a>
+ <ol>
+ <li style="display: none; ">
+ <a href="#method-anchor">methodName</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#global-events">Events</a>
+ <ol>
+ <li style="display: none; ">
+ <a href="#event-anchor">eventName</a>
+ </li><li>
+ <a href="#event-onSpeak">onSpeak</a>
+ </li><li>
+ <a href="#event-onStop">onStop</a>
+ </li>
+ </ol>
+ </li>
+ <li style="display: none; ">
+ <a href="#types">Types</a>
+ <ol>
+ <li>
+ <a href="#id-anchor">id</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </div>
+ <!-- /TABLE OF CONTENTS -->
+
+ <!-- Standard content lead-in for experimental API pages -->
+ <p id="classSummary">
+ For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+ </p>
+
+ <!-- STATIC CONTENT PLACEHOLDER -->
+ <div id="static"><p id="classSummary">
+Use the <code>chrome.experimental.ttsEngine</code> module to
+implement a text-to-speech (TTS) engine using an extension. If your
+extension registers using this API, it will receive events containing
+the intended utterance and other parameters when any extension or packaged
+app uses the
+<a href="experimental.tts.html">experimental.tts</a>
+module to generate speech. Your extension can then use any available
+web technology to synthesize and output the speech, and send events back
+to the calling function to report the status.
+</p>
+
+<p class="note"><b>Give us feedback:</b> If you have suggestions,
+especially changes that should be made before stabilizing the first
+version of this API, please send your ideas to the
+<a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">chromium-extensions</a>
+group.</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>To enable this experimental API, visit
+<b>chrome://flags</b> and enable <b>Experimental Extension APIs</b>.
+
+</p><p>An extension can register itself as a speech engine. By doing so, it
+can intercept some or all calls to functions such as
+<a href="experimental.tts.html#method-speak"><code>speak()</code></a> and
+<a href="experimental.tts.html#method-stop"><code>stop()</code></a>
+and provide an alternate implementation.
+Extensions are free to use any available web technology
+to provide speech, including streaming audio from a server, HTML5 audio,
+Native Client, or Flash. An extension could even do something different
+with the utterances, like display closed captions in a pop-up window or
+send them as log messages to a remote server.</p>
+
+<h2 id="manifest">Manifest</h2>
+
+<p>To implement a TTS engine, an extension must first declare all voices
+it provides in the extension manifest, like this:</p>
+
+<pre>{
+ "name": "My TTS Engine",
+ "version": "1.0",
+ <b>"permissions": ["experimental"],
+ "tts_engine": {
+ "voices": [
+ {
+ "voice_name": "Alice",
+ "lang": "en-US",
+ "gender": "female",
+ "event_types": ["start", "marker", "end"]
+ },
+ {
+ "voice_name": "Pat",
+ "lang": "en-US",
+ "event_types": ["end"]
+ }
+ ]
+ },</b>
+ "background_page": "background.html",
+}</pre>
+
+<p>An extension can specify any number of voices.</p>
+
+<p>The <code>voice_name</code> parameter is required. The name should be
+descriptive enough that it identifies the name of the voice and the
+engine used. In the unlikely event that two extensions register voices
+with the same name, a client can manually specify the extension id it
+wants to do the synthesis.</p>
+
+<p>The <code>gender</code> parameter is optional. If your voice corresponds
+to a male or female voice, you can use this parameter to help clients
+choose the most appropriate voice for their application.</p>
+
+<p>The <code>lang</code> parameter is optional, but highly recommended.
+Almost always, a voice can synthesize speech in just a single language.
+When an engine supports more than one language, it can easily register a
+separate voice for each language. Under rare circumstances where a single
+voice can handle more than one language, it's easiest to just list two
+separate voices and handle them using the same logic internally. However,
+if you want to create a voice that will handle utterances in any language,
+leave out the <code>lang</code> parameter from your extension's manifest.</p>
+
+<p>Finally, the <code>event_types</code> parameter is required if the engine can
+send events to update the client on the progress of speech synthesis.
+At a minimum, supporting the <code>'end'</code> event type to indicate
+when speech is finished is highly recommend, otherwise it's impossible
+for Chrome to schedule queued utterances.</p>
+
+<p class="note">If your TTS engine does not support the <code>'end'</code>
+event type, Chrome will pass the <code>enqueue</code> option to
+onSpeak, so that your engine can implement its own queuing. However, this is
+discouraged because it means that users cannot queue utterances that get
+sent to different speech engines.</p>
+
+<p>The possible event types you can send correspond to the event types that
+the <code>speak()</code> method receives:</p>
+
+<ul>
+ <li><code>'start'</code>: the engine has started speaking the utterance.
+ </li><li><code>'word'</code>: a word boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ </li><li><code>'sentence'</code>: a sentence boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ </li><li><code>'marker'</code>: an SSML marker was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ </li><li><code>'end'</code>: the engine has finished speaking the utterance.
+ </li><li><code>'error'</code>: An engine-specific error occurred and
+ this utterance cannot be spoken.
+ Pass more information in <code>event.errorMessage</code>.
+</li></ul>
+
+<p>The <code>'interrupted'</code> and <code>'cancelled'</code> events are
+not sent by the speech engine; they are generated automatically by Chrome.</p>
+
+<p>The information about your extensions's voices from your manifest
+will be returned to any client that calls <code>getVoices</code>, assuming
+you've also registered speech event listeners as described below.</p>
+
+<h2 id="handling_speech_events">Handling Speech Events</h2>
+
+<p>To generate speech at the request of clients, your extension must
+register listeners for both <code>onSpeak</code> and <code>onStop</code>,
+like this:</p>
+
+<pre>var speakListener = function(utterance, options, sendTtsEvent) {
+ sendTtsEvent({'event_type': 'start', 'charIndex': 0})
+
+ // (start speaking)
+
+ sendTtsEvent({'event_type': 'end', 'charIndex': utterance.length})
+};
+
+var stopListener = function() {
+ // (stop all speech)
+};
+
+chrome.experimental.ttsEngine.onSpeak.addListener(speakListener);
+chrome.experimental.ttsEngine.onStop.addListener(stopListener);</pre>
+
+<p class="warning">If an extension does not register listeners for both
+<code>onSpeak</code> and <code>onStop</code>, it will not intercept any
+speech calls, regardless of what is in the manifest.</p>
+
+<p>The decision of whether or not to send a given speech request to an
+extension is based solely on whether the extension supports the given voice
+parameters in its manifest and has registered listeners
+for <code>onSpeak</code> and <code>onStop</code>. In other words,
+there's no way for an extension to receive a speech request and
+dynamically decide whether to handle it or not.</p>
+</div>
+
+ <!-- API PAGE -->
+ <div class="apiPage">
+ <a name="apiReference"></a>
+ <h2>API reference: chrome.experimental.ttsEngine</h2>
+
+ <!-- PROPERTIES -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="properties"></a>
+ <h3 id="properties">Properties</h3>
+
+ <div>
+ <a></a>
+ <h4>getLastError</h4>
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.extension</span><span>lastError</span>
+ </div>
+ <div>
+ </div>
+ </div>
+
+ </div> <!-- /apiGroup -->
+
+ <!-- METHODS -->
+ <div id="methodsTemplate" class="apiGroup">
+ <a name="global-methods"></a>
+ <h3>Methods</h3>
+
+ <!-- iterates over all functions -->
+ <div class="apiItem" style="display: none; ">
+ <a></a> <!-- method-anchor -->
+ <h4>method name</h4>
+
+ <div class="summary"><span>void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.module.methodName</span>(<span><span>, </span><span></span>
+ <var><span></span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo">Undocumented.</p>
+ <p>
+ A description from the json schema def of the function goes here.
+ </p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4>Returns</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p>
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- EVENTS -->
+ <div id="eventsTemplate" class="apiGroup">
+ <a name="global-events"></a>
+ <h3>Events</h3>
+ <!-- iterates over all events -->
+ <div class="apiItem" style="display: none; ">
+ <a></a>
+ <h4>event name</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span><span>, Type opt_param1, Type opt_param2</span>));
+ </div>
+
+ <div class="description">
+ <p class="todo">Undocumented.</p>
+ <p>
+ A description from the json schema def of the event goes here.
+ </p>
+
+ <!-- LISTENER PARAMETERS -->
+ <div>
+ <h4>Listener parameters</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- EXTRA PARAMETERS -->
+ <div>
+ <h4>Extra parameters to addListener</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- LISTENER RETURN VALUE -->
+ <h4>Listener returns</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /description -->
+ </div><div class="apiItem">
+ <a name="event-onSpeak"></a>
+ <h4>onSpeak</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.experimental.ttsEngine.</span><span>onSpeak</span><span class="subdued">.addListener</span>(function(<span>string utterance, object options, function sendTtsEvent</span>) <span class="subdued">{...}</span><span></span>));
+ </div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Called when the user makes a call to tts.speak and the options matches one of the tts_voices from this extension's manifest.</p>
+
+ <!-- LISTENER PARAMETERS -->
+ <div>
+ <h4>Listener parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>utterance</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The text to speak. This may include SSML, so if your engine does not support SSML, you should strip out all XML markup and synthesize only the underlying text content. This is guaranteed to be no more than 32,768 characters. If this engine does not support speaking that many characters at a time, the utterance should be split into smaller chunks and queued internally without returning an error.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>options</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The speak options.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>voiceName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The name of the voice to use for synthesis.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>lang</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The language to be used for synthesis, in the form <language>-<region>, e.g. en-US, en-GB, fr-CA, zh-CN, etc.</region></language></dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>gender</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span>["male", "female"]</span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Gender of voice for synthesized speech.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>rate</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>number</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Speaking rate relative to the default rate for this voice. 1.0 is the default rate, normally around 180 to 220 words per minute, 2.0 would be twice as fast, and 0.5 would be half as fast. This value is guaranteed to be between 0.1 and 10.0, inclusive. When a voice does not support this full range of rates, the actual rate should be clipped to the range that is supported without returning an error.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>pitch</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>number</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Speaking pitch between 0 and 2 inclusive, with 0 being lowest and 1 being highest, with 1.0 being the default pitch of this particular voice.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>volume</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>number</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>sendTtsEvent</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Call this function with events that occur in the process of speaking the utterance.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd>
+ <div>
+ <h5>Parameters</h5>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>event</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.tts.html#type-TtsEvent">TtsEvent</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The event from the text-to-speech engine indicating the status of this utterance.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- EXTRA PARAMETERS -->
+ <div style="display: none; ">
+ <h4>Extra parameters to addListener</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- LISTENER RETURN VALUE -->
+ <h4 style="display: none; ">Listener returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /description -->
+ </div><div class="apiItem">
+ <a name="event-onStop"></a>
+ <h4>onStop</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.experimental.ttsEngine.</span><span>onStop</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span><span></span>));
+ </div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Fired when a call is made to tts.stop and this extension may be in the middle of speaking. If an extension receives a call to onStop and speech is already stopped, it should do nothing (not raise an error).</p>
+
+ <!-- LISTENER PARAMETERS -->
+ <div style="display: none; ">
+ <h4>Listener parameters</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- EXTRA PARAMETERS -->
+ <div style="display: none; ">
+ <h4>Extra parameters to addListener</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- LISTENER RETURN VALUE -->
+ <h4 style="display: none; ">Listener returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /description -->
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- TYPES -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="types"></a>
+ <h3 id="types">Types</h3>
+
+ <!-- iterates over all types -->
+ <div class="apiItem">
+ <a></a>
+ <h4>type name</h4>
+
+ <div>
+ </div>
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ </div> <!-- /apiPage -->
+ </div> <!-- /gc-pagecontent -->
+ </div> <!-- /g-section -->
+ </div> <!-- /codesiteContent -->
+ <div id="gc-footer" --="">
+ <div class="text">
+ <p>
+ Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+ the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+ Attribution 3.0 License</a>, and code samples are licensed under the
+ <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+ </p>
+ <p>
+ ©2011 Google
+ </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+ // chrome doc tracking
+ try {
+ var engdocs = _gat._getTracker("YT-10763712-2");
+ engdocs._trackPageview();
+ } catch(err) {}
+
+ // code.google.com site-wide tracking
+ try {
+ _uacct="UA-18071-1";
+ _uanchor=1;
+ _uff=0;
+ urchinTracker();
+ }
+ catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+ </div>
+ </div> <!-- /gc-footer -->
+ </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/static/experimental.tts.html b/chrome/common/extensions/docs/static/experimental.tts.html
index fb2a772..31cc987 100644
--- a/chrome/common/extensions/docs/static/experimental.tts.html
+++ b/chrome/common/extensions/docs/static/experimental.tts.html
@@ -1,7 +1,9 @@
<p id="classSummary">
Use the <code>chrome.experimental.tts</code> module to play synthesized
-text-to-speech (TTS) from your extension or packaged app, or to register
-as a speech provider for other extensions and packaged apps that want to speak.
+text-to-speech (TTS) from your extension or packaged app.
+See also the related
+<a href="experimental.ttsEngine.html">experimental.ttsEngine</a>
+module which allows an extension to implement a speech engine.
</p>
<p class="note"><b>Give us feedback:</b> If you have suggestions,
@@ -19,7 +21,7 @@ group.</p>
5), Mac OS X, and Chrome OS, using speech synthesis capabilities
provided by the operating system. On all platforms, the user can
install extensions that register themselves as alternative speech
-synthesis providers.</p>
+engines.</p>
<h2 id="generating_speech">Generating speech</h2>
@@ -28,119 +30,160 @@ packaged app to speak. For example:</p>
<pre>chrome.experimental.tts.speak('Hello, world.');</pre>
+<p>To stop speaking immediately, just call <code>stop()</code>:
+
+<pre>chrome.experimental.tts.stop();</pre>
+
<p>You can provide options that control various properties of the speech,
such as its rate, pitch, and more. For example:</p>
-<pre>chrome.experimental.tts.speak('Hello, world.', {'rate': 0.8});</pre>
+<pre>chrome.experimental.tts.speak('Hello, world.', {'rate': 2.0});</pre>
-<p>It's also a good idea to specify the locale so that a synthesizer
+<p>It's also a good idea to specify the language so that a synthesizer
supporting that language (and regional dialect, if applicable) is chosen.</p>
<pre>chrome.experimental.tts.speak(
- 'Hello, world.',
- {
- 'locale': 'en-US',
- 'rate': 0.8
- });</pre>
-
-<p>Not all speech engines will support all options.</p>
+ 'Hello, world.', {'lang': 'en-US', 'rate': 2.0});</pre>
-<p>You can also pass a callback function that will be called when the
-speech has finished. For example, suppose we have an image on our page
-displaying a picture of a face with a closed mouth. We could open the mouth
-while speaking, and close it when done.</p>
+<p>By default, each call to <code>speak()</code> will interrupt any
+ongoing speech and speak immediately. To determine if a call would be
+interrupting anything, you can call <code>isSpeaking()</code>, or
+you can use the <code>enqueue</code> option to cause this utterance to
+be added to a queue of utterances that will be spoken when the current
+utterance has finished.
-<pre>faceImage.src = 'open_mouth.png';
+<pre>chrome.experimental.tts.speak(
+ 'Speak this first.');
chrome.experimental.tts.speak(
- 'Hello, world.', null, function() {
- faceImage.src = 'closed_mouth.png';
- });
+ 'Speak this next, when the first sentence is done.', {'enqueue': true});
</pre>
-<p>To stop speaking immediately, just call <code>stop()</code>. Call
-<code>isSpeaking()</code> to find out if a TTS engine is currently speaking.</p>
+<p>A complete description of all options can be found in the
+<a href="#method-speak">speak() method documentation</a> below.
+Not all speech engines will support all options.</p>
+
+<p>To catch errors and make sure you're calling <code>speak()</code>
+correctly, pass a callback function that takes no arguments. Inside
+the callback, check
+<a href="extension.html#property-lastError">chrome.extension.lastError</a>
+to see if there were any errors.</p>
+
+<pre>chrome.experimental.tts.speak(
+ utterance,
+ options,
+ function() {
+ if (chrome.extension.lastError) {
+ console.log('Error: ' + chrome.extension.lastError.message);
+ }
+ });</pre>
+
+<p>The callback returns right away, before the speech engine has started
+generating speech. The purpose of the callback is to alert you to syntax
+errors in your use of the TTS API, not all possible errors that might occur
+in the process of synthesizing and outputting speech. To catch these errors
+too, you need to use an event listener, described below.
+
+<h2 id="events">Listening to events</h2>
-<p>You can check to see if an error occurred by checking
-<code>chrome.extension.lastError</code> inside the callback function.</p>
+<p>To get more real-time information about the status of synthesized speech,
+pass an event listener in the options to <code>speak()</code>, like this:</p>
+
+<pre>chrome.experimental.tts.speak(
+ utterance,
+ {
+ 'onevent': function(event) {
+ console.log('Event ' + event.type ' at position ' + event.charIndex);
+ if (event.type == 'error') {
+ console.log('Error: ' + event.errorMessage);
+ }
+ }
+ },
+ callback);</pre>
+
+<p>Each event includes an event type, the character index of the current
+speech relative to the utterance, and for error events, an optional
+error message. The event types are:</p>
+
+<ul>
+ <li><code>'start'</code>: the engine has started speaking the utterance.
+ <li><code>'word'</code>: a word boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ <li><code>'sentence'</code>: a sentence boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ <li><code>'marker'</code>: an SSML marker was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ <li><code>'end'</code>: the engine has finished speaking the utterance.
+ <li><code>'interrupted'</code>: this utterance was interrupted by another
+ call to <code>speak()</code> or <code>stop()</code> and did not
+ finish.
+ <li><code>'cancelled'</code>: this utterance was queued, but then
+ cancelled by another call to <code>speak()</code> or
+ <code>stop()</code> and never began to speak at all.
+ <li><code>'error'</code>: An engine-specific error occurred and
+ this utterance cannot be spoken.
+ Check <code>event.errorMessage</code> for details.
+</ul>
+
+<p>Four of the event types, <code>'end'</code>, <code>'interrupted'</code>,
+<code>'cancelled'</code>, and <code>'error'</code>, are <i>final</i>. After
+one of those events is received, this utterance will no longer speak and
+no new events from this utterance will be received.</p>
+
+<p>Some TTS engines may not support all event types, and some may not even
+support any events at all. To require that the speech engine used sends
+the events you're interested in, you can pass a list of event types in
+the <code>requiredEventTypes</code> member of the options object, or use
+<code>getVoices</code> to choose a voice that has the events you need.
+Both are documented below.
<h2 id="ssml">SSML markup</h2>
<p>Utterances used in this API may include markup using the
<a href="http://www.w3.org/TR/speech-synthesis">Speech Synthesis Markup
-Language (SSML)</a>. For example:
+Language (SSML)</a>. If you use SSML, the first argument to
+<code>speak()</code> should be a complete SSML document with an XML
+header and a top-level <code>&lt;speak&gt;</code> tag, not a document
+fragment.
-<pre>chrome.experimental.tts.speak('The &lt;emphasis&gt;second&lt;/emphasis&gt; word of this sentence was emphasized.');</pre>
+For example:
+
+<pre>chrome.experimental.tts.speak(
+ '&lt;?xml version="1.0"?&gt;' +
+ '&lt;speak&gt;' +
+ ' The &lt;emphasis&gt;second&lt;/emphasis&gt; ' +
+ ' word of this sentence was emphasized.' +
+ '&lt;/speak&gt;');</pre>
<p>Not all speech engines will support all SSML tags, and some may not support
-SSML at all, but all engines are expected to ignore any SSML they don't
+SSML at all, but all engines are required to ignore any SSML they don't
support and still speak the underlying text.</p>
-<h2 id="provider">Implementing a speech provider</h2>
-
-<p>An extension can register itself as a speech provider. By doing so, it
-can intercept some or all calls to functions such as
-<code>speak()</code> and <code>stop()</code> and provide an alternate
-implementation. Extensions are free to use any available web technology
-to provide speech, including streaming audio from a server, HTML5 audio,
-Native Client, or Flash. An extension could even do something different
-with the utterances, like display closed captions in a pop-up window or
-send them as log messages to a remote server.</p>
-
-<p>To provide TTS, an extension must first declare all voices it provides
-in the extension manifest, like this:</p>
-
-<pre>{
- "name": "My TTS Provider",
- "version": "1.0",
- <b>"permissions": ["experimental"]
- "tts": {
- "voices": [
- {
- "voiceName": "Alice",
- "locale": "en-US",
- "gender": "female"
- },
- {
- "voiceName": "Pat",
- "locale": "en-US"
+<h2 id="choosing_voice">Choosing a voice</h2>
+
+<p>By default, Chrome will choose the most appropriate voice for each
+utterance you want to speak, based on the language and gender. On most
+Windows, Mac OS X, and Chrome OS systems, speech synthesis provided by
+the operating system should be able to speak any text in at least one
+language. Some users may have a variety of voices available, though,
+from their operating system and from speech engines implemented by other
+Chrome extensions. In those cases, you can implement custom code to choose
+the appropriate voice, or present the user with a list of choices.</p>
+
+<p>To get a list of all voices, call <code>getVoices()</code> and pass it
+a function that receives an array of <code>TtsVoice</code> objects as its
+argument:</p>
+
+<pre>chrome.experimental.tts.getVoices(
+ function(voices) {
+ for (var i = 0; i < voices.length; i++) {
+ console.log('Voice ' + i + ':');
+ console.log(' name: ' + voices[i].voiceName);
+ console.log(' lang: ' + voices[i].lang);
+ console.log(' gender: ' + voices[i].gender);
+ console.log(' extension id: ' + voices[i].extensionId);
+ console.log(' event types: ' + voices[i].eventTypes);
}
- ]
- },</b>
- "background_page": "background.html",
-}</pre>
-
-<p>An extension can specify any number of voices. The three
-parameters&mdash;<code>voiceName</code>, <code>locale</code>,
-and <code>gender</code>&mdash;are all optional. If they are all unspecified,
-the extension will handle all speech from all clients. If any of them
-are specified, they can be used to filter speech requests. For
-example, if a voice only supports French, it should set the locale to
-'fr' (or something more specific like 'fr-FR') so that only utterances
-in that locale are routed to that extension.</p>
-
-<p>To handle speech calls, the extension should register listeners
-for <code>onSpeak</code> and <code>onStop</code>, like this:</p>
-
-<pre>var speakListener = function(utterance, options, callback) {
- ...
- callback();
-};
-var stopListener = function() {
- ...
-};
-chrome.experimental.tts.onSpeak.addListener(speakListener);
-chrome.experimental.tts.onStop.addListener(stopListener);</pre>
-
-<p class="warning"><b>Important:</b> Don't forget to call the callback
-function from your speak listener!</p>
-
-<p>If an extension does not register listeners for both
-<code>onSpeak</code> and <code>onStop</code>, it will not intercept any
-speech calls, regardless of what is in the manifest.
-
-<p>The decision of whether or not to send a given speech request to an
-extension is based solely on whether the extension supports the given voice
-parameters in its manifest and has registered listeners
-for <code>onSpeak</code> and <code>onStop</code>. In other words,
-there's no way for an extension to receive a speech request and
-dynamically decide whether to handle it or not.</p>
+ });</pre>
diff --git a/chrome/common/extensions/docs/static/experimental.ttsEngine.html b/chrome/common/extensions/docs/static/experimental.ttsEngine.html
new file mode 100644
index 0000000..d7c3387
--- /dev/null
+++ b/chrome/common/extensions/docs/static/experimental.ttsEngine.html
@@ -0,0 +1,152 @@
+<p id="classSummary">
+Use the <code>chrome.experimental.ttsEngine</code> module to
+implement a text-to-speech (TTS) engine using an extension. If your
+extension registers using this API, it will receive events containing
+the intended utterance and other parameters when any extension or packaged
+app uses the
+<a href="experimental.tts.html">experimental.tts</a>
+module to generate speech. Your extension can then use any available
+web technology to synthesize and output the speech, and send events back
+to the calling function to report the status.
+</p>
+
+<p class="note"><b>Give us feedback:</b> If you have suggestions,
+especially changes that should be made before stabilizing the first
+version of this API, please send your ideas to the
+<a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">chromium-extensions</a>
+group.</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>To enable this experimental API, visit
+<b>chrome://flags</b> and enable <b>Experimental Extension APIs</b>.
+
+<p>An extension can register itself as a speech engine. By doing so, it
+can intercept some or all calls to functions such as
+<a href="experimental.tts.html#method-speak"><code>speak()</code></a> and
+<a href="experimental.tts.html#method-stop"><code>stop()</code></a>
+and provide an alternate implementation.
+Extensions are free to use any available web technology
+to provide speech, including streaming audio from a server, HTML5 audio,
+Native Client, or Flash. An extension could even do something different
+with the utterances, like display closed captions in a pop-up window or
+send them as log messages to a remote server.</p>
+
+<h2 id="manifest">Manifest</h2>
+
+<p>To implement a TTS engine, an extension must first declare all voices
+it provides in the extension manifest, like this:</p>
+
+<pre>{
+ "name": "My TTS Engine",
+ "version": "1.0",
+ <b>"permissions": ["experimental"],
+ "tts_engine": {
+ "voices": [
+ {
+ "voice_name": "Alice",
+ "lang": "en-US",
+ "gender": "female",
+ "event_types": ["start", "marker", "end"]
+ },
+ {
+ "voice_name": "Pat",
+ "lang": "en-US",
+ "event_types": ["end"]
+ }
+ ]
+ },</b>
+ "background_page": "background.html",
+}</pre>
+
+<p>An extension can specify any number of voices.</p>
+
+<p>The <code>voice_name</code> parameter is required. The name should be
+descriptive enough that it identifies the name of the voice and the
+engine used. In the unlikely event that two extensions register voices
+with the same name, a client can manually specify the extension id it
+wants to do the synthesis.</p>
+
+<p>The <code>gender</code> parameter is optional. If your voice corresponds
+to a male or female voice, you can use this parameter to help clients
+choose the most appropriate voice for their application.</p>
+
+<p>The <code>lang</code> parameter is optional, but highly recommended.
+Almost always, a voice can synthesize speech in just a single language.
+When an engine supports more than one language, it can easily register a
+separate voice for each language. Under rare circumstances where a single
+voice can handle more than one language, it's easiest to just list two
+separate voices and handle them using the same logic internally. However,
+if you want to create a voice that will handle utterances in any language,
+leave out the <code>lang</code> parameter from your extension's manifest.</p>
+
+<p>Finally, the <code>event_types</code> parameter is required if the engine can
+send events to update the client on the progress of speech synthesis.
+At a minimum, supporting the <code>'end'</code> event type to indicate
+when speech is finished is highly recommend, otherwise it's impossible
+for Chrome to schedule queued utterances.</p>
+
+<p class="note">If your TTS engine does not support the <code>'end'</code>
+event type, Chrome will pass the <code>enqueue</code> option to
+onSpeak, so that your engine can implement its own queuing. However, this is
+discouraged because it means that users cannot queue utterances that get
+sent to different speech engines.</p>
+
+<p>The possible event types you can send correspond to the event types that
+the <code>speak()</code> method receives:</p>
+
+<ul>
+ <li><code>'start'</code>: the engine has started speaking the utterance.
+ <li><code>'word'</code>: a word boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ <li><code>'sentence'</code>: a sentence boundary was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ <li><code>'marker'</code>: an SSML marker was reached. Use
+ <code>event.charIndex</code> to determine the current speech
+ position.
+ <li><code>'end'</code>: the engine has finished speaking the utterance.
+ <li><code>'error'</code>: An engine-specific error occurred and
+ this utterance cannot be spoken.
+ Pass more information in <code>event.errorMessage</code>.
+</ul>
+
+<p>The <code>'interrupted'</code> and <code>'cancelled'</code> events are
+not sent by the speech engine; they are generated automatically by Chrome.</p>
+
+<p>The information about your extensions's voices from your manifest
+will be returned to any client that calls <code>getVoices</code>, assuming
+you've also registered speech event listeners as described below.</p>
+
+<h2 id="handling_speech_events">Handling Speech Events</h2>
+
+<p>To generate speech at the request of clients, your extension must
+register listeners for both <code>onSpeak</code> and <code>onStop</code>,
+like this:</p>
+
+<pre>var speakListener = function(utterance, options, sendTtsEvent) {
+ sendTtsEvent({'event_type': 'start', 'charIndex': 0})
+
+ // (start speaking)
+
+ sendTtsEvent({'event_type': 'end', 'charIndex': utterance.length})
+};
+
+var stopListener = function() {
+ // (stop all speech)
+};
+
+chrome.experimental.ttsEngine.onSpeak.addListener(speakListener);
+chrome.experimental.ttsEngine.onStop.addListener(stopListener);</pre>
+
+<p class="warning">If an extension does not register listeners for both
+<code>onSpeak</code> and <code>onStop</code>, it will not intercept any
+speech calls, regardless of what is in the manifest.</p>
+
+<p>The decision of whether or not to send a given speech request to an
+extension is based solely on whether the extension supports the given voice
+parameters in its manifest and has registered listeners
+for <code>onSpeak</code> and <code>onStop</code>. In other words,
+there's no way for an extension to receive a speech request and
+dynamically decide whether to handle it or not.</p>
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 606ba76..d3fd98f 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -2245,9 +2245,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags,
}
// Initialize text-to-speech voices (optional).
- if (source.HasKey(keys::kTts)) {
+ if (source.HasKey(keys::kTtsEngine)) {
DictionaryValue* tts_dict = NULL;
- if (!source.GetDictionary(keys::kTts, &tts_dict)) {
+ if (!source.GetDictionary(keys::kTtsEngine, &tts_dict)) {
*error = errors::kInvalidTts;
return false;
}
@@ -2274,11 +2274,11 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags,
return false;
}
}
- if (one_tts_voice->HasKey(keys::kTtsVoicesLocale)) {
+ if (one_tts_voice->HasKey(keys::kTtsVoicesLang)) {
if (!one_tts_voice->GetString(
- keys::kTtsVoicesLocale, &voice_data.locale) ||
- !l10n_util::IsValidLocaleSyntax(voice_data.locale)) {
- *error = errors::kInvalidTtsVoicesLocale;
+ keys::kTtsVoicesLang, &voice_data.lang) ||
+ !l10n_util::IsValidLocaleSyntax(voice_data.lang)) {
+ *error = errors::kInvalidTtsVoicesLang;
return false;
}
}
@@ -2291,6 +2291,36 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags,
return false;
}
}
+ if (one_tts_voice->HasKey(keys::kTtsVoicesEventTypes)) {
+ ListValue* event_types_list;
+ if (!one_tts_voice->GetList(
+ keys::kTtsVoicesEventTypes, &event_types_list)) {
+ *error = errors::kInvalidTtsVoicesEventTypes;
+ return false;
+ }
+ for (size_t i = 0; i < event_types_list->GetSize(); i++) {
+ std::string event_type;
+ if (!event_types_list->GetString(i, &event_type)) {
+ *error = errors::kInvalidTtsVoicesEventTypes;
+ return false;
+ }
+ if (event_type != keys::kTtsVoicesEventTypeEnd &&
+ event_type != keys::kTtsVoicesEventTypeError &&
+ event_type != keys::kTtsVoicesEventTypeMarker &&
+ event_type != keys::kTtsVoicesEventTypeSentence &&
+ event_type != keys::kTtsVoicesEventTypeStart &&
+ event_type != keys::kTtsVoicesEventTypeWord) {
+ *error = errors::kInvalidTtsVoicesEventTypes;
+ return false;
+ }
+ if (voice_data.event_types.find(event_type) !=
+ voice_data.event_types.end()) {
+ *error = errors::kInvalidTtsVoicesEventTypes;
+ return false;
+ }
+ voice_data.event_types.insert(event_type);
+ }
+ }
tts_voices_.push_back(voice_data);
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 95e1be0..505bac6 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -139,8 +139,9 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
struct TtsVoice {
std::string voice_name;
- std::string locale;
+ std::string lang;
std::string gender;
+ std::set<std::string> event_types;
};
enum InitFromValueFlags {
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index 4761639..0218761 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -81,13 +81,20 @@ const char* kThemeImages = "images";
const char* kThemeTints = "tints";
const char* kToolstripPath = "path";
const char* kToolstrips = "toolstrips";
-const char* kTts = "tts";
+const char* kTtsEngine = "tts_engine";
const char* kTtsGenderFemale = "female";
const char* kTtsGenderMale = "male";
const char* kTtsVoices = "voices";
+const char* kTtsVoicesEventTypeEnd = "end";
+const char* kTtsVoicesEventTypeError = "error";
+const char* kTtsVoicesEventTypeMarker = "marker";
+const char* kTtsVoicesEventTypeSentence = "sentence";
+const char* kTtsVoicesEventTypeStart = "start";
+const char* kTtsVoicesEventTypeWord = "word";
+const char* kTtsVoicesEventTypes = "event_types";
const char* kTtsVoicesGender = "gender";
-const char* kTtsVoicesLocale = "locale";
-const char* kTtsVoicesVoiceName = "voiceName";
+const char* kTtsVoicesLang = "lang";
+const char* kTtsVoicesVoiceName = "voice_name";
const char* kType = "type";
const char* kUpdateURL = "update_url";
const char* kVersion = "version";
@@ -326,15 +333,17 @@ const char* kInvalidToolstrip =
const char* kInvalidToolstrips =
"Invalid value for 'toolstrips'.";
const char* kInvalidTts =
- "Invalid value for 'tts'.";
+ "Invalid value for 'tts_engine'.";
const char* kInvalidTtsVoices =
- "Invalid value for 'tts.voices'.";
+ "Invalid value for 'tts_engine.voices'.";
+const char* kInvalidTtsVoicesEventTypes =
+ "Invalid value for 'tts_engine.voices[*].event_types'.";
const char* kInvalidTtsVoicesGender =
- "Invalid value for 'tts.voices[*].gender'.";
-const char* kInvalidTtsVoicesLocale =
- "Invalid value for 'tts.voices[*].locale'.";
+ "Invalid value for 'tts_engine.voices[*].gender'.";
+const char* kInvalidTtsVoicesLang =
+ "Invalid value for 'tts_engine.voices[*].lang'.";
const char* kInvalidTtsVoicesVoiceName =
- "Invalid value for 'tts.voices[*].voiceName'.";
+ "Invalid value for 'tts_engine.voices[*].voice_name'.";
const char* kInvalidUpdateURL =
"Invalid value for update url: '[*]'.";
const char* kInvalidURLPatternError =
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 1fdd433..b9fd273 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -86,12 +86,19 @@ namespace extension_manifest_keys {
extern const char* kThemeTints;
extern const char* kToolstripPath;
extern const char* kToolstrips;
- extern const char* kTts;
+ extern const char* kTtsEngine;
extern const char* kTtsGenderFemale;
extern const char* kTtsGenderMale;
extern const char* kTtsVoices;
+ extern const char* kTtsVoicesEventTypeEnd;
+ extern const char* kTtsVoicesEventTypeError;
+ extern const char* kTtsVoicesEventTypeMarker;
+ extern const char* kTtsVoicesEventTypeSentence;
+ extern const char* kTtsVoicesEventTypeStart;
+ extern const char* kTtsVoicesEventTypeWord;
+ extern const char* kTtsVoicesEventTypes;
extern const char* kTtsVoicesGender;
- extern const char* kTtsVoicesLocale;
+ extern const char* kTtsVoicesLang;
extern const char* kTtsVoicesVoiceName;
extern const char* kType;
extern const char* kUpdateURL;
@@ -222,8 +229,9 @@ namespace extension_manifest_errors {
extern const char* kInvalidToolstrips;
extern const char* kInvalidTts;
extern const char* kInvalidTtsVoices;
+ extern const char* kInvalidTtsVoicesEventTypes;
extern const char* kInvalidTtsVoicesGender;
- extern const char* kInvalidTtsVoicesLocale;
+ extern const char* kInvalidTtsVoicesLang;
extern const char* kInvalidTtsVoicesVoiceName;
extern const char* kInvalidUpdateURL;
extern const char* kInvalidURLPatternError;
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index 7a7122a..1184d52 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -706,29 +706,34 @@ TEST_F(ExtensionManifestTest, DefaultLocale) {
EXPECT_EQ("de-AT", extension->default_locale());
}
-TEST_F(ExtensionManifestTest, TtsProvider) {
- LoadAndExpectError("tts_provider_invalid_1.json",
+TEST_F(ExtensionManifestTest, TtsEngine) {
+ LoadAndExpectError("tts_engine_invalid_1.json",
extension_manifest_errors::kInvalidTts);
- LoadAndExpectError("tts_provider_invalid_2.json",
+ LoadAndExpectError("tts_engine_invalid_2.json",
extension_manifest_errors::kInvalidTtsVoices);
- LoadAndExpectError("tts_provider_invalid_3.json",
+ LoadAndExpectError("tts_engine_invalid_3.json",
extension_manifest_errors::kInvalidTtsVoices);
- LoadAndExpectError("tts_provider_invalid_4.json",
+ LoadAndExpectError("tts_engine_invalid_4.json",
extension_manifest_errors::kInvalidTtsVoicesVoiceName);
- LoadAndExpectError("tts_provider_invalid_5.json",
- extension_manifest_errors::kInvalidTtsVoicesLocale);
- LoadAndExpectError("tts_provider_invalid_6.json",
- extension_manifest_errors::kInvalidTtsVoicesLocale);
- LoadAndExpectError("tts_provider_invalid_7.json",
+ LoadAndExpectError("tts_engine_invalid_5.json",
+ extension_manifest_errors::kInvalidTtsVoicesLang);
+ LoadAndExpectError("tts_engine_invalid_6.json",
+ extension_manifest_errors::kInvalidTtsVoicesLang);
+ LoadAndExpectError("tts_engine_invalid_7.json",
extension_manifest_errors::kInvalidTtsVoicesGender);
+ LoadAndExpectError("tts_engine_invalid_8.json",
+ extension_manifest_errors::kInvalidTtsVoicesEventTypes);
+ LoadAndExpectError("tts_engine_invalid_9.json",
+ extension_manifest_errors::kInvalidTtsVoicesEventTypes);
scoped_refptr<Extension> extension(
- LoadAndExpectSuccess("tts_provider_valid.json"));
+ LoadAndExpectSuccess("tts_engine_valid.json"));
ASSERT_EQ(1u, extension->tts_voices().size());
EXPECT_EQ("name", extension->tts_voices()[0].voice_name);
- EXPECT_EQ("en-US", extension->tts_voices()[0].locale);
+ EXPECT_EQ("en-US", extension->tts_voices()[0].lang);
EXPECT_EQ("female", extension->tts_voices()[0].gender);
+ EXPECT_EQ(3U, extension->tts_voices()[0].event_types.size());
}
TEST_F(ExtensionManifestTest, ForbidPortsInPermissions) {