~kf5jwc/garretts

0667fe68c828f6992226a28126fba8cd2b457629 — Kyle Jones 1 year, 4 months ago 06f25cc
A readme!
2 files changed, 97 insertions(+), 13 deletions(-)

M garretts/__init__.py
A readme.md
M garretts/__init__.py => garretts/__init__.py +0 -13
@@ 1,19 1,6 @@
"""GarreTTS is a TTS synthesizer which uses plugin-provided synthesizers.

It is my first attempt to use Qt5 and plugins.

You can make plugins for it, so it can use your preferred synthesizer.
(I'm so sorry, there aren't docs for that yet. If you want to read
synthesizer.py and plugin_errors.py, they have the logic in them.)
I use `gather` (by way of garretts.Plugin and the gather
entrypoint) to do plugins. I expect to hand you a string and to get
back BinaryIO in a format Qt5 can play (MP3 is probably safe).

You can use `PluginFile` to request a path to your expected file. I
do not ensure that it exists or that its contents are appropriate.

If your plugin has an error, you should catch it and raise a PluginError
for the user to read. Uncaught errors will crash the program.
"""

import gather as _gather

A readme.md => readme.md +97 -0
@@ 0,0 1,97 @@
# GarreTTS

GarreTTS is a TTS synthesizer which uses plugin-provided synthesizers.
You can make plugins for it, so it can use your preferred synthesizer.

This project is my first attempt to use Qt5 and plugins.

## Making a plugin

Plugins have a very simple interface. You provide a function which
accepts a string of text to be synthesized. You should return the
binary contents of an audio file in whatever format you like (though
MP3 is likely to be the most compatible).

```python
def my_synthesizer(user_text: str) -> BinaryIO:
	...
```

Plugins are registered with a decorator you can import from this
package (`garretts.Plugin` and `@Plugin.register()`) using `gather`.
`...register(name=...)` allows you to provide a custom name, if you
like.

```python
from garretts import Plugin

@Plugin.register(name="My very fancy Mario voice")
def my_synthesizer(user_text: str) -> BinaryIO:
	...
```

### Accessing persistent files

The only method for asking a user for input is via files.

The package provides a way to store and access any file/data you may
need. `garretts.plugin_file(file: str)` accepts the name of your
file and hands you a `pathlib.Path` to its expected location. I do
not ensure that it exists or that its contents are appropriate.

```python
from garretts import plugin_file

PEACH = "another_castle.txt"

@Plugin.register(name="My very fancy Mario voice")
def my_synthesizer(user_text: str) -> BinaryIO:
	peach_file = plugin_file(PEACH)
	...
```

### Requesting data from the user

This package provides a `garretts.PluginFileMissing` exception which
can be raised when you need to be given some data. Its arguments
include the name of the file, a prompt to be shown to the user, and a
caption for the file picker window. The user will be shown your prompt
before being asked to pick their file.

```python
from garretts import PluginFileMissing

...
	if not peach_file.exists():
		user_prompt = "You must tell me which castle peach is in!"
		picker_caption = "Which castle?"
		raise PluginFileMissing(PEACH, user_prompt, picker_caption)
	...
```

When you raise this error, it will cancel the current synthesizer
attempt. After selecting a file, the user will try synthesizing again.

### Invalid data

If you need to "refresh" a file, or have data which is no longer
valid, you *should* use `PluginFileMissing` to prompt the user for a
new version. The currently existing file will be overwritten.

### Plugin errors

This package provides a `garretts.PluginError`. If your plugin has an
error, you should catch it and raise a PluginError for the user to
read. Uncaught errors will be presented to the user and then crash
the program.

```python
from garretts import PluginError

...
	try:
		scary_operation()
	except ScaryOperationFailure as e:
		raise PluginError(e.message)
	...
```