diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/tts.google/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/tts.google/index.scss
new file mode 120000
index 00000000..867ef5c6
--- /dev/null
+++ b/platypush/backend/http/static/css/source/webpanel/plugins/tts.google/index.scss
@@ -0,0 +1 @@
+../tts/index.scss
\ No newline at end of file
diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/tts/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/tts/index.scss
new file mode 100644
index 00000000..ed059b99
--- /dev/null
+++ b/platypush/backend/http/static/css/source/webpanel/plugins/tts/index.scss
@@ -0,0 +1,32 @@
+@import 'common/vars';
+
+.tts-container {
+ max-width: 80rem;
+ min-height: 10rem;
+ margin: 3rem auto;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: $default-border-2;
+ border-radius: 3rem;
+
+ form {
+ margin: 0;
+ width: 90%;
+
+ input[type=text] {
+ width: 100%;
+ }
+
+ button {
+ border-radius: 5rem;
+ }
+
+ input, button {
+ &:hover {
+ border-color: $default-hover-fg;
+ }
+ }
+ }
+}
+
diff --git a/platypush/backend/http/static/js/plugins/tts.google/index.js b/platypush/backend/http/static/js/plugins/tts.google/index.js
new file mode 100644
index 00000000..b9a16866
--- /dev/null
+++ b/platypush/backend/http/static/js/plugins/tts.google/index.js
@@ -0,0 +1,26 @@
+Vue.component('tts-google', {
+ template: '#tmpl-tts-google',
+ data: function() {
+ return {
+ talking: false,
+ };
+ },
+
+ methods: {
+ talk: async function(event) {
+ event.preventDefault();
+
+ const args = [...event.target.querySelectorAll('input')].reduce((obj, el) => {
+ if (el.value.length)
+ obj[el.name] = el.value;
+ return obj;
+ }, {});
+
+ this.talking = true;
+ await request('tts.google.say', args);
+ this.talking = false;
+ },
+ },
+});
+
+
diff --git a/platypush/backend/http/static/js/plugins/tts/index.js b/platypush/backend/http/static/js/plugins/tts/index.js
new file mode 100644
index 00000000..6a8ee794
--- /dev/null
+++ b/platypush/backend/http/static/js/plugins/tts/index.js
@@ -0,0 +1,25 @@
+Vue.component('tts', {
+ template: '#tmpl-tts',
+ data: function() {
+ return {
+ talking: false,
+ };
+ },
+
+ methods: {
+ talk: async function(event) {
+ event.preventDefault();
+
+ const args = [...event.target.querySelectorAll('input')].reduce((obj, el) => {
+ if (el.value.length)
+ obj[el.name] = el.value;
+ return obj;
+ }, {});
+
+ this.talking = true;
+ await request('tts.say', args);
+ this.talking = false;
+ },
+ },
+});
+
diff --git a/platypush/backend/http/templates/plugins/music.mpd.html b/platypush/backend/http/templates/plugins/music.mpd.html
deleted file mode 100644
index fbf79a9b..00000000
--- a/platypush/backend/http/templates/plugins/music.mpd.html
+++ /dev/null
@@ -1,181 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Artist
-
Title
-
Album
-
Time
-
-
-
-
-
-
-
-
-
- No media is being played
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/platypush/backend/http/templates/plugins/music.snapcast.html b/platypush/backend/http/templates/plugins/music.snapcast.html
deleted file mode 100644
index 2aedf352..00000000
--- a/platypush/backend/http/templates/plugins/music.snapcast.html
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/platypush/backend/http/templates/plugins/tts.google.html b/platypush/backend/http/templates/plugins/tts.google.html
deleted file mode 100644
index 8e2829c0..00000000
--- a/platypush/backend/http/templates/plugins/tts.google.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
diff --git a/platypush/backend/http/templates/plugins/tts.google/index.html b/platypush/backend/http/templates/plugins/tts.google/index.html
new file mode 100644
index 00000000..e08192d4
--- /dev/null
+++ b/platypush/backend/http/templates/plugins/tts.google/index.html
@@ -0,0 +1,4 @@
+
+
diff --git a/platypush/backend/http/templates/plugins/tts.html b/platypush/backend/http/templates/plugins/tts.html
deleted file mode 100644
index 9d00b9fb..00000000
--- a/platypush/backend/http/templates/plugins/tts.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
diff --git a/platypush/backend/http/templates/plugins/tts/common.html b/platypush/backend/http/templates/plugins/tts/common.html
new file mode 100644
index 00000000..823e2eef
--- /dev/null
+++ b/platypush/backend/http/templates/plugins/tts/common.html
@@ -0,0 +1,15 @@
+
diff --git a/platypush/backend/http/templates/plugins/tts/index.html b/platypush/backend/http/templates/plugins/tts/index.html
new file mode 100644
index 00000000..a8de0e8c
--- /dev/null
+++ b/platypush/backend/http/templates/plugins/tts/index.html
@@ -0,0 +1,4 @@
+
+
diff --git a/platypush/plugins/tts/__init__.py b/platypush/plugins/tts/__init__.py
index cc7eb26a..ddd32495 100644
--- a/platypush/plugins/tts/__init__.py
+++ b/platypush/plugins/tts/__init__.py
@@ -17,17 +17,17 @@ class TtsPlugin(Plugin):
self.lang=lang
@action
- def say(self, phrase, lang=None):
+ def say(self, text, language=None):
"""
Say a phrase
- :param phrase: Phrase to say
- :type phrase: str
+ :param text: Phrase to say
+ :type text: str
- :param lang: Language code
- :type lang: str
+ :param language: Language code
+ :type language: str
"""
- if lang is None: lang=self.lang
+ if language is None: language=self.lang
output = None
errors = []
cmd = ['mplayer -ao alsa -really-quiet -noconsolecontrols ' +
@@ -35,8 +35,8 @@ class TtsPlugin(Plugin):
.format(urllib.parse.urlencode({
'ie' : 'UTF-8',
'client' : 'tw-ob',
- 'tl' : lang,
- 'q' : phrase,
+ 'tl' : language,
+ 'q' : text,
}))]
try:
diff --git a/platypush/plugins/tts/google.py b/platypush/plugins/tts/google.py
index e20a03c1..d67e1e45 100644
--- a/platypush/plugins/tts/google.py
+++ b/platypush/plugins/tts/google.py
@@ -18,7 +18,7 @@ class TtsGooglePlugin(Plugin):
* **mplayer** - see your distribution docs on how to install the mplayer package
"""
- def __init__(self, language='en-US', voice='en-US-Wavenet-C',
+ def __init__(self, language='en-US', voice=None,
gender='FEMALE', credentials_file='~/.credentials/platypush/google/platypush-tts.json'):
"""
:param language: Language code, see https://cloud.google.com/text-to-speech/docs/basics for supported languages
@@ -37,9 +37,34 @@ class TtsGooglePlugin(Plugin):
super().__init__()
self.language = language
self.voice = voice
+
+ self.language = self._parse_language(language)
+ self.voice = self._parse_voice(self.language, voice)
self.gender = getattr(texttospeech.enums.SsmlVoiceGender, gender.upper())
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = os.path.expanduser(credentials_file)
+ def _parse_language(self, language):
+ if language is None:
+ language = self.language or 'en-US'
+
+ if len(language) == 2:
+ language = language.lower()
+ if language == 'en':
+ language = 'en-US'
+ else:
+ language += '-' + language.upper()
+
+ return language
+
+ @staticmethod
+ def _parse_voice(language, voice):
+ if voice is not None:
+ return voice
+
+ if language == 'en-US':
+ return language + '-Wavenet-C'
+ return language + '-Wavenet-A'
+
@action
def say(self, text, language=None, voice=None, gender=None):
"""
@@ -61,17 +86,14 @@ class TtsGooglePlugin(Plugin):
client = texttospeech.TextToSpeechClient()
synthesis_input = texttospeech.types.SynthesisInput(text=text)
- if language is None:
- language = self.language
+ language = self._parse_language(language)
+ voice = self._parse_voice(language, voice)
if gender is None:
gender = self.gender
else:
gender = getattr(texttospeech.enums.SsmlVoiceGender, gender.upper())
- if voice is None:
- voice = self.voice
-
voice = texttospeech.types.VoiceSelectionParams(
language_code=language, ssml_gender=gender,
name=voice)