From ecafe0753c1ef60254c030473265b62ed45a4193 Mon Sep 17 00:00:00 2001 From: guirem Date: Thu, 28 May 2020 01:07:16 +0200 Subject: [PATCH] added 2 params --- core/class/googlecast.class.php | 24 +++---- plugin_info/configuration.php | 21 ++++-- plugin_info/install.php | 12 ++++ resources/globals.py | 3 + resources/googlecast.py | 109 ++++++++++++++++++++++---------- resources/install.sh | 6 +- resources/requirements.txt | 7 +- 7 files changed, 126 insertions(+), 56 deletions(-) diff --git a/core/class/googlecast.class.php b/core/class/googlecast.class.php index 35499dc..42dc865 100644 --- a/core/class/googlecast.class.php +++ b/core/class/googlecast.class.php @@ -120,17 +120,17 @@ public function preUpdate() if (!$found) { // try to guess based on manufacturer $castType = $this->getConfiguration('cast_type'); $manufName = strtolower($this->getConfiguration('manufacturer', 'UNKOWN')); - if (strpos($manufName, 'google') !== false) { - if ($castType=='audio') { - $imgLogo = $imgRoot . 'model_googlehome.png'; - } - if ($castType=='cast') { - $imgLogo = $imgRoot . 'model_chromecast_video.png'; - } - if ($castType=='group') { - $imgLogo = $imgRoot . 'model_castgroup.png'; - } - } + // if (strpos($manufName, 'google') !== false) { + // if ($castType=='audio') { + // $imgLogo = $imgRoot . 'model_googlehome.png'; + // } + // if ($castType=='cast') { + // $imgLogo = $imgRoot . 'model_chromecast_video.png'; + // } + // if ($castType=='group') { + // $imgLogo = $imgRoot . 'model_castgroup.png'; + // } + // } if (strpos($manufName, 'xiaomi') !== false) { $imgLogo = $imgRoot . 'model_androidtv.png'; } @@ -962,6 +962,8 @@ public static function deamon_start() } $cmd .= ' --ttsgapikey ' . config::byKey('tts_gapikey', 'googlecast', 'none'); $cmd .= ' --gcttsvoice ' . config::byKey('gctts_voice', 'googlecast', 'fr-FR-Standard-A'); + $cmd .= ' --ttsdefaultrestoretime ' . config::byKey('tts_default_restoretime', 'googlecast', '1300'); + $cmd .= ' --ttsdefaultsilenceduration ' . config::byKey('tts_default_silence_duration', 'googlecast', '300'); $cmd .= ' --daemonname local'; $cmd .= ' --cyclefactor ' . config::byKey('cyclefactor', 'googlecast', '1'); $cmd .= ' --defaultstatus ' . "'". config::byKey('defaultsatus', 'googlecast', " ") ."'"; diff --git a/plugin_info/configuration.php b/plugin_info/configuration.php index 43675fb..126d40b 100644 --- a/plugin_info/configuration.php +++ b/plugin_info/configuration.php @@ -320,16 +320,27 @@ -
- +
+
- +
+
ms (défaut: 1000)
+
+
+ +
+ +
+
ms (défaut: 300)
- + +
diff --git a/plugin_info/install.php b/plugin_info/install.php index 65b4899..96a9d21 100644 --- a/plugin_info/install.php +++ b/plugin_info/install.php @@ -40,6 +40,12 @@ function googlecast_update() if (config::byKey('gctts_voice', 'googlecast') == '') { config::save('gctts_voice', 'fr-FR-Standard-A', 'googlecast'); } + if (config::byKey('tts_default_restoretime', 'googlecast') == '') { + config::save('tts_default_restoretime', '1300', 'googlecast'); + } + if (config::byKey('tts_default_silence_duration', 'googlecast') == '') { + config::save('tts_default_silence_duration', '300', 'googlecast'); + } foreach (googlecast::byType('googlecast') as $googlecast) { try { @@ -93,6 +99,12 @@ function googlecast_install() if (config::byKey('tts_disablecache', 'googlecast') == '') { config::save('tts_disablecache', '0', 'googlecast'); } + if (config::byKey('tts_default_restoretime', 'googlecast') == '') { + config::save('tts_default_restoretime', '1300', 'googlecast'); + } + if (config::byKey('tts_default_silence_duration', 'googlecast') == '') { + config::save('tts_default_silence_duration', '300', 'googlecast'); + } linkTemplate('dashboard/cmd.info.string.googlecast_playing.html'); linkTemplate('dashboard/cmd.action.message.googlecast_speak.html'); diff --git a/resources/globals.py b/resources/globals.py index ba118ee..64b03d5 100644 --- a/resources/globals.py +++ b/resources/globals.py @@ -77,6 +77,9 @@ tts_gapi_voice = 'fr-FR-Standard-A' tts_gapi_haskey = False +tts_default_restoredelay = 1300 # additionnal time in ms to add after tts (before vol up command) +tts_default_silenceduration = 300 # default silence duration added at tts start + localmedia_folder = 'localmedia' localmedia_fullpath = os.path.abspath(os.path.join( os.path.dirname(os.path.dirname(__file__)), localmedia_folder)) diff --git a/resources/googlecast.py b/resources/googlecast.py index 581ba3c..1f9533c 100644 --- a/resources/googlecast.py +++ b/resources/googlecast.py @@ -26,7 +26,7 @@ import sys import argparse import time -from datetime import datetime +from datetime import datetime, timedelta import signal import json import traceback @@ -51,6 +51,7 @@ try: import pychromecast.pychromecast.controllers.dashcast as dashcast import pychromecast.pychromecast.controllers.spotify as spotify + import pychromecast.pychromecast.controllers.youtube as youtube except ImportError: logging.error( "ERROR: One or several pychromecast controllers are not loaded !") @@ -60,7 +61,6 @@ try: import pychromecast.pychromecast.customcontrollers.plex2 as plex - import pychromecast.pychromecast.customcontrollers.youtube as youtube except ImportError: logging.error("ERROR: Custom controllers not loaded !") logging.error(traceback.format_exc()) @@ -398,6 +398,29 @@ def disconnect(self): pass self.free_memory() + def check_connection(self): + reset = False + castsocket = self.gcast.socket_client + try: + # if castsocket.heartbeat_controller.is_expired(): + castsocket.heartbeat_controller.ping() + # castsocket.heartbeat_controller.reset() + except Exception: + logging.debug("JEEDOMCHROMECAST------ check_connection : ping failed") + reset = True + pass + + if reset: + for channel in castsocket._open_channels: + castsocket.disconnect_channel(channel) + try: + castsocket.initialize_connection() + except Exception: + castsocket.stop.set() + pass + + return not reset + def free_memory(self): try: self.gcast.socket_client.socket.shutdown(socket.SHUT_RDWR) @@ -886,35 +909,31 @@ def action_handler(message): if cmd == 'play_media': fallbackMode = False - wptoken = None - if 'user' in command and 'pass' in command: - username = command['user'] - password = command['pass'] - wptoken = stoken.SpotifyWpToken(username, password) - - if 'token' in command: - token = command['token'] - keepGoing = True - if value is None: + if 'spdc' in command and 'spkey' in command: + spdc = command['spdc'] + spkey = command['spkey'] + spdc = "AQCgatcbOEWKU9btY2uaCYa-f40OilLICq-hzBoQRxhdCTfMTrmgxyVC0h-WCQ-H3aa4Cq4V-woqmRz3Fx8AL_RRutLHo38vk_iXNsY1YPw" + spkey = "cdb4b966-a7dc-4813-ad95-b55361902e8c" + data = stoken.start_session(spdc, spkey) + access_token = data[0] + expires = data[1] - int(time.time()) + else: logging.error( - "ACTION------ Missing content id for spotify") + "ACTION------ Missing spdc and/or spkey") keepGoing = False - if token is None: + + if value is None: logging.error( - "ACTION------ Missing token paramaters for spotify") + "ACTION------ Missing content id for spotify") keepGoing = False if keepGoing is True: player = jcast.loadPlayer( app, {'quitapp': quit_app_before, 'wait': wait}) - if wptoken is None: - player.launch_app(token) - else: - time.sleep(1) - player.launch_app(wptoken.value) + player.launch_app(access_token, expires) - spotifyClient = spotipy.Spotify(auth=token) + spotifyClient = spotipy.Spotify(auth=access_token) time.sleep(1) value = value.replace('spotify:', '') @@ -947,7 +966,9 @@ def action_handler(message): 'spotify:', '') logging.debug( "ACTION------Spotify recently played : " + value) - # logging.debug("ACTION------Spotify recently played : " + str(recentlyPlayed)) + # logging.debug("ACTION------Spotify recently played : " + str(recentlyPlayed)) + spotifyClient.start_playback( + device_id=device_id, uris=['spotify:'+value]) elif 'track' not in value: # album or playlist spotifyClient.start_playback( device_id=device_id, context_uri='spotify:'+value) @@ -1199,9 +1220,10 @@ def action_handler(message): url, 'video/mp4', 'NOTIF', thumb=thumb, stream_type=streamtype) player.block_until_active(timeout=2) jcast.disable_notif = False + duration_total = duration + (globals.tts_default_restoredelay/1000) sleep_done = False if vol is not None: - time.sleep(duration+1) + time.sleep(duration_total) if sleep > 0: time.sleep(sleep) sleep = 0 @@ -1215,7 +1237,7 @@ def action_handler(message): gcast.media_controller.stop() if quit: if vol is None: - time.sleep(duration+1) + time.sleep(duration_total) sleep_done = True if sleep > 0: time.sleep(sleep) @@ -1223,7 +1245,7 @@ def action_handler(message): gcast.quit_app() if resume: if vol is None and sleep_done is False: - time.sleep(duration+1) + time.sleep(duration_total) if sleep > 0: time.sleep(sleep) sleep = 0 @@ -1256,11 +1278,11 @@ def action_handler(message): forcetts = False if 'forcetts' in command: forcetts = True - silence = 300 + silence = globals.tts_default_silenceduration if 'silence' in command: silence = int(command['silence']) elif jcast.is_castgroup is True: - silence = 1000 + silence = silence + 700 generateonly = False if 'generateonly' in command: generateonly = True @@ -1309,14 +1331,17 @@ def action_handler(message): gcast.media_controller.pause() time.sleep(0.1) gcast.set_volume(vol/100) - time.sleep(0.1) + # time.sleep(0.1) + streamtype = 'BUFFERED' player.play_media( url, 'audio/mp3', 'TTS', thumb=thumb, stream_type=streamtype) - player.block_until_active(timeout=2) + player.block_until_active(timeout=4) + duration_total = duration + (globals.tts_default_restoredelay/1000) + logging.debug("TTS------Estimated duration of tts media is " + str(duration_total) + " secondes") jcast.disable_notif = False vol_done = False if vol is not None: - time.sleep(duration+(silence/1000)+1) + time.sleep(duration_total) if sleep > 0: time.sleep(sleep) sleep = 0 @@ -1326,14 +1351,14 @@ def action_handler(message): if quit: if vol is None: - time.sleep(duration+(silence/1000)+1) + time.sleep(duration_total) if sleep > 0: time.sleep(sleep) sleep = 0 gcast.quit_app() if resume: if vol is None and vol_done is False: - time.sleep(duration+(silence/1000)+1) + time.sleep(duration_total) if sleep > 0: time.sleep(sleep) sleep = 0 @@ -1549,7 +1574,7 @@ def manage_resume(uuid, source='googlecast', forceapplaunch=False, origin='TTS') return False -def get_tts_data(text, language, engine, speed, forcetts, calcduration, silence=300, quality='32k', ttsparams=None): +def get_tts_data(text, language, engine, speed, forcetts, calcduration, silence=100, quality='32k', ttsparams=None): srclanguage = language if engine == 'gttsapidev': # removed this engine but failover to gttsapi engine = 'gttsapi' @@ -1817,7 +1842,7 @@ def logByTTS(text_id): else: text = "Un erreur s'est produite !" url, duration, mp3filename = get_tts_data( - text, lang, engine, speed, False, False, 300) + text, lang, engine, speed, False, False, globals.tts_default_silenceduration) thumb = globals.JEEDOM_WEB + '/plugins/googlecast/desktop/images/tts.png' jcast = None # TODO: get googlecast device first player = jcast.loadPlayer('media', {'quitapp': False, 'wait': 0}) @@ -1911,6 +1936,7 @@ def start(cycle=2): except Exception: logging.error("GLOBAL------Exception on main loop") + shutdown() except KeyboardInterrupt: logging.error("GLOBAL------KeyboardInterrupt, shutdown") @@ -2153,6 +2179,11 @@ def scanner(name='UNKNOWN SOURCE'): if known in globals.GCAST_DEVICES: if globals.GCAST_DEVICES[known].is_connected is True: is_not_available = False + + # try to ping it to confirm it's well connected + con_ok = globals.GCAST_DEVICES[known].check_connection() + if not con_ok: + logging.debug("SCANNER------Seen as connected but ping failed, trying to reconnect " + known) else: # something went wrong so disconnect completely globals.GCAST_DEVICES[known].disconnect() @@ -2333,6 +2364,8 @@ def shutdown(): parser.add_argument("--ttsgapikey", help="TTS Google Speech API Key", type=str) parser.add_argument( "--gcttsvoice", help="TTS Google Speech API default voice", type=str) +parser.add_argument("--ttsdefaultrestoretime", help="TTS Default restore volume delay", type=str) +parser.add_argument("--ttsdefaultsilenceduration", help="TTS Default silence duration", type=str) parser.add_argument("--socketport", help="Socket Port", type=str) parser.add_argument("--sockethost", help="Socket Host", type=str) parser.add_argument("--daemonname", help="Daemon Name", type=str) @@ -2375,6 +2408,10 @@ def shutdown(): globals.tts_gapi_haskey = True if args.gcttsvoice: globals.tts_gapi_voice = args.gcttsvoice +if args.ttsdefaultrestoretime: + globals.tts_default_restoredelay = int(args.ttsdefaultrestoretime) +if args.ttsdefaultsilenceduration: + globals.tts_default_silenceduration = int(args.ttsdefaultsilenceduration) if args.cycle: globals.cycle_event = float(args.cycle) if args.cyclemain: @@ -2422,6 +2459,10 @@ def shutdown(): str(globals.tts_gapi_voice)) else: logging.info('GLOBAL------TTS Google API Key (optional) : NOK') +logging.info('GLOBAL------TTS default delay before volume restore : ' + + str(globals.tts_default_restoredelay) + ' ms') +logging.info('GLOBAL------TTS default silence before tts : ' + + str(globals.tts_default_silenceduration) + ' ms') logging.info('GLOBAL------Cache status : '+str(globals.tts_cacheenabled)) logging.info('GLOBAL------Callback : '+str(globals.callback)) logging.info('GLOBAL------Event cycle : '+str(globals.cycle_event)) diff --git a/resources/install.sh b/resources/install.sh index 2c02e43..72f785d 100644 --- a/resources/install.sh +++ b/resources/install.sh @@ -93,7 +93,7 @@ if [[ ! -z $pip3cmd ]]; then # pip3 found echo 87 > /tmp/dependancy_googlecast_in_progress echo "" echo "-- Installation of python library 'zeroconf' with command $pip3cmd" - $(sudo $pip3cmd install 'zeroconf<0.24.4,>=0.22.0' > /tmp/dependancy_googlecast) + $(sudo $pip3cmd install 'zeroconf>=0.25.1' > /tmp/dependancy_googlecast) cat /tmp/dependancy_googlecast echo 92 > /tmp/dependancy_googlecast_in_progress echo "" @@ -102,8 +102,8 @@ if [[ ! -z $pip3cmd ]]; then # pip3 found cat /tmp/dependancy_googlecast echo 96 > /tmp/dependancy_googlecast_in_progress echo "" - echo "-- Installation of python library 'tqdm, websocket-client' for plex with command $pip3cmd" - $(sudo $pip3cmd install tqdm websocket-client > /tmp/dependancy_googlecast) + echo "-- Installation of python library 'tqdm, websocket-client, casttube' for plex/youtube with command $pip3cmd" + $(sudo $pip3cmd install tqdm websocket-client casttube > /tmp/dependancy_googlecast) cat /tmp/dependancy_googlecast echo 100 > /tmp/dependancy_googlecast_in_progress echo "" diff --git a/resources/requirements.txt b/resources/requirements.txt index 02bba8c..aee7115 100644 --- a/resources/requirements.txt +++ b/resources/requirements.txt @@ -1,9 +1,10 @@ setuptools requests>=2.21.0 -protobuf -zeroconf<0.24.4,>=0.22.0 click bs4 six tqdm -websocket-client \ No newline at end of file +websocket-client +protobuf>=3.0.0 +zeroconf>=0.25.1 +casttube>=0.2.0 \ No newline at end of file