def getPreInitSettings(cls) -> SupportedSettingType:
		"""Get settings that can be configured before the provider is initialized.
		This is a class method because it does not rely on any instance state in this class.
		"""
		return [
			driverHandler.BooleanDriverSetting(
				"shouldDoX",  # value stored in matching property name on class
				"Should Do X",
				defaultVal=True
			),
			driverHandler.BooleanDriverSetting(
				"shouldDoY",  # value stored in matching property name on class
				"Should Do Y",
				defaultVal=False
			),
			driverHandler.NumericDriverSetting(
				"amountOfZ",  # value stored in matching property name on class
				"Amount of Z",
				defaultVal=11
			),
			driverHandler.DriverSetting(
				# options for this come from a property with name generated by
				# f"available{settingID.capitalize()}s"
				# Note:
				#   First letter of Id becomes capital, the rest lowercase.
				#   the 's' character on the end.
				# result: 'availableNameofsomethings'
				"nameOfSomething",  # value stored in matching property name on class
				"Name of something",
			)
		]
예제 #2
0
	def VolumeSetting(cls,minStep=1):
		"""Factory function for creating volume setting."""
		# Translators: Label for a setting in voice settings dialog.
		return driverHandler.NumericDriverSetting("volume",_("V&olume"),minStep=minStep,normalStep=5,availableInSettingsRing=True,

		# Translators: Label for a setting in synth settings ring.
		displayName=pgettext('synth setting','Volume'))
 def InflectionSetting(cls, minStep=1):
     """Factory function for creating inflection setting."""
     # Translators: Label for a setting in voice settings dialog.
     return driverHandler.NumericDriverSetting(
         "inflection",
         _("&Inflection"),
         minStep=minStep,
         availableInSettingsRing=True,
         # Translators: Label for a setting in synth settings ring.
         displayName=pgettext('synth setting', 'Inflection'))
	def _getAvailableRuntimeSettings(self) -> SupportedSettingType:
		settings = []
		if self._hasFeature("runtimeOnlySetting_externalValueLoad"):
			settings.extend([
				driverHandler.NumericDriverSetting(
					"runtimeOnlySetting_externalValueLoad",  # value stored in matching property name on class
					"Runtime Only amount, external value load",
					# no GUI default
				),
			])
		if self._hasFeature("runtimeOnlySetting_localDefault"):
			settings.extend([
				driverHandler.NumericDriverSetting(
					"runtimeOnlySetting_localDefault",  # value stored in matching property name on class
					"Runtime Only amount, local default",
					defaultVal=50,
				),
			])
		return settings
예제 #5
0
 def PitchSetting(cls, minStep=1):
     """Factory function for creating pitch setting."""
     return driverHandler.NumericDriverSetting(
         "pitch",
         # Translators: Label for a setting in voice settings dialog.
         _("&Pitch"),
         minStep=minStep,
         availableInSettingsRing=True,
         # Translators: Label for a setting in synth settings ring.
         displayName=pgettext('synth setting', 'Pitch'),
     )
예제 #6
0
class SynthDriver(SynthDriver):
    name = "WorldVoiceXVED2"
    description = "WorldVoice(VE)"
    supportedSettings = [
        SynthDriver.VoiceSetting(),
        # SynthDriver.VariantSetting(),
        SynthDriver.RateSetting(),
        SynthDriver.PitchSetting(),
        SynthDriver.VolumeSetting(),
        driverHandler.DriverSetting(
            "numlan",
            # Translators: Label for a setting in voice settings dialog.
            _("Number &Language"),
            availableInSettingsRing=True,
            defaultVal="default",
            # Translators: Label for a setting in synth settings ring.
            displayName=_("Number Language"),
        ),
        driverHandler.DriverSetting(
            "nummod",
            # Translators: Label for a setting in voice settings dialog.
            _("Number &Mode"),
            availableInSettingsRing=True,
            defaultVal="value",
            # Translators: Label for a setting in synth settings ring.
            displayName=_("Number Mode"),
        ),
        driverHandler.NumericDriverSetting(
            "chinesespace",
            # Translators: Label for a setting in voice settings dialog.
            _("Pause time when encountering spaces between Chinese"),
            defaultVal=0,
            minStep=1,
        ),
        driverHandler.BooleanDriverSetting(
            "cni",
            _("Ignore comma between number"),
            defaultVal=False,
        ),
        driverHandler.BooleanDriverSetting(
            "dli",
            _("Ignore language information of document"),
            defaultVal=False,
        ),
        driverHandler.BooleanDriverSetting(
            "uwv",
            _("Enable WorldVoice setting rules to detect text language"),
            availableInSettingsRing=True,
            defaultVal=True,
            displayName=_("Enable WorldVoice rules"),
        ),
    ]
    supportedCommands = {
        speech.IndexCommand,
        speech.CharacterModeCommand,
        speech.LangChangeCommand,
        speech.BreakCommand,
        speech.PitchCommand,
        speech.RateCommand,
        speech.VolumeCommand,
    }
    supportedNotifications = {synthIndexReached, synthDoneSpeaking}

    @classmethod
    def check(cls):
        with _vocalizer.preOpenVocalizer() as check:
            return check

    def __init__(self):
        _config.load()
        # Initialize the driver
        try:
            _vocalizer.initialize(self._onIndexReached)
            log.debug("Vocalizer info: %s" % self._info())
        except _vocalizer.VeError as e:
            if e.code == _vocalizer.VAUTONVDA_ERROR_INVALID:
                log.info("Vocalizer license for NVDA is Invalid")
            elif e.code == _vocalizer.VAUTONVDA_ERROR_DEMO_EXPIRED:
                log.info("Vocalizer demo license for NVDA as expired.")
            raise
        self._voiceManager = VoiceManager()

        self._realSpeakFunc = speech.speak
        self._realSpellingFunc = speech.speakSpelling
        speech.speak = self.patchedSpeak
        speech.speakSpelling = self.patchedSpeakSpelling

        speechSymbols = SpeechSymbols()
        speechSymbols.load('unicode.dic')
        self._languageDetector = languageDetection.LanguageDetector(
            list(self._voiceManager.languages), speechSymbols)

        speech._speakWithoutPauses = speech.SpeechWithoutPauses(
            speakFunc=self.patchedSpeak)
        speech.speakWithoutPauses = speech._speakWithoutPauses.speakWithoutPauses

        self._localeToVoices = self._voiceManager.localeToVoicesMap
        self._locales = sorted([
            l for l in self._localeToVoices if len(self._localeToVoices[l]) > 0
        ])
        self._localeNames = list(
            map(self._getLocaleReadableName, self._locales))

        self._voice = None

    def _onIndexReached(self, index):
        if index is not None:
            synthIndexReached.notify(synth=self, index=index)
        else:
            synthDoneSpeaking.notify(synth=self)

    def terminate(self):
        speech.speak = self._realSpeakFunc
        speech.speakSpelling = self._realSpellingFunc

        speech._speakWithoutPauses = speech.SpeechWithoutPauses(
            speakFunc=speech.speak)
        speech.speakWithoutPauses = speech._speakWithoutPauses.speakWithoutPauses

        try:
            self.cancel()
            self._voiceManager.close()
            _vocalizer.terminate()
        except RuntimeError:
            log.error("Vocalizer terminate", exc_info=True)

    def speak(self, speechSequence):
        if self.uwv \
         and _config.vocalizerConfig['autoLanguageSwitching']['useUnicodeLanguageDetection'] \
         and _config.vocalizerConfig['autoLanguageSwitching']['afterSymbolDetection']:
            speechSequence = self._languageDetector.add_detected_language_commands(
                speechSequence)
            speechSequence = list(speechSequence)
        speechSequence = self.patchedNumSpeechSequence(speechSequence)
        speechSequence = self.patchedSpaceSpeechSequence(speechSequence)

        currentInstance = defaultInstance = self._voiceManager.defaultVoiceInstance.token
        currentLanguage = defaultLanguage = self.language
        chunks = []
        hasText = False
        charMode = False
        for command in speechSequence:
            if isinstance(command, str):
                command = command.strip()
                if not command:
                    continue
                # If character mode is on use lower case characters
                # Because the synth does not allow to turn off the caps reporting
                if charMode or len(command) == 1:
                    command = command.lower()
                # replace the excape character since it is used for parameter changing
                chunks.append(command.replace("\x1b", ""))
                hasText = True
            elif isinstance(command, speech.IndexCommand):
                chunks.append("\x1b\\mrk=%d\\" % command.index)
            elif isinstance(command, speech.BreakCommand):
                maxTime = 6553 if self.variant == "bet2" else 65535
                breakTime = max(1, min(command.time, maxTime))
                self._speak(currentInstance, chunks)
                chunks = []
                hasText = False
                _vocalizer.processBreak(currentInstance, breakTime)
            elif isinstance(command, speech.CharacterModeCommand):
                charMode = command.state
                s = "\x1b\\tn=spell\\" if command.state else "\x1b\\tn=normal\\"
                chunks.append(s)
            elif isinstance(command, speech.LangChangeCommand) or isinstance(
                    command, speechcommand.WVLangChangeCommand):
                if command.lang == currentLanguage:
                    # Keep on the same voice.
                    continue
                if command.lang is None:
                    # No language, use default.
                    currentInstance = defaultInstance
                    currentLanguage = defaultLanguage
                    continue
                # Changed language, lets see what we have.
                currentLanguage = command.lang
                newVoiceName = self._voiceManager.getVoiceNameForLanguage(
                    currentLanguage)
                if newVoiceName is None:
                    # No voice for this language, use default.
                    newInstance = defaultInstance
                else:
                    newInstance = self._voiceManager.getVoiceInstance(
                        newVoiceName).token
                if newInstance == currentInstance:
                    # Same voice, next command.
                    continue
                if hasText:  # We changed voice, send text we already have to vocalizer.
                    self._speak(currentInstance, chunks)
                    chunks = []
                    hasText = False
                currentInstance = newInstance
            elif isinstance(command, speech.PitchCommand):
                pitch = self._voiceManager.getVoiceParameter(
                    currentInstance, _vocalizer.VE_PARAM_PITCH, type_=int)
                pitchOffset = self._percentToParam(
                    command.offset, _vocalizer.PITCH_MIN,
                    _vocalizer.PITCH_MAX) - _vocalizer.PITCH_MIN
                chunks.append("\x1b\\pitch=%d\\" % (pitch + pitchOffset))
            elif isinstance(command, speechcommand.SplitCommand):
                self._speak(currentInstance, chunks)
                chunks = []
                hasText = False
        if chunks:
            self._speak(currentInstance, chunks)

    def _speak(self, voiceInstance, chunks):
        text = speech.CHUNK_SEPARATOR.join(chunks).replace("  \x1b", "\x1b")
        _vocalizer.processText2Speech(voiceInstance, text)

    def patchedSpeak(self, speechSequence, symbolLevel=None, priority=None):
        if self._cni:
            temp = []
            for command in speechSequence:
                if isinstance(command, str):
                    temp.append(comma_number_pattern.sub(
                        lambda m: '', command))
                else:
                    temp.append(command)
            speechSequence = temp
        if self._dli:
            speechSequence = self.patchedRemoveLangChangeCommandSpeechSequence(
                speechSequence)
        if self.uwv \
         and _config.vocalizerConfig['autoLanguageSwitching']['useUnicodeLanguageDetection'] \
         and not _config.vocalizerConfig['autoLanguageSwitching']['afterSymbolDetection']:
            speechSequence = self._languageDetector.add_detected_language_commands(
                speechSequence)
            speechSequence = list(speechSequence)
        self._realSpeakFunc(speechSequence, symbolLevel, priority=priority)

    def patchedSpeakSpelling(self,
                             text,
                             locale=None,
                             useCharacterDescriptions=False,
                             priority=None):
        if config.conf["speech"]["autoLanguageSwitching"] \
         and _config.vocalizerConfig['autoLanguageSwitching']['useUnicodeLanguageDetection'] \
         and config.conf["speech"]["trustVoiceLanguage"]:
            for text, loc in self._languageDetector.process_for_spelling(
                    text, locale):
                self._realSpellingFunc(text,
                                       loc,
                                       useCharacterDescriptions,
                                       priority=priority)
        else:
            self._realSpellingFunc(text,
                                   locale,
                                   useCharacterDescriptions,
                                   priority=priority)

    def cancel(self):
        _vocalizer.stop()

    def pause(self, switch):
        if switch:
            _vocalizer.pause()
        else:
            _vocalizer.resume()

    def _get_volume(self):
        return self._voiceManager.defaultVoiceInstance.volume

    def _set_volume(self, value):
        self._voiceManager.defaultVoiceInstance.volume = value
        self._voiceManager.defaultVoiceInstance.commit()

    def _get_rate(self):
        return self._voiceManager.defaultVoiceInstance.rate

    def _set_rate(self, value):
        self._voiceManager.defaultVoiceInstance.rate = value
        self._voiceManager.defaultVoiceInstance.commit()

    def _get_pitch(self):
        return self._voiceManager.defaultVoiceInstance.pitch

    def _set_pitch(self, value):
        self._voiceManager.defaultVoiceInstance.pitch = value
        self._voiceManager.defaultVoiceInstance.commit()

    def _getAvailableVoices(self):
        return self._voiceManager.voiceInfos

    def _get_voice(self):
        if self._voice is None:
            voice = self._voiceManager.getVoiceNameForLanguage(
                languageHandler.getLanguage())
            if voice is None:
                voice = list(self.availableVoices.keys())[0]
            return voice
        return self._voiceManager.defaultVoiceName

    def _set_voice(self, voiceName):
        self._voice = voiceName
        if voiceName == self._voiceManager.defaultVoiceName:
            return
        # Stop speech before setting a new voice to avoid voice instances
        # continuing speaking when changing voices for, e.g., say-all
        # See NVDA ticket #3540
        _vocalizer.stop()
        self._voiceManager.setDefaultVoice(voiceName)
        # Available variants are cached by default. As variants maybe different for each voice remove the cached value
        # if hasattr(self, '_availableVariants'):
        # del self._availableVariants
        # Synchronize with the synth so the parameters
        # we report are not from the previous voice.
        # _vocalizer.sync()

    def _get_variant(self):
        return self._voiceManager.defaultVoiceInstance.variant

    def _set_variant(self, name):
        self.cancel()
        self._voiceManager.defaultVoiceInstance.variant = name

    def _getAvailableVariants(self):
        dbs = self._voiceManager.defaultVoiceInstance.variants
        return OrderedDict([(d, VoiceInfo(d, d)) for d in dbs])

    def _get_availableLanguages(self):
        return self._voiceManager.languages

    def _get_language(self):
        return self._voiceManager.getVoiceLanguage()

    def _info(self):
        s = [self.description]
        return ", ".join(s)

    def _get_availableNumlans(self):
        return dict(
            {
                "default":
                driverHandler.StringParameterInfo("default", _("default")),
            }, **{
                locale: driverHandler.StringParameterInfo(locale, name)
                for locale, name in zip(self._locales, self._localeNames)
            })

    def _get_numlan(self):
        return self._numlan

    def _set_numlan(self, value):
        self._numlan = value

    def _get_availableNummods(self):
        return dict({
            "value":
            driverHandler.StringParameterInfo("value", _("value")),
            "number":
            driverHandler.StringParameterInfo("number", _("number")),
        })

    def _get_nummod(self):
        return self._nummod

    def _set_nummod(self, value):
        self._nummod = value

    def _get_chinesespace(self):
        return self._chinesespace

    def _set_chinesespace(self, value):
        self._chinesespace = value

    def _get_cni(self):
        return self._cni

    def _set_cni(self, value):
        self._cni = value

    def _get_dli(self):
        return self._dli

    def _set_dli(self, value):
        self._dli = value

    def patchedNumSpeechSequence(self, speechSequence):
        return self.coercionNumberLangChange(speechSequence, self._numlan,
                                             self._nummod)

    def patchedSpaceSpeechSequence(self, speechSequence):
        if not int(self._chinesespace) == 0:
            joinString = ""
            tempSpeechSequence = []
            for command in speechSequence:
                if not isinstance(command, str):
                    tempSpeechSequence.append(joinString)
                    tempSpeechSequence.append(command)
                    joinString = ""
                else:
                    joinString += command
            tempSpeechSequence.append(joinString)
            speechSequence = tempSpeechSequence

            tempSpeechSequence = []
            for command in speechSequence:
                if isinstance(command, str):
                    result = re.split(chinese_space_pattern, command)
                    if len(result) == 1:
                        tempSpeechSequence.append(command)
                    else:
                        temp = []
                        for i in result:
                            temp.append(i)
                            temp.append(
                                speech.BreakCommand(
                                    int(self._chinesespace) * 5))
                        temp = temp[:-1]
                        tempSpeechSequence += temp
                else:
                    tempSpeechSequence.append(command)
            speechSequence = tempSpeechSequence
        return speechSequence

    def patchedRemoveLangChangeCommandSpeechSequence(self, speechSequence):
        result = []
        for command in speechSequence:
            if not isinstance(command, speech.LangChangeCommand):
                result.append(command)
        return result

    def patchedLengthSpeechSequence(self, speechSequence):
        result = []
        for command in speechSequence:
            if isinstance(command, str):
                result.extend(self.lengthsplit(command, 100))
            else:
                result.append(command)
        return result

    def lengthsplit(self, string, length):
        result = []
        pattern = re.compile(r"[\s]")
        spaces = pattern.findall(string)
        others = pattern.split(string)
        fragment = ""
        for other, space in zip(others, spaces):
            fragment += other + space
            if len(fragment) > length:
                result.append(fragment)
                result.append(speechcommand.SplitCommand())
                fragment = ""
        fragment += others[-1]
        result.append(fragment)
        return result

    def resplit(self, pattern, string, mode):
        result = []
        numbers = pattern.findall(string)
        others = pattern.split(string)
        for other, number in zip(others, numbers):
            if mode == 'value':
                result.extend([
                    other,
                    speech.LangChangeCommand('StartNumber'), number,
                    speech.LangChangeCommand('EndNumber')
                ])
            elif mode == 'number':
                result.extend([
                    other,
                    speech.LangChangeCommand('StartNumber'),
                    ' '.join(number).replace(" . ", "."),
                    speech.LangChangeCommand('EndNumber')
                ])
        result.append(others[-1])
        return result

    def coercionNumberLangChange(self, speechSequence, numberLanguage, mode):
        result = []
        for command in speechSequence:
            if isinstance(command, str):
                result.extend(self.resplit(number_pattern, command, mode))
            else:
                result.append(command)

        currentLang = self.language
        for command in result:
            if isinstance(command, speech.LangChangeCommand):
                if command.lang == 'StartNumber':
                    command.lang = numberLanguage
                elif command.lang == 'EndNumber':
                    command.lang = currentLang
                else:
                    currentLang = command.lang
        return result

    def _getLocaleReadableName(self, locale):
        description = languageHandler.getLanguageDescription(locale)
        return "%s" % (description) if description else locale
예제 #7
0
class SynthDriver(synthDriverHandler.SynthDriver):
    supportedSettings = (SynthDriver.VoiceSetting(),
                         SynthDriver.VariantSetting(),
                         SynthDriver.RateSetting(), SynthDriver.PitchSetting(),
                         SynthDriver.InflectionSetting(),
                         SynthDriver.VolumeSetting(),
                         driverHandler.NumericDriverSetting(
                             "hsz", "Head Size"),
                         driverHandler.NumericDriverSetting(
                             "rgh", "Roughness"),
                         driverHandler.NumericDriverSetting(
                             "bth", "Breathiness"),
                         driverHandler.BooleanDriverSetting(
                             "backquoteVoiceTags",
                             "Enable backquote voice &tags", True))
    supportedCommands = {
        speech.IndexCommand,
        speech.CharacterModeCommand,
        speech.LangChangeCommand,
        speech.BreakCommand,
        speech.PitchCommand,
        speech.RateCommand,
        speech.VolumeCommand,
        speech.PhonemeCommand,
    }
    supportedNotifications = {synthIndexReached, synthDoneSpeaking}
    PROSODY_ATTRS = {
        speech.PitchCommand: _eloquence.pitch,
        speech.VolumeCommand: _eloquence.vlm,
        speech.RateCommand: _eloquence.rate,
    }

    description = 'ETI-Eloquence'
    name = 'eloquence'

    @classmethod
    def check(cls):
        return _eloquence.eciCheck()

    def __init__(self):
        _eloquence.initialize(self._onIndexReached)
        self.curvoice = "enu"
        self.rate = 50
        self.variant = "1"

    def speak(self, speechSequence):
        last = None
        outlist = []
        for item in speechSequence:
            if isinstance(item, str):
                s = str(item)
                s = self.xspeakText(s)
                outlist.append((_eloquence.speak, (s, )))
                last = s
            elif isinstance(item, speech.IndexCommand):
                outlist.append((_eloquence.index, (item.index, )))
            elif isinstance(item, speech.BreakCommand):
                # Eloquence doesn't respect delay time in milliseconds.
                # Therefor we need to adjust waiting time depending on curernt speech rate
                # The following table of adjustments has been measured empirically
                # Then we do linear approximation
                coefficients = {
                    10: 1,
                    43: 2,
                    60: 3,
                    75: 4,
                    85: 5,
                }
                ck = sorted(coefficients.keys())
                if self.rate <= ck[0]:
                    factor = coefficients[ck[0]]
                elif self.rate >= ck[-1]:
                    factor = coefficients[ck[-1]]
                elif self.rate in ck:
                    factor = coefficients[self.rate]
                else:
                    li = [
                        index for index, r in enumerate(ck) if r < self.rate
                    ][-1]
                    ri = li + 1
                    ra = ck[li]
                    rb = ck[ri]
                    factor = 1.0 * coefficients[ra] + (
                        coefficients[rb] - coefficients[ra]) * (self.rate -
                                                                ra) / (rb - ra)
                pFactor = factor * item.time
                pFactor = int(pFactor)
                outlist.append((_eloquence.speak, (f'`p{pFactor}.', )))
            elif type(item) in self.PROSODY_ATTRS:
                pr = self.PROSODY_ATTRS[type(item)]
                if item.multiplier == 1:
                    # Revert back to defaults
                    outlist.append((_eloquence.cmdProsody, (
                        pr,
                        None,
                    )))
                else:
                    outlist.append((_eloquence.cmdProsody, (
                        pr,
                        item.multiplier,
                    )))
        if last is not None and not last.rstrip()[-1] in punctuation:
            outlist.append((_eloquence.speak, ('`p1.', )))
        outlist.append((_eloquence.index, (0xffff, )))
        outlist.append((_eloquence.synth, ()))
        _eloquence.synth_queue.put(outlist)
        _eloquence.process()

    def xspeakText(self, text, should_pause=False):
        if _eloquence.params[9] == 65536 or _eloquence.params[9] == 65537:
            text = resub(english_fixes, text)
        if _eloquence.params[9] == 131072 or _eloquence.params[9] == 131073:
            text = resub(spanish_fixes, text)
        if _eloquence.params[9] in (196609, 196608):
            text = resub(french_fixes, text)
        #this converts to ansi for anticrash. If this breaks with foreign langs, we can remove it.
        #text = text.encode('mbcs')
        text = normalizeText(text)
        text = resub(anticrash_res, text)
        if not self._backquoteVoiceTags:
            text = text.replace('`', ' ')
        text = "`pp0 `vv%d %s" % (self.getVParam(_eloquence.vlm), text
                                  )  #no embedded commands
        text = pause_re.sub(r'\1 `p1\2\3', text)
        text = time_re.sub(r'\1:\2 \3', text)
        #if two strings are sent separately, pause between them. This might fix some of the audio issues we're having.
        if should_pause:
            text = text + ' `p1.'
        return text
        #  _eloquence.speak(text, index)

        # def cancel(self):
        #  self.dll.eciStop(self.handle)

    def pause(self, switch):
        _eloquence.pause(switch)
        #  self.dll.eciPause(self.handle,switch)

    def terminate(self):
        _eloquence.terminate()

    _backquoteVoiceTags = False

    def _get_backquoteVoiceTags(self):
        return self._backquoteVoiceTags

    def _set_backquoteVoiceTags(self, enable):
        if enable == self._backquoteVoiceTags:
            return
        self._backquoteVoiceTags = enable

    def _get_rate(self):
        return self._paramToPercent(self.getVParam(_eloquence.rate), minRate,
                                    maxRate)

    def _set_rate(self, vl):
        self._rate = self._percentToParam(vl, minRate, maxRate)
        self.setVParam(_eloquence.rate,
                       self._percentToParam(vl, minRate, maxRate))

    def _get_pitch(self):
        return self.getVParam(_eloquence.pitch)

    def _set_pitch(self, vl):
        self.setVParam(_eloquence.pitch, vl)

    def _get_volume(self):
        return self.getVParam(_eloquence.vlm)

    def _set_volume(self, vl):
        self.setVParam(_eloquence.vlm, int(vl))

    def _set_inflection(self, vl):
        vl = int(vl)
        self.setVParam(_eloquence.fluctuation, vl)

    def _get_inflection(self):
        return self.getVParam(_eloquence.fluctuation)

    def _set_hsz(self, vl):
        vl = int(vl)
        self.setVParam(_eloquence.hsz, vl)

    def _get_hsz(self):
        return self.getVParam(_eloquence.hsz)

    def _set_rgh(self, vl):
        vl = int(vl)
        self.setVParam(_eloquence.rgh, vl)

    def _get_rgh(self):
        return self.getVParam(_eloquence.rgh)

    def _set_bth(self, vl):
        vl = int(vl)
        self.setVParam(_eloquence.bth, vl)

    def _get_bth(self):
        return self.getVParam(_eloquence.bth)

    def _getAvailableVoices(self):
        o = OrderedDict()
        for name in os.listdir(_eloquence.eciPath[:-8]):
            if not name.lower().endswith('.syn'): continue
            info = _eloquence.langs[name.lower()[:-4]]
            o[str(info[0])] = synthDriverHandler.VoiceInfo(
                str(info[0]), info[1], None)
        return o

    def _get_voice(self):
        return str(_eloquence.params[9])

    def _set_voice(self, vl):
        _eloquence.set_voice(vl)
        self.curvoice = vl

    def getVParam(self, pr):
        return _eloquence.getVParam(pr)

    def setVParam(self, pr, vl):
        _eloquence.setVParam(pr, vl)

    def _get_lastIndex(self):
        #fix?
        return _eloquence.lastindex

    def cancel(self):
        _eloquence.stop()

    def _getAvailableVariants(self):

        global variants
        return OrderedDict(
            (str(id), synthDriverHandler.VoiceInfo(str(id), name))
            for id, name in variants.items())

    def _set_variant(self, v):
        global variants
        self._variant = v if int(v) in variants else "1"
        _eloquence.setVariant(int(v))
        self.setVParam(_eloquence.rate, self._rate)
        #  if 'eloquence' in config.conf['speech']:
        #   config.conf['speech']['eloquence']['pitch'] = self.pitch

    def _get_variant(self):
        return self._variant

    def _onIndexReached(self, index):
        if index is not None:
            synthIndexReached.notify(synth=self, index=index)
        else:
            synthDoneSpeaking.notify(synth=self)