Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate import of Commands directly from speech module in favour of speech.commands #12126

Merged
merged 6 commits into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/mathPres/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def getSpeechForMathMl(self, mathMl):
@param mathMl: The MathML markup.
@type mathMl: str
@return: A speech sequence.
@rtype: List[str, speech.SpeechCommand]
@rtype: List[str, SpeechCommand]
"""
raise NotImplementedError

Expand Down
30 changes: 19 additions & 11 deletions source/mathPres/mathPlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
import braille
import mathPres

from speech.commands import (
PitchCommand,
VolumeCommand,
RateCommand,
LangChangeCommand,
BreakCommand,
CharacterModeCommand,
PhonemeCommand,
)

RE_MP_SPEECH = re.compile(
# Break.
r"<break time='(?P<break>\d+)ms'/> ?"
Expand All @@ -35,9 +45,9 @@
# Actual content.
r"|(?P<content>[^<,]+)")
PROSODY_COMMANDS = {
"pitch": speech.PitchCommand,
"volume": speech.VolumeCommand,
"rate": speech.RateCommand,
"pitch": PitchCommand,
"volume": VolumeCommand,
"rate": RateCommand,
}
def _processMpSpeech(text, language):
# MathPlayer's default rate is 180 wpm.
Expand All @@ -47,16 +57,15 @@ def _processMpSpeech(text, language):
breakMulti = 180.0 / wpm
out = []
if language:
out.append(speech.LangChangeCommand(language))
out.append(LangChangeCommand(language))
resetProsody = set()
for m in RE_MP_SPEECH.finditer(text):
if m.lastgroup == "break":
out.append(speech.BreakCommand(time=int(m.group("break")) * breakMulti))
out.append(BreakCommand(time=int(m.group("break")) * breakMulti))
elif m.lastgroup == "char":
out.extend((speech.CharacterModeCommand(True),
m.group("char"), speech.CharacterModeCommand(False)))
out.extend((CharacterModeCommand(True), m.group("char"), CharacterModeCommand(False)))
elif m.lastgroup == "comma":
out.append(speech.BreakCommand(time=100))
out.append(BreakCommand(time=100))
elif m.lastgroup in PROSODY_COMMANDS:
command = PROSODY_COMMANDS[m.lastgroup]
out.append(command(multiplier=int(m.group(m.lastgroup)) / 100.0))
Expand All @@ -66,12 +75,11 @@ def _processMpSpeech(text, language):
out.append(command(multiplier=1))
resetProsody.clear()
elif m.lastgroup == "phonemeText":
out.append(speech.PhonemeCommand(m.group("ipa"),
text=m.group("phonemeText")))
out.append(PhonemeCommand(m.group("ipa"), text=m.group("phonemeText")))
elif m.lastgroup == "content":
out.append(m.group(0))
if language:
out.append(speech.LangChangeCommand(None))
out.append(LangChangeCommand(None))
return out

class MathPlayerInteraction(mathPres.MathInteractionNVDAObject):
Expand Down
16 changes: 9 additions & 7 deletions source/sayAllHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import queueHandler
import winKernel

from speech.commands import CallbackCommand, EndUtteranceCommand

CURSOR_CARET = 0
CURSOR_REVIEW = 1

Expand Down Expand Up @@ -69,7 +71,7 @@ def next(self):
if not obj:
return
# Call this method again when we start speaking this object.
callbackCommand = speech.CallbackCommand(self.next, name="say-all:next")
callbackCommand = CallbackCommand(self.next, name="say-all:next")
speech.speakObject(obj, reason=controlTypes.OutputReason.SAYALL, _prefixSpeechCommand=callbackCommand)

def stop(self):
Expand Down Expand Up @@ -148,8 +150,8 @@ def nextLine(self):
# No more text.
if isinstance(self.reader.obj, textInfos.DocumentWithPageTurns):
# Once the last line finishes reading, try turning the page.
cb = speech.CallbackCommand(self.turnPage, name="say-all:turnPage")
speech.speakWithoutPauses([cb, speech.EndUtteranceCommand()])
cb = CallbackCommand(self.turnPage, name="say-all:turnPage")
speech.speakWithoutPauses([cb, EndUtteranceCommand()])
else:
self.finish()
return
Expand All @@ -163,7 +165,7 @@ def nextLine(self):
def _onLineReached(obj=self.reader.obj, state=state):
self.lineReached(obj, bookmark, state)

cb = speech.CallbackCommand(
cb = CallbackCommand(
_onLineReached,
name="say-all:lineReached"
)
Expand Down Expand Up @@ -239,11 +241,11 @@ def finish(self):
# Otherwise, if a different synth is being used for say all,
# we might switch synths too early and truncate the final speech.
# We do this by putting a CallbackCommand at the start of a new utterance.
cb = speech.CallbackCommand(self.stop, name="say-all:stop")
cb = CallbackCommand(self.stop, name="say-all:stop")
speech.speakWithoutPauses([
speech.EndUtteranceCommand(),
EndUtteranceCommand(),
cb,
speech.EndUtteranceCommand()
EndUtteranceCommand()
])

def stop(self):
Expand Down
20 changes: 1 addition & 19 deletions source/speech/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,7 @@
EndUtteranceCommand,
CharacterModeCommand,
)
from .commands import ( # noqa: F401
# F401 imported but unused:
# The following are imported here because other files that speech.py
# previously relied on "import * from .commands"
# New commands added to commands.py should be directly imported only where needed.
# Usage of these imports is deprecated and will be removed in 2021.1
SynthCommand,
IndexCommand,
SynthParamCommand,
BreakCommand,
BaseProsodyCommand,
VolumeCommand,
RateCommand,
PhonemeCommand,
BaseCallbackCommand,
CallbackCommand,
WaveFileCommand,
ConfigProfileTriggerCommand,
)

from . import types
from .types import (
SpeechSequence,
Expand Down
20 changes: 1 addition & 19 deletions source/speech/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,7 @@
IndexCommand,
_CancellableSpeechCommand,
)
from .commands import ( # noqa: F401
# F401 imported but unused:
# These are imported explicitly to maintain backwards compatibility and will be removed in
# 2021.1. Rather than rely on these imports, import directly from the commands module.
# New commands added to commands.py should be directly imported only where needed.
SpeechCommand,
PitchCommand,
LangChangeCommand,
BeepCommand,
CharacterModeCommand,
SynthCommand,
BreakCommand,
BaseProsodyCommand,
VolumeCommand,
RateCommand,
PhonemeCommand,
CallbackCommand,
WaveFileCommand,
)

from .priorities import Spri, SPEECH_PRIORITIES
from logHandler import log
from synthDriverHandler import getSynth
Expand Down
5 changes: 3 additions & 2 deletions source/speechXml.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from collections import namedtuple, OrderedDict
import re
import speech
from speech.commands import SpeechCommand
from logHandler import log

XML_ESCAPES = {
Expand Down Expand Up @@ -196,7 +197,7 @@ class SpeechXmlConverter(object):
Subclasses implement specific XML schemas by implementing methods which convert each speech command.
The method for a speech command should be named with the prefix "convert" followed by the command's class name.
For example, the handler for C{IndexCommand} should be named C{convertIndexCommand}.
These methods receive the L{speech.SpeechCommand} instance as their only argument.
These methods receive the L{SpeechCommand} instance as their only argument.
They should return an appropriate XmlBalancer command.
Subclasses may wish to extend L{generateBalancerCommands}
to produce additional XmlBalancer commands at the start or end;
Expand All @@ -210,7 +211,7 @@ def generateBalancerCommands(self, speechSequence):
for item in speechSequence:
if isinstance(item, str):
yield item
elif isinstance(item, speech.SpeechCommand):
elif isinstance(item, SpeechCommand):
name = type(item).__name__
# For example: self.convertIndexCommand
func = getattr(self, "convert%s" % name, None)
Expand Down
4 changes: 2 additions & 2 deletions source/synthDriverHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class SynthDriver(driverHandler.Driver):
e.g. the L{voice} attribute is used for the L{voice} setting.
These will usually be properties.
L{supportedCommands} should specify what synth commands the synthesizer supports.
At a minimum, L{speech.IndexCommand} must be supported.
At a minimum, L{IndexCommand} must be supported.
L{PitchCommand} must also be supported if you want capital pitch change to work;
support for the pitch setting is not sufficient.
L{supportedNotifications} should specify what notifications the synthesizer provides.
Expand Down Expand Up @@ -93,7 +93,7 @@ class SynthDriver(driverHandler.Driver):
#: @type: str
description = ""
#: The speech commands supported by the synth.
#: @type: set of L{speech.SynthCommand} subclasses.
#: @type: set of L{SynthCommand} subclasses.
supportedCommands = frozenset()
#: The notifications provided by the synth.
#: @type: set of L{extensionPoints.Action} instances
Expand Down
43 changes: 27 additions & 16 deletions source/synthDrivers/espeak.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@
from logHandler import log
from driverHandler import BooleanDriverSetting

from speech.commands import (
IndexCommand,
CharacterModeCommand,
LangChangeCommand,
BreakCommand,
PitchCommand,
RateCommand,
VolumeCommand,
PhonemeCommand,
)

class SynthDriver(SynthDriver):
name = "espeak"
description = "eSpeak NG"
Expand All @@ -29,14 +40,14 @@ class SynthDriver(SynthDriver):
SynthDriver.VolumeSetting(),
)
supportedCommands = {
speech.IndexCommand,
speech.CharacterModeCommand,
speech.LangChangeCommand,
speech.BreakCommand,
speech.PitchCommand,
speech.RateCommand,
speech.VolumeCommand,
speech.PhonemeCommand,
IndexCommand,
CharacterModeCommand,
LangChangeCommand,
BreakCommand,
PitchCommand,
RateCommand,
VolumeCommand,
PhonemeCommand,
}
supportedNotifications = {synthIndexReached, synthDoneSpeaking}

Expand All @@ -60,9 +71,9 @@ def _get_language(self):
return self._language

PROSODY_ATTRS = {
speech.PitchCommand: "pitch",
speech.VolumeCommand: "volume",
speech.RateCommand: "rate",
PitchCommand: "pitch",
VolumeCommand: "volume",
RateCommand: "rate",
}

IPA_TO_ESPEAK = {
Expand Down Expand Up @@ -91,16 +102,16 @@ def speak(self,speechSequence):
for item in speechSequence:
if isinstance(item,str):
textList.append(self._processText(item))
elif isinstance(item,speech.IndexCommand):
elif isinstance(item, IndexCommand):
textList.append("<mark name=\"%d\" />"%item.index)
elif isinstance(item,speech.CharacterModeCommand):
elif isinstance(item, CharacterModeCommand):
textList.append("<say-as interpret-as=\"characters\">" if item.state else "</say-as>")
elif isinstance(item,speech.LangChangeCommand):
elif isinstance(item, LangChangeCommand):
if langChanged:
textList.append("</voice>")
textList.append("<voice xml:lang=\"%s\">"%(item.lang if item.lang else defaultLanguage).replace('_','-'))
langChanged=True
elif isinstance(item,speech.BreakCommand):
elif isinstance(item, BreakCommand):
textList.append('<break time="%dms" />' % item.time)
elif type(item) in self.PROSODY_ATTRS:
if prosody:
Expand All @@ -121,7 +132,7 @@ def speak(self,speechSequence):
for attr,val in prosody.items():
textList.append(' %s="%d%%"'%(attr,val))
textList.append(">")
elif isinstance(item,speech.PhonemeCommand):
elif isinstance(item, PhonemeCommand):
# We can't use str.translate because we want to reject unknown characters.
try:
phonemes="".join([self.IPA_TO_ESPEAK[char] for char in item.ipa])
Expand Down
33 changes: 22 additions & 11 deletions source/synthDrivers/oneCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@
import winVersion
import NVDAHelper

from speech.commands import (
IndexCommand,
CharacterModeCommand,
LangChangeCommand,
BreakCommand,
PitchCommand,
RateCommand,
VolumeCommand,
PhonemeCommand,
)

#: The number of 100-nanosecond units in 1 second.
HUNDRED_NS_PER_SEC = 10000000 # 1000000000 ns per sec / 100 ns
ocSpeech_Callback = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_int, ctypes.c_wchar_p)
Expand Down Expand Up @@ -78,9 +89,9 @@ def generateBalancerCommands(self, speechSequence):
yield next(commands)
# OneCore didn't provide a way to set base prosody values before API version 5.
# Therefore, the base values need to be set using SSML.
yield self.convertRateCommand(speech.RateCommand(multiplier=1))
yield self.convertVolumeCommand(speech.VolumeCommand(multiplier=1))
yield self.convertPitchCommand(speech.PitchCommand(multiplier=1))
yield self.convertRateCommand(RateCommand(multiplier=1))
yield self.convertVolumeCommand(VolumeCommand(multiplier=1))
yield self.convertPitchCommand(PitchCommand(multiplier=1))
for command in commands:
yield command

Expand All @@ -105,14 +116,14 @@ class SynthDriver(SynthDriver):
# Translators: Description for a speech synthesizer.
description = _("Windows OneCore voices")
supportedCommands = {
speech.IndexCommand,
speech.CharacterModeCommand,
speech.LangChangeCommand,
speech.BreakCommand,
speech.PitchCommand,
speech.RateCommand,
speech.VolumeCommand,
speech.PhonemeCommand,
IndexCommand,
CharacterModeCommand,
LangChangeCommand,
BreakCommand,
PitchCommand,
RateCommand,
VolumeCommand,
PhonemeCommand,
}
supportedNotifications = {synthIndexReached, synthDoneSpeaking}

Expand Down
9 changes: 5 additions & 4 deletions source/synthDrivers/sapi4.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import nvwave
import weakref

from speech.commands import IndexCommand, SpeechCommand, CharacterModeCommand

class SynthDriverBufSink(COMObject):
_com_interfaces_ = [ITTSBufNotifySink]
Expand Down Expand Up @@ -96,16 +97,16 @@ def speak(self,speechSequence):
for item in speechSequence:
if isinstance(item,str):
textList.append(item.replace('\\','\\\\'))
elif isinstance(item,speech.IndexCommand):
elif isinstance(item, IndexCommand):
textList.append("\\mrk=%d\\"%item.index)
elif isinstance(item,speech.CharacterModeCommand):
elif isinstance(item, CharacterModeCommand):
textList.append("\\RmS=1\\" if item.state else "\\RmS=0\\")
charMode=item.state
elif isinstance(item,speech.SpeechCommand):
elif isinstance(item, SpeechCommand):
log.debugWarning("Unsupported speech command: %s"%item)
else:
log.error("Unknown speech: %s"%item)
if isinstance(item,speech.IndexCommand):
if isinstance(item, IndexCommand):
# This is the index denoting the end of the speech sequence.
self._finalIndex=item.index
if charMode:
Expand Down
Loading