def init_chromecast(options): global shared_options global shared_redis_connection global shared_chromecast global shared_chromecast_listener global shared_chromecast_media_listener try: try_to_connect_to_redis() shared_options = options shared_chromecast = False shared_chromecast = Chromecast(shared_options['chromecast_output_ip']) shared_chromecast.start() shared_chromecast.wait() shared_chromecast_listener = StatusListener( shared_chromecast.name, shared_chromecast, shared_options["chromecast_output_uuid"], shared_redis_connection) shared_chromecast.register_status_listener(shared_chromecast_listener) shared_chromecast_media_listener = StatusMediaListener( shared_chromecast.name, shared_chromecast, shared_options["chromecast_output_uuid"], shared_redis_connection) shared_chromecast.media_controller.register_status_listener( shared_chromecast_media_listener) #start_adhoc_listener() try: shared_chromecast.media_controller.stop() except Exception as e: print(e) except Exception as e: shared_chromecast = False return False
def play(): try: output_chromecast_ip = sys.argv[1] uri_to_play = sys.argv[2] shuffle = sys.argv[3] if type(shuffle != bool): shuffle = string_to_bool(shuffle) redis_connection = try_to_connect_to_redis() spotify_token_info = RefreshSpotifyTokenIfNecessary(redis_connection) cast = Chromecast(output_chromecast_ip) cast.wait() client = spotipy.Spotify(auth=spotify_token_info["access_token"]) sp = SpotifyController(spotify_token_info["access_token"], spotify_token_info["seconds_left"]) cast.register_handler(sp) sp.launch_app() if not sp.is_launched and not sp.credential_error: print('Failed to launch spotify controller due to timeout') sys.exit(1) if not sp.is_launched and sp.credential_error: print( 'Failed to launch spotify controller due to credential error') sys.exit(1) devices_available = client.devices() spotify_device_id = None for device in devices_available['devices']: if device['id'] == sp.device: spotify_device_id = device['id'] break if not spotify_device_id: print('No device with id "{}" known by Spotify'.format(sp.device)) print('Known devices: {}'.format(devices_available['devices'])) sys.exit(1) # # Start playback if uri_to_play.find('track') > 0: client.start_playback(device_id=spotify_device_id, uris=[uri_to_play]) else: client.start_playback(device_id=spotify_device_id, context_uri=[uri_to_play]) time.sleep(2) client.shuffle(shuffle) return True except Exception as e: print("Couldn't Load URI and Play Spotify") print(e) return False
def play_currated_uris(spotify_token_info, chromecast_output_ip, uris): try: cast = Chromecast(chromecast_output_ip) cast.wait() cast.media_controller.stop() #client = spotipy.Spotify( auth=spotify_token_info[ "access_token" ] ) client = spotipy.Spotify(auth=spotify_token_info["access_token"]) sp = SpotifyController(spotify_token_info["access_token"], spotify_token_info["seconds_left"]) cast.register_handler(sp) sp.launch_app() if not sp.is_launched and not sp.credential_error: print('Failed to launch spotify controller due to timeout') return False if not sp.is_launched and sp.credential_error: print( 'Failed to launch spotify controller due to credential error') return False devices_available = client.devices() spotify_device_id = None for device in devices_available['devices']: if device['id'] == sp.device: spotify_device_id = device['id'] break if not spotify_device_id: print('No device with id "{}" known by Spotify'.format(sp.device)) print('Known devices: {}'.format(devices_available['devices'])) return False client.start_playback(device_id=spotify_device_id, uris=uris) time.sleep(2) client.volume(99) time.sleep(2) client.volume(100) client.shuffle(False) return True except Exception as e: print("Couldn't Load Spotify Chromecast App") print(e) return False
if "seconds_left" not in OurSpotifyTokenDB.self: GenerateSpotifyToken() return time_now = int( time.time() ) OurSpotifyTokenDB.self[ "seconds_left" ] = OurSpotifyTokenDB.self[ "expire_time" ] - time_now if OurSpotifyTokenDB.self[ "seconds_left" ] < 300: print( "Spotify Token is About to Expire in " + str( OurSpotifyTokenDB.self[ "seconds_left" ] ) + " Seconds" ) GenerateSpotifyToken() else: print( "Spotify Token is Still Valid for " + str( OurSpotifyTokenDB.self[ "seconds_left" ] ) + " Seconds" ) RefreshSpotifyTokenIfNecessary() cast = Chromecast( OurPersonalDB.self[ "chromecast_ip" ] ) print('cast {}'.format(cast)) cast.wait() spotify_device_id = None # Create a spotify client client = spotipy.Spotify( auth=OurSpotifyTokenDB.self[ "access_token" ] ) spotipy.trace = True spotipy.trace_out = True # Launch the spotify app on the cast we want to cast to sp = SpotifyController( OurSpotifyTokenDB.self[ "access_token" ] , OurSpotifyTokenDB.self[ "seconds_left" ] ) cast.register_handler(sp) sp.launch_app() if not sp.is_launched and not sp.credential_error: print('Failed to launch spotify controller due to timeout')
class TwitchCastController(BaseController): """Controller used to send TwitchCast streams to a Chromecast.""" def __init__(self, chromecast_name: str = None, chromecast_host: str = None) -> None: """Take care of some house keeping on init.""" super(TwitchCastController, self).__init__('urn:x-cast:com.google.cast.media', 'DAC1CD8C') self._cast = None # type: Chromecast self._chromecast_host = chromecast_host self._chromecast_name = chromecast_name self._expected_app_id = 'DAC1CD8C' self._setup_valid = False self._headers = { 'User-Agent': "Home-Assistant-TwitchCast-Service {}".format(__version__) } self._location = "https://hls-us-west.nightdev.com" def _setup(self) -> bool: self._setup_valid = self._setup_chromecast() if self._setup_valid: _LOGGER.info("setup completed successfully") else: _LOGGER.error("setup failed") if not self._cast: _LOGGER.error("no cast device") return False return True def _setup_chromecast(self) -> bool: if self._chromecast_host: try: self._cast = Chromecast(host=self._chromecast_host) self._cast.register_handler(self) self._cast.wait() return True except pychromecast.error.ChromecastConnectionError: _LOGGER.error("cannot find {}".format(self._chromecast_host)) elif self._chromecast_name: try: self._cast = next( cc for cc in get_chromecasts() if cc.device.friendly_name == self._chromecast_name) self._cast.register_handler(self) self._cast.wait() return True except StopIteration: _LOGGER.error("cannot find {}".format(self._chromecast_name)) else: _LOGGER.error("no chromecast host or name defined.") return False @property def cast(self) -> Chromecast: """Get chromecast object or set one up if needed.""" if not self._setup_valid: self._setup() return self._cast def _get_content_id(self, channel: str) -> str: _LOGGER.debug("getting content_id for {}".format(channel)) r = requests.get( 'https://nightdev.com/api/1/twitchcast/token?channel={}'.format( requests.utils.quote(channel)), headers=self._headers) token, sig = "", "" if r.status_code == 200: try: parsed_text = json.loads(r.text) token = parsed_text['token'] sig = parsed_text['sig'] except (ValueError, KeyError): _LOGGER.error( "error parsing token and sig for {}".format(channel)) return "" else: _LOGGER.error("status {} during token and sig for {}".format( r.status_code, channel)) playlist = [] # type: List[dict] if token and sig: url = '{}/get/playlist?channel={}&token={}&sig={}&callback=?'.\ format( self._location, requests.utils.quote(channel), requests.utils.quote(token), requests.utils.quote(sig)) r = requests.get(url, headers=self._headers) if r.status_code == 200: try: playlist = json.loads(r.text[2:-2])['playlist'] except ValueError: _LOGGER.error( "error parsing playlist for {}".format(channel)) return "" else: _LOGGER.error("status {} during playlist for {}".format( r.status_code, channel)) else: return "" if playlist: return playlist[0]['url'] else: return "" def _check_app_id(self, timeout: int = 10) -> bool: if not self.cast: return False if self.cast.app_id != self._expected_app_id: self.launch() for t in range(timeout * 5): if self.cast.app_id != self._expected_app_id: time.sleep(t / 5) else: return True return False def _stream_channel_callback(self, channel: str, layout: str, content_id: str) -> None: msg = { 'type': 'LOAD', 'media': { 'contentId': content_id, 'contentType': 'video/mp4', 'streamType': 'LIVE', 'metadata': self.channel_details(channel) }, 'mediaSessionId': None, 'customData': { 'channel': channel, 'layout': layout, }, } _LOGGER.debug("sending chromecast message {}".format(msg)) self.send_message(msg) def channel_details(self, channel: str) -> dict: """Get stream title & details from Twitch Kraken API.""" _LOGGER.debug("getting steam details for {}".format(channel)) metadata = { 'metadataType': 1, 'title': channel, 'subtitle': channel, 'images': [] } r = requests.get('https://api.twitch.tv/kraken/streams/{}?client_id' '=apbhlybpld3ybc6grv5c118xqpoz01c'.format( requests.utils.quote(channel)), headers=self._headers) if r.status_code == 200: try: parsed_text = json.loads(r.text)['stream']['channel'] metadata['title'] = parsed_text['display_name'] metadata['subtitle'] = parsed_text['status'] metadata['images'].append({ 'url': parsed_text['logo'], 'width': 0, 'height': 0, }) except (ValueError, KeyError): _LOGGER.error( "error parsing channel details for {}".format(channel)) else: _LOGGER.error("status {} during token and sig for {}".format( r.status_code, channel)) return metadata def stream_channel(self, channel: str, layout: str) -> None: """Stream a channel for a given layout on the Chromecast.""" _LOGGER.debug("trying to stream {} - {}".format(channel, layout)) content_id = self._get_content_id(channel) self._launched = False if content_id: _LOGGER.debug("launching {} - {}".format(channel, layout)) if self._check_app_id(): self.launch( callback_function=partial(self._stream_channel_callback, channel=channel, layout=layout, content_id=content_id)) else: _LOGGER.error("timed out waiting on chromecast") else: _LOGGER.error("couldn't get content_id for {}".format(channel))
def main(): import getopt import os import sys try: opts, args = getopt.getopt( sys.argv[1:], "vhH:l:", ["version", "help", "ip-addresses=", "language="]) except getopt.GetoptError: print(__usage__) sys.exit(2) lang = os.getenv("GNOTIFY_LANG", "") ips = [ip for ip in os.getenv("GNOTIFY_IPS", "").split(',') if ip] tts = " ".join(args) for opt, arg in opts: if opt in ("-h", "--help"): print(__usage__) sys.exit(2) elif opt in ("-v", "--version"): print("Version: {}".format(__version__)) sys.exit(2) elif opt in ("-l", "--language"): lang = arg elif opt in ("-H", "--ip-addresses"): ips = [ip for ip in arg.split(',') if ip] import re errors = [] if len(ips) == 0: errors.append( 'Please enter one or more ip addresses separated by commas as an option.' ) if str(lang) == "": errors.append('Please enter a language code (ISO 639-1) as an option.') elif not re.match(r"^\w{2}$", lang): errors.append( 'Please enter a valid language code (ISO 639-1) as an option.') if not tts or str(tts) == "": errors.append('Please enter a text-to-speech as arguments.') elif len(tts) > 5000: errors.append('The requested text-to-speech is too long (> 5000).') if errors: print(__usage__ + '\n') print('\n'.join(errors)) sys.exit(2) import time from pychromecast import Chromecast from pychromecast.error import ChromecastConnectionError from socketserver import ThreadingTCPServer from http.server import SimpleHTTPRequestHandler from threading import Thread from cachier import cachier @cachier() def get_tts_mp3(tl, q): from urllib.error import HTTPError from urllib.parse import urlencode from urllib.request import Request from urllib.request import urlopen request = Request("{}?{}".format( "https://translate.google.com/translate_tts", urlencode({ "ie": "UTF-8", "q": q, "tl": tl, "client": "tw-ob" }))) request.add_header("Referer", "http://translate.google.com/") request.add_header("User-Agent", "stagefright/1.2 (Linux;Android 5.0)") try: response = urlopen(request) except HTTPError: print("Google Translate error") sys.exit(2) return response.read() class FileHTTPRequestHandler(SimpleHTTPRequestHandler): def do_GET(self): self.send_response(200) self.end_headers() self.wfile.write(get_tts_mp3(lang, tts)) def log_message(self, format, *args): return for ip in ips: try: cast = Chromecast(ip) except ChromecastConnectionError as e: print(e) sys.exit(2) server_ip = cast.socket_client.socket.getsockname()[0] server = ThreadingTCPServer((server_ip, 0), FileHTTPRequestHandler) server_port = str(server.server_address[1]) thread = Thread(target=server.serve_forever) thread.daemon = True thread.start() cast.wait() mc = cast.media_controller mc.play_media("http://{}:{}".format(server_ip, server_port), "audio/mpeg") time.sleep(.5) while mc.status.player_state != "IDLE": try: time.sleep(0.05) except KeyboardInterrupt: mc.stop() break server.shutdown() server.server_close()