Example #1
0
def Play():
    """
    Endpoint to play media.
    """
    Log.Debug('Recieved a call to play media.')
    params = ['Clienturi', 'Contentid', 'Contenttype', 'Serverid', 'Serveruri',
              'Username', 'Transienttoken', 'Queueid', 'Version']
    values = sort_headers(params, False)
    status = "Missing required headers"
    msg = status
    if values is not False:
        Log.Debug("Holy crap, we have all the headers we need.")
        client_uri = values['Clienturi'].split(":")
        host = client_uri[0]
        port = int(client_uri[1])
        pc = False
        servers = fetch_servers()
        for server in servers:
            if server['id'] == values['Serverid']:
                Log.Debug("Found a matching server!")
                values['Serveruri'] = server['uri']
                values['Version'] = server['version']

        msg = "No message received"
        try:
            cast = pychromecast.Chromecast(host, port)
            cast.wait()
            values['Type'] = cast.cast_type
            pc = PlexController(cast)
            cast.register_handler(pc)
            pc.play_media(values, log_data)
        except pychromecast.LaunchError, pychromecast.PyChromecastError:
            Log.Debug('Error connecting to host.')
            status = "Error"
        finally:
Example #2
0
File: cast.py Project: jbouwh/core
def _play_media(hass: HomeAssistant, chromecast: Chromecast, media_type: str,
                media_id: str) -> None:
    """Play media."""
    result = process_plex_payload(hass, media_type, media_id)
    controller = PlexController()
    chromecast.register_handler(controller)
    offset_in_s = result.offset / 1000
    controller.play_media(result.media, offset=offset_in_s)
Example #3
0
def cast_media_to(cast, media):
    try:
        cast.wait()
        pc = PlexController()
        cast.register_handler(pc)
        pc.play_media(media)
    except Exception as e:
        logging.error(e)
Example #4
0
def _play_media(hass: HomeAssistant, chromecast: Chromecast, media_type: str,
                media_id: str) -> None:
    """Play media."""
    media_id = media_id[len(PLEX_URI_SCHEME):]
    media = lookup_plex_media(hass, media_type, media_id)
    if media is None:
        return
    controller = PlexController()
    chromecast.register_handler(controller)
    controller.play_media(media)
    def play_media(self, media_type, media_id, **kwargs):
        """Play media from a URL."""
        extra = kwargs.get(ATTR_MEDIA_EXTRA, {})
        metadata = extra.get("metadata")

        # We do not want this to be forwarded to a group
        if media_type == CAST_DOMAIN:
            try:
                app_data = json.loads(media_id)
                if metadata is not None:
                    app_data["metadata"] = extra.get("metadata")
            except json.JSONDecodeError:
                _LOGGER.error("Invalid JSON in media_content_id")
                raise

            # Special handling for passed `app_id` parameter. This will only launch
            # an arbitrary cast app, generally for UX.
            if "app_id" in app_data:
                app_id = app_data.pop("app_id")
                _LOGGER.info("Starting Cast app by ID %s", app_id)
                self._chromecast.start_app(app_id)
                if app_data:
                    _LOGGER.warning(
                        "Extra keys %s were ignored. Please use app_name to cast media",
                        app_data.keys(),
                    )
                return

            app_name = app_data.pop("app_name")
            try:
                quick_play(self._chromecast, app_name, app_data)
            except NotImplementedError:
                _LOGGER.error("App %s not supported", app_name)
        # Handle plex
        elif media_id and media_id.startswith(PLEX_URI_SCHEME):
            media_id = media_id[len(PLEX_URI_SCHEME):]
            media, _ = lookup_plex_media(self.hass, media_type, media_id)
            if media is None:
                return
            controller = PlexController()
            self._chromecast.register_handler(controller)
            controller.play_media(media)
        else:
            app_data = {
                "media_id": media_id,
                "media_type": media_type,
                **extra
            }
            quick_play(self._chromecast, "default_media_receiver", app_data)
Example #6
0
def remote_control(hass, zeroconf, control, device, jump_amount):
    plex_c = PlexController()
    if control == "jump_forward":
        jump(hass, device, jump_amount[0])
    elif control == "jump_back":
        jump(hass, device, -jump_amount[1])
    elif control == "next_track" and device["device_type"] == "cast":
        cast_next_prev(hass, zeroconf, plex_c, device, "next")
    elif control == "previous_track" and device["device_type"] == "cast":
        cast_next_prev(hass, zeroconf, plex_c, device, "previous")
    else:
        media_service(hass, device["entity_id"], f"media_{control}")
Example #7
0
    def _setup_controllers(self):
        self.ctls = Controllers(
            YouTubeController(),
            DashCastController(),
            PlexController(),
            SuplaController(),
            # BbcIplayerController(),
            # BbcSoundsController(),
            # BubbleUPNPController(),
            # YleAreenaController(),
            # PlexApiController(),
            # HomeAssistantController(),
        )

        for ctl in self.ctls:
            if ctl:
                self._register(ctl)
Example #8
0
    def handle_input(call):
        command_string = call.data.get("command").strip().lower()

        if not command_string:
            _LOGGER.warning(localize["no_call"])
            return

        chromecasts = get_chromecasts()
        for chromecast in chromecasts:
            PA.devices[chromecast.device.friendly_name] = chromecast

        PA.clients = PA.server.clients()
        PA.client_names = [client.title for client in PA.clients]
        PA.client_ids = [client.machineIdentifier for client in PA.clients]

        if localize["controls"]["update_sensor"] in command_string:
            update_sensor()
            return

        cast = None
        alias = ["", 0]
        client = False
        speech_error = False

        command = process_speech(command_string, localize, default_cast, PA)

        if not command["control"]:
            _LOGGER.debug({i: command[i] for i in command if i != 'library'})

        if PA.lib["updated"] < PA.plex.search(sort="addedAt:desc",
                                              limit=1)[0].addedAt:
            PA.lib = get_libraries(PA.plex)

        PA.device_names = list(PA.devices.keys())
        devices = PA.device_names + PA.client_names + PA.client_ids
        device = fuzzy(command["device"] or default_cast, devices)
        if aliases:
            alias = fuzzy(command["device"] or default_cast, PA.alias_names)

        if alias[1] < 60 and device[1] < 60:
            _LOGGER.warning("{0} {1}: \"{2}\"".format(
                localize["cast_device"].capitalize(), localize["not_found"],
                command["device"].title()))
            _LOGGER.debug("Device Score: %s", device[1])
            _LOGGER.debug("Devices: %s", str(devices))

            if aliases:
                _LOGGER.debug("Alias Score: %s", alias[1])
                _LOGGER.debug("Aliases: %s", str(PA.alias_names))
            return

        name = aliases[alias[0]] if alias[1] > device[1] else device[0]
        cast = PA.devices[name] if name in PA.device_names else name
        client = isinstance(cast, str)
        if client:
            client_device = next(
                c for c in PA.clients
                if c.title == cast or c.machineIdentifier == cast)
            cast = client_device

        if command["control"]:
            control = command["control"]
            if client:
                cast.proxyThroughServer()
                plex_c = PA.server.client(cast.title)
            else:
                plex_c = PlexController()
                cast.wait()
                cast.register_handler(plex_c)
            if control == "play":
                plex_c.play()
            elif control == "pause":
                plex_c.pause()
            elif control == "stop":
                plex_c.stop()
            elif control == "jump_forward":
                plex_c.stepForward()
            elif control == "jump_back":
                plex_c.stepBack()
            return

        try:
            result = find_media(command, command["media"], PA.lib)
            media = video_selection(command, result["media"],
                                    result["library"])
        except Exception:
            error = media_error(command, localize)
            if tts_error:
                tts = gTTS(error, lang=lang)
                tts.save(directory + 'error.mp3')
                speech_error = True
            _LOGGER.warning(error)

        if speech_error and not client:
            cast.wait()
            med_con = cast.media_controller
            mp3 = get_url(hass) + "/local/plex_assist_tts/error.mp3"
            med_con.play_media(mp3, 'audio/mpeg')
            med_con.block_until_active()
            return

        _LOGGER.debug("Media: %s", str(media))

        if client:
            _LOGGER.debug("Client: %s", cast)
            cast.proxyThroughServer()
            plex_c = cast
            plex_c.playMedia(media)
        else:
            _LOGGER.debug("Cast: %s", cast.name)
            delay = 6
            if call.data.get("cast_delay") or call.data.get("cast_delay") == 0:
                delay = call.data.get("cast_delay")
            elif cast.name in cast_delay.keys():
                delay = cast_delay[cast.name]
            plex_c = PlexController()
            plex_c.namespace = 'urn:x-cast:com.google.cast.media'
            cast.register_handler(plex_c)
            cast.wait()
            play_media(float(delay), cast, plex_c, media)

        update_sensor()
Example #9
0
def Status(input_name=False):
    """
    Fetch player status
    TODO: Figure out how to parse and return additional data here
    """
    uri = "FOOBAR"
    name = "FOOBAR"
    show_all = False
    Log.Debug('Trying to get cast device status here')
    for key, value in Request.Headers.items():
        Log.Debug("Header key %s is %s", key, value)
        if key in ("X-Plex-Clienturi", "Clienturi"):
            Log.Debug("We have a client URI")
            uri = value

        if key in ("X-Plex-Clientname", "Clientname"):
            Log.Debug("X-Plex-Clientname: " + value)
            name = value

    if input_name is not False:
        name = input_name
    if uri == name:
        show_all = True

    chromecasts = fetch_devices()
    devices = []

    for chromecast in chromecasts:
        cast = False
        if show_all is not True:
            if chromecast['name'] == name:
                Log.Debug("Found a matching chromecast: " + name)
                cast = chromecast

            if chromecast['uri'] == uri:
                Log.Debug("Found a matching uri:" + uri)
                cast = chromecast
        else:
            cast = chromecast

        if cast is not False:
            devices.append(cast)

    do = ""

    if len(devices) != 0:
        for device in devices:
            Log.Debug("We have set a chromecast here.")
            uris = device['uri'].split(":")
            host = uris[0]
            port = uris[1]
            Log.Debug("Host and port are %s and %s", host, port)
            cast = pychromecast.Chromecast(host, int(port))
            Log.Debug("Waiting for device")
            cast.wait(2)
            app_id = cast.app_id
            meta_dict = False
            if app_id == "9AC194DC":
                pc = PlexController(cast)
                cast.register_handler(pc)
                plex_status = pc.plex_status()
                raw_status = {
                    'state': plex_status['state'],
                    'volume': plex_status['volume'],
                    'muted': plex_status['muted']
                }
                meta_dict = plex_status['meta']
            else:
                raw_status = {"state": "idle"}

            Log.Debug("Did we get it?!?! %s", raw_status)
            if not cast.is_idle:
                Log.Debug("We have a non-idle cast")
                status = "Running" + cast.app_display_name()
            else:
                status = "Idle"

            do = StatusContainer(
                dict=raw_status
            )
            if meta_dict is not False:
                mc = MetaContainer(
                    dict=meta_dict
                )

                do.add(mc)

    return do
Example #10
0
def Cmd():
    """
    Media control command(s).

    Plex-specific commands use the format:


    Required params:
    Uri
    Cmd
    Vol(If setting volume, otherwise, ignored)

    Where <COMMAND> is one of:
    PLAY (resume)
    PAUSE
    STOP
    STEPFORWARD
    STEPBACKWARD Need to test, not in PHP cast app)
    PREVIOUS
    NEXT
    MUTE
    UNMUTE
    VOLUME - also requires an int representing level from 0-100

    """
    Log.Debug('Recieved a call to control playback')
    params = sort_headers(['Uri', 'Cmd', 'Val'], False)
    status = "Missing paramaters"
    response = "Error"

    if params is not False:
        uri = params['Uri'].split(":")
        cast = pychromecast.Chromecast(uri[0], int(uri[1]))
        cast.wait()
        pc = PlexController(cast)
        Log.Debug("Handler namespace is %s" % pc.namespace)
        cast.register_handler(pc)

        Log.Debug("Handler namespace is %s" % pc.namespace)

        cmd = params['Cmd']
        Log.Debug("Command is " + cmd)

        if cmd == "play":
            pc.play()
        if cmd == "pause":
            pc.pause()
        if cmd == "stop":
            pc.stop()
        if cmd == "next":
            pc.next()
        if (cmd == "offset") & ('Val' in params):
            pc.seek(params["Val"])
        if cmd == "previous":
            pc.previous()
        if cmd == "volume.mute":
            pc.mute(True)
        if cmd == "volume.unmute":
            pc.mute(False)
        if (cmd == "volume") & ('Val' in params):
            pc.set_volume(params["Val"])
        if cmd == "volume.down":
            pc.volume_down()
        if cmd == "volume.up":
            pc.volume_up()

        cast.disconnect()
        response = "Command successful"

    oc = ObjectContainer(
        title1=response,
        title2=status,
        no_cache=True,
        no_history=True)
    return oc
Example #11
0
    media = plex_server.createPlayQueue(libraryItems)
    # Set starting position to the 3rd item if startItem demo.
    startItem = libraryItems[2] if args.startitem else None
    # Print info
    media_info(media, media.items)
    start_item_info(libraryItems[2])
elif args.demo == "playlist":
    # Convert list into a playlist for media.
    media = plex_server.createPlaylist("pychromecast test playlist",
                                       libraryItems)
    # Set starting position to the 4th item if startItem demo.
    startItem = libraryItems[3] if args.startitem else None
    # Print info
    media_info(media, media.items())
    start_item_info(libraryItems[2])

plex_c = PlexController()
cast.register_handler(plex_c)
cast.wait()

# Plays the media item, list, playlist, or playqueue.
# If startItem = None it is ignored and playback starts at first item,
# otherwise playback starts at the position of the media item given.
plex_c.block_until_playing(media, startItem=startItem)

if getattr(media, "TYPE", None) == "playlist":
    media.delete()

# Shut down discovery
browser.stop_discovery()
Example #12
0
    def handle_input(call):
        if not call.data.get("command").strip():
            _LOGGER.warning(localize["no_call"])
            return

        command_string = call.data.get("command").strip().lower()
        _LOGGER.debug("Command: %s", command_string)

        PA.client_update = True
        get_chromecasts(blocking=False,
                        callback=cc_callback,
                        zeroconf_instance=zc)

        if localize["controls"]["update_sensor"] in command_string:
            update_sensor(hass)
            return

        cast = None
        alias = ["", 0]
        client = False
        speech_error = False

        command = process_speech(command_string, localize, default_cast, PA)
        PA.device_names = list(PA.devices.keys())

        if not command["control"]:
            _LOGGER.debug({i: command[i] for i in command if i != "library"})

        if PA.lib["updated"] < PA.plex.search(sort="addedAt:desc",
                                              limit=1)[0].addedAt:
            PA.lib = get_libraries(PA.plex)

        devices = PA.device_names + PA.client_names + PA.client_ids
        device = fuzzy(command["device"] or default_cast, devices)

        if aliases:
            alias = fuzzy(command["device"] or default_cast, PA.alias_names)

        if alias[1] < 60 and device[1] < 60:
            _LOGGER.warning('{0} {1}: "{2}"'.format(
                localize["cast_device"].capitalize(),
                localize["not_found"],
                command["device"].title(),
            ))
            _LOGGER.debug("Device Score: %s", device[1])
            _LOGGER.debug("Devices: %s", str(devices))

            if aliases:
                _LOGGER.debug("Alias Score: %s", alias[1])
                _LOGGER.debug("Aliases: %s", str(PA.alias_names))
            return

        name = aliases[alias[0]] if alias[1] > device[1] else device[0]
        cast = PA.devices[name] if name in PA.device_names else name
        client = isinstance(cast, str)

        if client:
            client_device = next(
                c for c in PA.clients
                if c.title == cast or c.machineIdentifier == cast)
            cast = client_device

        if command["control"]:
            control = command["control"]
            if client:
                try:
                    if "127.0.0.1" in cast.url("/"):
                        cast.proxyThroughServer()
                except plexapi.exceptions.BadRequest:
                    cast.proxyThroughServer()
                plex_c = cast
            else:
                plex_c = PlexController()
                cast.wait()
                cast.register_handler(plex_c)
            if control == "play":
                plex_c.play()
            elif control == "pause":
                plex_c.pause()
            elif control == "stop":
                plex_c.stop()
            elif control == "jump_forward":
                plex_c.stepForward()
            elif control == "jump_back":
                plex_c.stepBack()
            return

        try:
            result = find_media(command, command["media"], PA.lib)
            media = video_selection(command, result["media"],
                                    result["library"])
        except Exception:
            error = media_error(command, localize)
            if tts_error:
                tts = gTTS(error, lang=lang)
                tts.save(directory + "error.mp3")
                speech_error = True

        if speech_error and not client:
            cast.wait()
            med_con = cast.media_controller
            mp3 = get_url(hass) + "/local/plex_assist_tts/error.mp3"
            med_con.play_media(mp3, "audio/mpeg")
            med_con.block_until_active()
            return

        _LOGGER.debug("Media: %s", str(media))

        if client:
            _LOGGER.debug("Client: %s", cast)
            try:
                if "127.0.0.1" in cast.url("/"):
                    cast.proxyThroughServer()
            except plexapi.exceptions.BadRequest:
                cast.proxyThroughServer()
            plex_c = cast
            plex_c.playMedia(media)
        else:
            _LOGGER.debug("Cast: %s", cast.name)
            plex_c = PlexController()
            cast.register_handler(plex_c)
            cast.wait()
            plex_c.block_until_playing(media)

        update_sensor(hass)
Example #13
0
    def handle_input(call):
        """Handle the service call."""
        if not call.data.get("command").strip():
            _LOGGER.warning(localize["no_call"])
            return

        cast = None
        client = False
        speech_error = False

        get_chromecasts(blocking=False, callback=cc_callback)
        for client in PA.server.clients():
            if client.title not in PA.client_names:
                PA.client_names.append(client.title)

        command = process_speech(
            call.data.get("command").lower(),
            localize,
            default_cast,
            PA
        )

        if not command["control"]:
            _LOGGER.debug({i: command[i] for i in command if i != 'library'})

        if PA.lib["updated"] < PA.plex.search(sort="addedAt:desc")[0].addedAt:
            PA.lib = get_libraries(PA.plex)

        try:
            devices = PA.device_names + PA.client_names
            device = fuzzy(command["device"] or default_cast, devices)
            alias = fuzzy(command["device"] or default_cast, PA.alias_names)
            name = aliases[alias[0]] if alias[1] > device[1] else device[0]
            cast = PA.devices[name] if name in PA.device_names else name
        except Exception:
            error = "{0} {1}.".format(localize["cast_device"].capitalize(),
                                      localize["not_found"])
            _LOGGER.warning(error)
            return

        client = isinstance(cast, str)

        if command["control"]:
            control = command["control"]
            if client:
                PA.server.client(cast).proxyThroughServer()
                plex_c = PA.server.client(cast)
            else:
                plex_c = PlexController()
                cast.wait()
                cast.register_handler(plex_c)
            if control == "play":
                plex_c.play()
            elif control == "pause":
                plex_c.pause()
            elif control == "stop":
                plex_c.stop()
            elif control == "jump_forward":
                plex_c.stepForward()
            elif control == "jump_back":
                plex_c.stepBack()
            return

        try:
            result = find_media(command, command["media"], PA.lib)
            media = video_selection(command, result["media"],
                                    result["library"])
        except Exception:
            error = media_error(command, localize)
            if tts_error:
                tts = gTTS(error, lang=lang)
                tts.save(directory + 'error.mp3')
                speech_error = True
            _LOGGER.warning(error)

        if speech_error and not client:
            cast.wait()
            med_con = cast.media_controller
            mp3 = hass.config.api.base_url + "/local/plex_assist_tts/error.mp3"
            med_con.play_media(mp3, 'audio/mpeg')
            med_con.block_until_active()
            return

        _LOGGER.debug("Media: %s", str(media))

        if client:
            _LOGGER.debug("Client: %s", cast)
            PA.server.client(cast).proxyThroughServer()
            plex_c = PA.server.client(cast)
            plex_c.playMedia(media)
        else:
            _LOGGER.debug("Cast: %s", cast.name)
            plex_c = PlexController()
            cast.wait()
            cast.register_handler(plex_c)
            play_media(cast, plex_c, media)