Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Speech / Src / Synthesis / PromptBuilder.cs / 1 / PromptBuilder.cs
//------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Globalization;
using System.Speech.Internal;
using System.Speech.Internal.Synthesis;
using System.Xml;
namespace System.Speech.Synthesis
{
///
/// TODOC
///
[Serializable]
public class PromptBuilder
{
//*******************************************************************
//
// Constructors
//
//*******************************************************************
#region Constructors
///
/// TODOC
///
public PromptBuilder ()
: this (CultureInfo.CurrentUICulture)
{
}
///
/// TODOC
///
///
public PromptBuilder (CultureInfo culture)
{
Helpers.ThrowIfNull (culture, "culture");
if (culture.Equals (CultureInfo.InvariantCulture))
{
throw new ArgumentException (SR.Get (SRID.InvariantCultureInfo), "culture");
}
_culture = culture;
// Reset all value to default
ClearContent ();
}
#endregion
//********************************************************************
//
// Public Methods
//
//*******************************************************************
#region Public Methods
// Use Append* naming convention.
///
/// Clear the content of the prompt builder
///
public void ClearContent ()
{
_elements.Clear ();
_elementStack.Push (new StackElement (SsmlElement.Lexicon | SsmlElement.Meta | SsmlElement.MetaData | SsmlElement.ParagraphOrSentence | SsmlElement.AudioMarkTextWithStyle, SsmlState.Header, _culture));
}
///
/// Append Text to the SSML stream
///
///
public void AppendText (string textToSpeak)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
// Validate that text can be added in this context
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
_elements.Add (new Element (ElementType.Text, textToSpeak));
}
///
/// TODOC
///
///
///
public void AppendText (string textToSpeak, PromptRate rate)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
if (rate < PromptRate.NotSet || rate > PromptRate.ExtraSlow)
{
throw new ArgumentOutOfRangeException ("rate");
}
// Validate that text can be added in this context
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
Element prosodyElement = new Element (ElementType.Prosody, textToSpeak);
_elements.Add (prosodyElement);
string sPromptRate = null;
switch (rate)
{
case PromptRate.NotSet:
break;
case PromptRate.ExtraFast:
sPromptRate = "x-fast";
break;
case PromptRate.ExtraSlow:
sPromptRate = "x-slow";
break;
default:
sPromptRate = rate.ToString ().ToLowerInvariant ();
break;
}
if (!string.IsNullOrEmpty (sPromptRate))
{
prosodyElement._attributes = new Collection ();
prosodyElement._attributes.Add (new AttributeItem ("rate", sPromptRate));
}
}
///
/// TODOC
///
///
///
public void AppendText (string textToSpeak, PromptVolume volume)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
if (volume < PromptVolume.NotSet || volume > PromptVolume.Default)
{
throw new ArgumentOutOfRangeException ("volume");
}
// Validate that text can be added in this context
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
Element prosodyElement = new Element (ElementType.Prosody, textToSpeak);
_elements.Add (prosodyElement);
string sVolumeLevel = null;
switch (volume)
{
// No volume do not set the attribute
case PromptVolume.NotSet:
break;
case PromptVolume.ExtraSoft:
sVolumeLevel = "x-soft";
break;
case PromptVolume.ExtraLoud:
sVolumeLevel = "x-loud";
break;
default:
sVolumeLevel = volume.ToString ().ToLowerInvariant ();
break;
}
if (!string.IsNullOrEmpty (sVolumeLevel))
{
prosodyElement._attributes = new Collection ();
prosodyElement._attributes.Add (new AttributeItem ("volume", sVolumeLevel));
}
}
///
/// TODOC
///
///
///
public void AppendText (string textToSpeak, PromptEmphasis emphasis)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
if (emphasis < PromptEmphasis.NotSet || emphasis > PromptEmphasis.Reduced)
{
throw new ArgumentOutOfRangeException ("emphasis");
}
// Validate that text can be added in this context
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
Element emphasisElement = new Element (ElementType.Emphasis, textToSpeak);
_elements.Add (emphasisElement);
if (emphasis != PromptEmphasis.NotSet)
{
emphasisElement._attributes = new Collection ();
emphasisElement._attributes.Add (new AttributeItem ("level", emphasis.ToString ().ToLowerInvariant ()));
}
}
///
/// TODOC
///
///
public void StartStyle (PromptStyle style)
{
Helpers.ThrowIfNull (style, "style");
// Validate that text can be added in this context
StackElement stackElement = _elementStack.Peek ();
ValidateElement (stackElement, SsmlElement.Prosody);
// For emphasis or Prosody the list of possible elements that can be children is different.
SsmlState ssmlState = (SsmlState) 0;
SsmlElement possibleChildren = stackElement._possibleChildren;
_elements.Add (new Element (ElementType.StartStyle));
if (style.Emphasis != PromptEmphasis.NotSet)
{
Element emphasisElement = new Element (ElementType.Emphasis);
_elements.Add (emphasisElement);
emphasisElement._attributes = new Collection ();
emphasisElement._attributes.Add (new AttributeItem ("level", style.Emphasis.ToString ().ToLowerInvariant ()));
// Set the expected children and mark the element used
possibleChildren = SsmlElement.AudioMarkTextWithStyle;
ssmlState = SsmlState.StyleEmphasis;
}
if (style.Rate != PromptRate.NotSet || style.Volume != PromptVolume.NotSet)
{
// two elements add a second strart style
if (ssmlState != (SsmlState) 0)
{
_elements.Add (new Element (ElementType.StartStyle));
}
Element prosodyElement = new Element (ElementType.Prosody);
_elements.Add (prosodyElement);
if (style.Rate != PromptRate.NotSet)
{
string sPromptRate;
switch (style.Rate)
{
case PromptRate.ExtraFast:
sPromptRate = "x-fast";
break;
case PromptRate.ExtraSlow:
sPromptRate = "x-slow";
break;
default:
sPromptRate = style.Rate.ToString ().ToLowerInvariant ();
break;
}
prosodyElement._attributes = new Collection ();
prosodyElement._attributes.Add (new AttributeItem ("rate", sPromptRate));
}
if (style.Volume != PromptVolume.NotSet)
{
string sVolumeLevel;
switch (style.Volume)
{
case PromptVolume.ExtraSoft:
sVolumeLevel = "x-soft";
break;
case PromptVolume.ExtraLoud:
sVolumeLevel = "x-loud";
break;
default:
sVolumeLevel = style.Volume.ToString ().ToLowerInvariant ();
break;
}
if (prosodyElement._attributes == null)
{
prosodyElement._attributes = new Collection ();
}
prosodyElement._attributes.Add (new AttributeItem ("volume", sVolumeLevel));
}
// Set the expected children and mark the element used
possibleChildren = SsmlElement.ParagraphOrSentence | SsmlElement.AudioMarkTextWithStyle;
ssmlState |= SsmlState.StyleProsody;
}
_elementStack.Push (new StackElement (possibleChildren, ssmlState, stackElement._culture));
}
///
/// TODOC
///
public void EndStyle ()
{
StackElement stackElement = _elementStack.Pop ();
if (stackElement._state != 0)
{
if ((stackElement._state & (SsmlState.StyleEmphasis | SsmlState.StyleProsody)) == 0)
{
throw new InvalidOperationException (SR.Get (SRID.PromptBuilderMismatchStyle));
}
_elements.Add (new Element (ElementType.EndStyle));
// Check if 2 xml elements have been created
if (stackElement._state == (SsmlState.StyleEmphasis | SsmlState.StyleProsody))
{
_elements.Add (new Element (ElementType.EndStyle));
}
}
}
///
/// TODOC [voice]
///
///
public void StartVoice (VoiceInfo voice)
{
Helpers.ThrowIfNull (voice, "voice");
if (!VoiceInfo.ValidateGender (voice.Gender))
{
throw new ArgumentException (SR.Get (SRID.EnumInvalid, "VoiceGender"), "voice");
}
if (!VoiceInfo.ValidateAge (voice.Age))
{
throw new ArgumentException (SR.Get (SRID.EnumInvalid, "VoiceAge"), "voice");
}
StackElement stackElement = _elementStack.Peek ();
ValidateElement (stackElement, SsmlElement.Voice);
CultureInfo culture = voice.Culture == null ? stackElement._culture : voice.Culture;
Element startVoice = new Element (ElementType.StartVoice);
startVoice._attributes = new Collection ();
_elements.Add (startVoice);
if (!string.IsNullOrEmpty (voice.Name))
{
startVoice._attributes.Add (new AttributeItem ("name", voice.Name));
}
if (voice.Culture != null)
{
startVoice._attributes.Add (new AttributeItem ("xml", "lang", voice.Culture.Name));
}
if (voice.Gender != VoiceGender.NotSet)
{
startVoice._attributes.Add (new AttributeItem ("gender", voice.Gender.ToString ().ToLowerInvariant ()));
}
if (voice.Age != VoiceAge.NotSet)
{
startVoice._attributes.Add (new AttributeItem ("age", ((int) voice.Age).ToString (CultureInfo.InvariantCulture)));
}
if (voice.Variant >= 0)
{
startVoice._attributes.Add (new AttributeItem ("variant", ((int) voice.Variant).ToString (CultureInfo.InvariantCulture)));
}
_elementStack.Push (new StackElement (SsmlElement.Sentence | SsmlElement.AudioMarkTextWithStyle, SsmlState.Voice, culture));
}
///
/// TODOC [voice]
///
///
public void StartVoice (string name)
{
Helpers.ThrowIfEmptyOrNull (name, "name");
StartVoice (new VoiceInfo (name));
}
///
/// TODOC [voice]
///
///
public void StartVoice (VoiceGender gender)
{
StartVoice (new VoiceInfo (gender));
}
///
/// TODOC [voice]
///
///
///
public void StartVoice (VoiceGender gender, VoiceAge age)
{
StartVoice (new VoiceInfo (gender, age));
}
///
/// TODOC [voice]
///
///
///
///
public void StartVoice (VoiceGender gender, VoiceAge age, int voiceAlternate)
{
StartVoice (new VoiceInfo (gender, age, voiceAlternate));
}
///
/// TODOC [voice]
///
///
public void StartVoice (CultureInfo culture)
{
StartVoice (new VoiceInfo (culture));
}
///
/// TODOC
///
public void EndVoice ()
{
if (_elementStack.Pop ()._state != SsmlState.Voice)
{
throw new InvalidOperationException (SR.Get (SRID.PromptBuilderMismatchVoice));
}
_elements.Add (new Element (ElementType.EndVoice));
}
// ,
///
/// TODOC
///
public void StartParagraph ()
{
StartParagraph (null);
}
///
/// TODOC
///
public void StartParagraph (CultureInfo culture)
{
// check for well formed document
StackElement stackElement = _elementStack.Peek ();
ValidateElement (stackElement, SsmlElement.Paragraph);
Element startParagraph = new Element (ElementType.StartParagraph);
_elements.Add (startParagraph);
if (culture != null)
{
if (culture.Equals (CultureInfo.InvariantCulture))
{
throw new ArgumentException (SR.Get (SRID.InvariantCultureInfo), "culture");
}
startParagraph._attributes = new Collection ();
startParagraph._attributes.Add (new AttributeItem ("xml", "lang", culture.Name));
}
else
{
culture = stackElement._culture;
}
_elementStack.Push (new StackElement (SsmlElement.AudioMarkTextWithStyle | SsmlElement.Sentence, SsmlState.Paragraph, culture));
}
///
/// TODOC
///
public void EndParagraph ()
{
if (_elementStack.Pop ()._state != SsmlState.Paragraph)
{
throw new InvalidOperationException (SR.Get (SRID.PromptBuilderMismatchParagraph));
}
_elements.Add (new Element (ElementType.EndParagraph));
}
///
/// TODOC
///
public void StartSentence ()
{
StartSentence (null);
}
///
/// TODOC
///
public void StartSentence (CultureInfo culture)
{
// check for well formed document
StackElement stackElement = _elementStack.Peek ();
ValidateElement (stackElement, SsmlElement.Sentence);
Element startSentence = new Element (ElementType.StartSentence);
_elements.Add (startSentence);
if (culture != null)
{
if (culture.Equals (CultureInfo.InvariantCulture))
{
throw new ArgumentException (SR.Get (SRID.InvariantCultureInfo), "culture");
}
startSentence._attributes = new Collection ();
startSentence._attributes.Add (new AttributeItem ("xml", "lang", culture.Name));
}
else
{
culture = stackElement._culture;
}
_elementStack.Push (new StackElement (SsmlElement.AudioMarkTextWithStyle, SsmlState.Sentence, culture));
}
///
/// TODOC
///
public void EndSentence ()
{
if (_elementStack.Pop ()._state != SsmlState.Sentence)
{
throw new InvalidOperationException (SR.Get (SRID.PromptBuilderMismatchSentence));
}
_elements.Add (new Element (ElementType.EndSentence));
}
///
/// TODOC - [say-as]
///
///
///
public void AppendTextWithHint (string textToSpeak, SayAs sayAs)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
if (sayAs < SayAs.SpellOut || sayAs > SayAs.Text)
{
throw new ArgumentOutOfRangeException ("sayAs");
}
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
if (sayAs != SayAs.Text)
{
Element sayAsElement = new Element (ElementType.SayAs, textToSpeak);
_elements.Add (sayAsElement);
sayAsElement._attributes = new Collection ();
string sInterpretAs = null;
string sFormat = null;
switch (sayAs)
{
case SayAs.SpellOut:
sInterpretAs = "characters";
break;
case SayAs.NumberOrdinal:
sInterpretAs = "ordinal";
break;
case SayAs.NumberCardinal:
sInterpretAs = "cardinal";
break;
case SayAs.Date:
sInterpretAs = "date";
break;
case SayAs.DayMonthYear:
sInterpretAs = "date";
sFormat = "dmy";
break;
case SayAs.MonthDayYear:
sInterpretAs = "date";
sFormat = "mdy";
break;
case SayAs.YearMonthDay:
sInterpretAs = "date";
sFormat = "ymd";
break;
case SayAs.YearMonth:
sInterpretAs = "date";
sFormat = "ym";
break;
case SayAs.MonthYear:
sInterpretAs = "date";
sFormat = "my";
break;
case SayAs.MonthDay:
sInterpretAs = "date";
sFormat = "md";
break;
case SayAs.DayMonth:
sInterpretAs = "date";
sFormat = "dm";
break;
case SayAs.Year:
sInterpretAs = "date";
sFormat = "y";
break;
case SayAs.Month:
sInterpretAs = "date";
sFormat = "m";
break;
case SayAs.Day:
sInterpretAs = "date";
sFormat = "d";
break;
case SayAs.Time:
sInterpretAs = "time";
break;
case SayAs.Time24:
sInterpretAs = "time";
sFormat = "hms24";
break;
case SayAs.Time12:
sInterpretAs = "time";
sFormat = "hms12";
break;
case SayAs.Telephone:
sInterpretAs = "telephone";
break;
#if SPEECHSERVER
case SayAs.Currency:
sInterpretAs = "currency";
break;
#endif
}
sayAsElement._attributes.Add (new AttributeItem ("interpret-as", sInterpretAs));
if (!string.IsNullOrEmpty (sFormat))
{
sayAsElement._attributes.Add (new AttributeItem ("format", sFormat));
}
}
else
{
AppendText (textToSpeak);
}
}
///
/// TODOC - [say-as]
///
///
///
public void AppendTextWithHint (string textToSpeak, string sayAs)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
Helpers.ThrowIfEmptyOrNull (sayAs, "sayAs");
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
Element sayAsElement = new Element (ElementType.SayAs, textToSpeak);
_elements.Add (sayAsElement);
sayAsElement._attributes = new Collection ();
sayAsElement._attributes.Add (new AttributeItem ("interpret-as", sayAs));
}
///
/// TODOC - [phoneme]
///
///
///
public void AppendTextWithPronunciation (string textToSpeak, string pronunciation)
{
Helpers.ThrowIfEmptyOrNull (textToSpeak, "textToSpeak");
Helpers.ThrowIfEmptyOrNull (pronunciation, "pronunciation");
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
// validate the pronunciation
PhonemeConverter.ValidateUpsIds (pronunciation);
Element phoneElement = new Element (ElementType.Phoneme, textToSpeak);
_elements.Add (phoneElement);
phoneElement._attributes = new Collection ();
phoneElement._attributes.Add (new AttributeItem ("ph", pronunciation));
}
///
/// TODOC - [sub]
///
///
///
public void AppendTextWithAlias (string textToSpeak, string substitute)
{
Helpers.ThrowIfNull (textToSpeak, "textToSpeak");
Helpers.ThrowIfNull (substitute, "substitute");
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Text);
Element subElement = new Element (ElementType.Sub, textToSpeak);
_elements.Add (subElement);
subElement._attributes = new Collection ();
subElement._attributes.Add (new AttributeItem ("alias", substitute));
}
///
/// TODOC
///
public void AppendBreak ()
{
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Break);
_elements.Add (new Element (ElementType.Break));
}
///
/// TODOC
///
///
public void AppendBreak (PromptBreak strength)
{
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Break);
Element breakElement = new Element (ElementType.Break);
_elements.Add (breakElement);
string sBreak = null;
switch (strength)
{
case PromptBreak.None:
sBreak = "none";
break;
case PromptBreak.ExtraSmall:
sBreak = "x-weak";
break;
case PromptBreak.Small:
sBreak = "weak";
break;
case PromptBreak.Medium:
sBreak = "medium";
break;
case PromptBreak.Large:
sBreak = "strong";
break;
case PromptBreak.ExtraLarge:
sBreak = "x-strong";
break;
default:
throw new ArgumentNullException ("strength");
}
breakElement._attributes = new Collection ();
breakElement._attributes.Add (new AttributeItem ("strength", sBreak));
}
///
/// TODOC
///
///
public void AppendBreak (TimeSpan duration)
{
// check for well formed document
ValidateElement (_elementStack.Peek (), SsmlElement.Break);
if (duration.Ticks < 0)
{
throw new ArgumentOutOfRangeException ("duration");
}
Element breakElement = new Element (ElementType.Break);
_elements.Add (breakElement);
breakElement._attributes = new Collection ();
breakElement._attributes.Add (new AttributeItem ("time", duration.TotalMilliseconds + "ms"));
}
//