JoystickGremlin icon indicating copy to clipboard operation
JoystickGremlin copied to clipboard

Feature Request: Add Voice Selector for TTS in Options

Open VegaAntares opened this issue 4 years ago • 4 comments

Hello and first of all, thanks for your fantastic job on this software. The voice of TTS is "random" among installed voice on windows. Actually this not "random", this is the first voice(item 0) from the list returned by the GetVoices() method of the SAPI com object. The idea would be to add the voice via the Voice property of the SAPI object (self._speak) in tts.py. The change should be pretty minor in the code and there would be a bit more work to adapt the option dialog to have a listbox listing voice. These can be obtained by parsing the list returned by the method GetVoices() and call GetDescription() to get a stringified id. This string Id then can be used to lookup back the voice object to set the attribute. I wanted to do it myself but for some reason I do not succeed to run gremlin_joystick ("script execution failed" runtime error) once all "compiled" without error (Python 3.6 32bit, pywin32, pyQT5, pyinstaller and pypiwin32) Thanks a lot for all your work.

VegaAntares avatar Feb 22 '21 01:02 VegaAntares

The thing is I have Cortana and Ivona doing a pretty good job for TTS but Joystick Gremlin keeps using the awfull Microsoft Zira that makes my ears bleeding.... Reading on previous posts that you were planning to move to Python39 64 bits ? That is Great news because my compilation issues are hard to fix since I am not sure of the version you are using and 3.6 is pretty deprecated now. Furthermore there is in your release msi a lot of Microsoft api dll that my compiled release does not have (copying did not solved my problem)

VegaAntares avatar Feb 22 '21 01:02 VegaAntares

Packaging things with pyinstaller is kind of a pain, and the releases I made were always done in a Windows 7 VM as that ensures all these dlls that you mention would be packaged as well. As the version I'm working on at the moment is effectively breaking everything that existed anyways I also used it as an excuse to change various libraries and versions since I didn't need to worry about breaking more than intended.

As for the actual feature addition of exposing available voices. That's definitely something that would be a good addition, the whole TTS action mostly has been neglected since I implemented the initial version. Part of it was that all I personally ever use it for is saying one word here and there and that a lot of other things stole priority from it. Depending on how I decide to reimplement all the actions I might work the changes into the action at that point.

WhiteMagic avatar Feb 22 '21 13:02 WhiteMagic

Thanks a lot for your reply. Since I've manager to make the installed code to work. Actually I was missing a dependency to reportlab and you should update the readme file accordingly. Still I have trouble with antivirus that detects joystick Gremlin as a virus, how do you manage to workaround the issue with your own msi ? Second issue is that It needs to be run with admin rights because of the debug.txt file created in the installation folder. Your msi also does not have this issue. So I will add the feature myself and submit the changes to you trying to respect your framework so I may save a bit of work to you. If you have interest, I will try to work for a plugin addon for Elite Dangerous offering access to API if user want to check some ship state to validate a command.

VegaAntares avatar Feb 22 '21 13:02 VegaAntares

Actually I made it as set of default options located in a specific tab in the Options dialog. Then I enriched the Text-To-Speech action to allow overrides of all the defaults.

I did large changes in tts.py to fix the issue of rapid successive calls of the speak() SAPI function, like several Text-To-Speech in the same container, were each cancelling previous ones. Actually when you modify the Voice/Volume/Speed/Output Stream, it only reads the last input. Tried just in case but with low hopes, to set the object static, to avoid GC or having distinct instance of the SAPI.SpVoice Interface. Your versions does not have this problem because it runs with constant settings.

The only working simple workaround would have been to set a time.sleep() of at least 0.3s witch wouldn't be accetable because it would have blocked the action thread this long too. So I simply implemented the TTS as dedicated thread where you can queue your TTS request that will be played synchronously and therefore performance remains optimal for event handlings.

I made it in a stand alone Python installation on a branch of 13.3, So I will do a proper GIT cloning, merge with the main trunk, clean the code and submit soon a pull request so your can keep focus on your major changes.

VegaAntares avatar Feb 24 '21 23:02 VegaAntares