Пример #1
0
# print(dbus_filter) # /org/example/ca/server


def cb_server_signal_emission(*args):
    """
    Callback on emitting signal from server
    Emitted signal is the value of the counter
    Data is in args[4]. The first item in a tuple.args[4][0]
    """
    data = args[4][0]
    print("Client:", data)


if __name__=="__main__":
    print("Client Starting...")
    # Subscribe to bus to monitor for server signal emissions
    # dbus_filter. E.g. /org/example/ca/server
    bus.subscribe(object = dbus_filter, 
                  signal_fired = cb_server_signal_emission)
    loop.run()

'''
Example of client_test.py...

$ python3 client_test.py
Client Starting...
Client: The random integer for this second is 12
Client: The random integer for this second is 98
Client: The random integer for this second is 6
'''
Пример #2
0
def main(api_endpoint, credentials, project_id, device_model_id, device_id,
         device_config, lang, verbose, input_audio_file, output_audio_file,
         audio_sample_rate, audio_sample_width, audio_iter_size,
         audio_block_size, audio_flush_size, grpc_deadline, once, *args,
         **kwargs):
    """Samples for the Google Assistant API.

    Examples:
      Run the sample with microphone input and speaker output:

        $ python -m googlesamples.assistant

      Run the sample with file input and speaker output:

        $ python -m googlesamples.assistant -i <input file>

      Run the sample with file input and output:

        $ python -m googlesamples.assistant -i <input file> -o <output file>
    """
    # Setup logging.
    logging.basicConfig(level=logging.DEBUG if verbose else logging.INFO)

    # Load OAuth 2.0 credentials.
    try:
        with open(credentials, 'r') as f:
            credentials = google.oauth2.credentials.Credentials(token=None,
                                                                **json.load(f))
            http_request = google.auth.transport.requests.Request()
            credentials.refresh(http_request)
    except Exception as e:
        logging.error('Error loading credentials: %s', e)
        logging.error('Run google-oauthlib-tool to initialize '
                      'new OAuth 2.0 credentials.')
        sys.exit(-1)

# D-Bus preparation
    cv_trigger = Condition(Lock())
    eventq = Queue()
    dbus_obj = DBusSignals()
    loop = GLib.MainLoop()
    system_bus = SystemBus()

    def dbus_handler(sender, object, iface, signal, params):
        # logging.info(sender)
        # logging.info(object)
        # logging.info(signal)
        # logging.info(params)

        logging.debug('Received D-Bus signal: {}'.format(signal))

        if signal == 'trigger':
            cv_trigger.acquire()
            cv_trigger.notify()
            cv_trigger.release()

    pub = system_bus.publish("io.respeaker.respeakerd", dbus_obj)
    sub = system_bus.subscribe(iface='respeakerd.signal',
                               signal_fired=dbus_handler)

    def exit_dbus():
        sub.unsubscribe()
        pub.unpublish()

    # Create an authorized gRPC channel.
    grpc_channel = google.auth.transport.grpc.secure_authorized_channel(
        credentials, http_request, api_endpoint)
    logging.info('Connecting to %s', api_endpoint)

    # Configure audio source and sink.
    audio_device = None
    if input_audio_file:
        audio_source = audio_helpers.WaveSource(
            open(input_audio_file, 'rb'),
            sample_rate=audio_sample_rate,
            sample_width=audio_sample_width)
    else:
        audio_source = audio_device = (audio_device
                                       or audio_helpers.SoundDeviceStream(
                                           sample_rate=audio_sample_rate,
                                           sample_width=audio_sample_width,
                                           block_size=audio_block_size,
                                           flush_size=audio_flush_size))
    if output_audio_file:
        audio_sink = audio_helpers.WaveSink(open(output_audio_file, 'wb'),
                                            sample_rate=audio_sample_rate,
                                            sample_width=audio_sample_width)
    else:
        audio_sink = audio_device = (audio_device
                                     or audio_helpers.SoundDeviceStream(
                                         sample_rate=audio_sample_rate,
                                         sample_width=audio_sample_width,
                                         block_size=audio_block_size,
                                         flush_size=audio_flush_size))
    # Create conversation stream with the given audio source and sink.
    conversation_stream = audio_helpers.ConversationStream(
        source=audio_source,
        sink=audio_sink,
        iter_size=audio_iter_size,
        sample_width=audio_sample_width,
    )

    if not device_id or not device_model_id:
        try:
            with open(device_config) as f:
                device = json.load(f)
                device_id = device['id']
                device_model_id = device['model_id']
                logging.info("Using device model %s and device id %s",
                             device_model_id, device_id)
        except Exception as e:
            logging.warning('Device config not found: %s' % e)
            logging.info('Registering device')
            if not device_model_id:
                logging.error('Option --device-model-id required '
                              'when registering a device instance.')
                exit_dbus()
                sys.exit(-1)
            if not project_id:
                logging.error('Option --project-id required '
                              'when registering a device instance.')
                exit_dbus()
                sys.exit(-1)
            device_base_url = ('https://%s/v1alpha2/projects/%s/devices' %
                               (api_endpoint, project_id))
            device_id = str(uuid.uuid1())
            payload = {
                'id': device_id,
                'model_id': device_model_id,
                'client_type': 'SDK_SERVICE'
            }
            session = google.auth.transport.requests.AuthorizedSession(
                credentials)
            r = session.post(device_base_url, data=json.dumps(payload))
            if r.status_code != 200:
                logging.error('Failed to register device: %s', r.text)
                exit_dbus()
                sys.exit(-1)
            logging.info('Device registered: %s', device_id)
            pathlib.Path(os.path.dirname(device_config)).mkdir(exist_ok=True)
            with open(device_config, 'w') as f:
                json.dump(payload, f)

    device_handler = device_helpers.DeviceRequestHandler(device_id)

    @device_handler.command('action.devices.commands.OnOff')
    def onoff(on):
        if on:
            logging.info('Turning device on')
        else:
            logging.info('Turning device off')

    # If file arguments are supplied:
    # exit after the first turn of the conversation.
    if input_audio_file or output_audio_file:
        with SampleAssistant(lang, device_model_id, device_id,
                             conversation_stream, grpc_channel, grpc_deadline,
                             device_handler, eventq) as assistant:
            dbus_obj.ready()
            assistant.assist()
            exit_dbus()
            return

    # else it's a long term run

    def assistant_thread(conversation_stream_):

        with SampleAssistant(lang, device_model_id, device_id,
                             conversation_stream_, grpc_channel, grpc_deadline,
                             device_handler, eventq) as assistant:

            dbus_obj.ready()

            # If no file arguments supplied:
            # keep recording voice requests using the microphone
            # and playing back assistant response using the speaker.
            # When the once flag is set, don't wait for a trigger. Otherwise, wait.
            wait_for_user_trigger = not once
            # capture device should always be opened when not playing
            conversation_stream_.start_recording()

            while True:
                if wait_for_user_trigger:
                    logging.info("speak hotword to wake up")
                    cv_trigger.acquire()
                    cv_trigger.wait()
                    cv_trigger.release()
                    logging.info("wake up!")

                continue_conversation = False
                try:
                    continue_conversation = assistant.assist()
                except PortAudioError as e:
                    logging.warn('PortAudio Error: {}'.format(str(e)))
                    eventq.put('on_idle')
                # wait for user trigger if there is no follow-up turn in
                # the conversation.
                wait_for_user_trigger = not continue_conversation

                # If we only want one conversation, break.
                if once and (not continue_conversation):
                    break
        exit_dbus()
        logging.debug('Exit from the assistant thread...')
        loop.quit()

    def event_process_thread():
        while True:
            event = eventq.get()
            if event == 'on_listen':
                dbus_obj.on_listen()
            elif event == 'on_think':
                dbus_obj.on_think()
            elif event == 'on_speak':
                dbus_obj.on_speak()
            elif event == 'on_idle':
                dbus_obj.on_idle()
            time.sleep(0.5)

    def on_exit(sig):
        exit_dbus()
        loop.quit()
        logging.info("Quit...")

    setup_signals(
        signals=[sys_signal.SIGINT, sys_signal.SIGTERM, sys_signal.SIGHUP],
        handler=on_exit)

    # make conversation_stream writable inside thread
    thrd1 = Thread(target=assistant_thread, args=(conversation_stream, ))
    thrd2 = Thread(target=event_process_thread)
    thrd1.daemon = True
    thrd2.daemon = True
    thrd1.start()
    thrd2.start()

    logging.info("Glib mainloop start running...")
    loop.run()

    dbus_obj.on_idle()
Пример #3
0
class BusClient:
    """
    Base class to use to implement a DbusClient using the sink services
    It automatically manage sink connection/disconnection and offers some abstraction
    of dbus
    """
    def __init__(self, logger=None, c_extension=True, ignored_ep_filter=None):

        # logger
        self.logger = logger or logging.getLogger(__name__)

        # Main loop for events
        self.loop = GLib.MainLoop()

        # Connect to session bus
        self.bus = SystemBus()

        # Manage sink list
        self.sink_manager = SinkManager(
            bus=self.bus,
            on_new_sink_cb=self.on_sink_connected,
            on_sink_removal_cb=self.on_sink_disconnected,
            on_stack_started=self.on_stack_started,
            logger=self.logger,
        )

        self.ignore_ep_filter = ignored_ep_filter

        # Register for packet on Dbus
        if c_extension:
            self.logger.info("Starting dbus client with c extension")
            self.c_extension_thread = DbusEventHandler(
                self._on_data_received_c, self.logger)
        else:
            self.logger.info("Starting dbus client without c extension")
            # Subscribe to all massages received from any sink (no need for
            # connected sink for that)
            self.bus.subscribe(
                signal="MessageReceived",
                object="/com/wirepas/sink",
                signal_fired=self._on_data_received,
            )

            self.c_extension_thread = None

    def _on_data_received_c(
        self,
        sender,
        timestamp,
        src,
        dst,
        src_ep,
        dst_ep,
        travel_time,
        qos,
        hop_count,
        data,
    ):

        # Could be done in C extension if needed by providing list to extension
        if self.ignore_ep_filter is not None and dst_ep in self.ignore_ep_filter:
            self.logger.debug("Message received on ep % filtered out", dst_ep)
            return

        # Get sink name from sender unique name
        name = self.sink_manager.get_sink_name(sender)
        self.on_data_received(
            sink_id=name,
            timestamp=timestamp,
            src=src,
            dst=dst,
            src_ep=src_ep,
            dst_ep=dst_ep,
            travel_time=travel_time,
            qos=qos,
            hop_count=hop_count,
            data=data,
        )

    def _on_data_received(self, sender, object, iface, signal, params):
        # pylint: disable=unused-argument
        # pylint: disable=redefined-builtin
        # filter out endpoint
        if self.ignore_ep_filter is not None and params[
                4] in self.ignore_ep_filter:
            self.logger.debug("Message received on ep % filtered out",
                              params[4])
            return

        # Get sink name from sender unique name
        name = self.sink_manager.get_sink_name(sender)
        self.on_data_received(
            sink_id=name,
            timestamp=params[0],
            src=params[1],
            dst=params[2],
            src_ep=params[3],
            dst_ep=params[4],
            travel_time=params[5],
            qos=params[6],
            hop_count=params[7],
            data=bytearray(params[8]),
        )

    def run(self):
        self.on_start_client()

        # If needed start C extension thread
        if self.c_extension_thread is not None:
            self.c_extension_thread.start()

        # For now, start the GLib loop for even if C extension is
        # in use as some signals are still handled on it. But should not be
        # the case in future. Even without handling signals, this thread takes
        # 30% of one CPU on a rpi3.
        try:
            self.loop.run()
        except KeyboardInterrupt:
            self.loop.quit()

        self.on_stop_client()

    def stop_dbus_client(self):
        """
        Explicitly stop the dbus client
        """
        self.loop.quit()

    # Method should be overwritten by child class
    def on_data_received(
        self,
        sink_id,
        timestamp,
        src,
        dst,
        src_ep,
        dst_ep,
        travel_time,
        qos,
        hop_count,
        data,
    ):
        pass

    def on_sink_connected(self, name):
        pass

    def on_sink_disconnected(self, name):
        pass

    def on_stack_started(self, name):
        pass

    def on_start_client(self):
        pass

    def on_stop_client(self):
        pass
Пример #4
0
bus_name = "org.example.ca.server"
dbus_filter = "/" + "/".join(bus_name.split("."))
# print(dbus_filter) # /org/example/ca/server


def cb_server_signal_emission(*args):
    """
    Callback on emitting signal from server
    Emitted signal is the value of the counter
    Data is in args[4]. The first item in a tuple.args[4][0]
    """
    data = args[4][0]
    print("Client:", data)


if __name__ == "__main__":
    print("Client Starting...")
    # Subscribe to bus to monitor for server signal emissions
    # dbus_filter. E.g. /org/example/ca/server
    bus.subscribe(object=dbus_filter, signal_fired=cb_server_signal_emission)
    loop.run()
'''
Example of client_test.py...

$ python3 client_test.py
Client Starting...
Client: The random integer for this second is 12
Client: The random integer for this second is 98
Client: The random integer for this second is 6
'''
Пример #5
0
        if signal != 'ActiveChanged':
            logging.debug("Not what we are looking for, ignored")
            return

        logging.debug("START OF SIGNAL PROCESSING")

        if signal_msg is True:
            logging.debug("Screensaver now active")
        else:
            logging.info("Running 'on 0\\nas\\nquit' to turn on TV")
            proc = subprocess.Popen(['/usr/bin/cec-client'], stdin=subprocess.PIPE)
            results = proc.communicate(input='on 0\nas\nquit\n'.encode())
            time.sleep(3)
            logging.debug(results[0])
            logging.debug(results[1])
            proc.terminate()
            proc.kill()

        logging.debug("END OF SIGNAL PROCESSING")


    BUS.subscribe(iface=DBUS_INTERFACE, signal_fired=signal_recieved)

    # loop forever, until CTRL+C, or something goes wrong
    try:
        MainLoop().run()
    except KeyboardInterrupt:
        logging.debug('Got CTRL+C, exiting cleanly')
        raise SystemExit

Пример #6
0
def main():

    # enable led power
    en = mraa.Gpio(12)
    if os.geteuid() != 0:
        time.sleep(1)
    en.dir(mraa.DIR_OUT)
    en.write(0)

    pixel_ring.set_brightness(100)
    pixel_ring.think()

    sm = StateMachine()

    def bus_handler(sender, object, iface, signal, params):
        # print(sender)
        # print(object)
        # print(signal)
        # print(params)

        if signal == 'trigger':
            try:
                dir = params[0]
            except:
                dir = 0
            sm.on_detected(dir)
        elif signal == 'on_listen':
            sm.on_listening()
        elif signal == 'on_think':
            sm.on_thinking()
        elif signal == 'on_speak':
            sm.on_speaking()
        elif signal == 'on_idle':
            sm.on_idle()
        elif signal == 'connecting':
            sm.on_thinking()
        elif signal == 'ready':
            sm.on_avs_ready()
        elif signal == 'respeakerd_ready':
            sm.on_respeakerd_ready()

    system_bus = SystemBus()
    loop = GLib.MainLoop()
    sub = system_bus.subscribe(iface='respeakerd.signal',
                               signal_fired=bus_handler)

    def on_exit(sig):
        sub.unsubscribe()
        loop.quit()

    setup_signals(signals=[signal.SIGINT, signal.SIGTERM, signal.SIGHUP],
                  handler=on_exit)

    print("Running...")

    try:
        loop.run()
    except KeyboardInterrupt:
        pass
    finally:
        pixel_ring.off()

    print("Quit...")

    en.write(1)
Пример #7
0
if __name__ == '__main__':

    logging.debug('starting')

    bus = SystemBus()
    if_list = [
        ('org.ofono.Modem', 'PropertyChanged', lambda _a, obj, iface, signal,
         params: mqtt(dev(obj, iface), prop(signal, params))),
        ('org.ofono.VoiceCall', 'PropertyChanged', lambda _a, obj, iface,
         signal, params: mqtt(vcdev(obj, iface), prop(signal, params))),
        ('org.ofono.CallVolume', 'PropertyChanged', lambda _a, obj, iface,
         signal, params: mqtt(dev(obj, iface), prop(signal, params))),
        ('org.ofono.VoiceCallManager', 'PropertyChanged', lambda _a, obj,
         iface, signal, params: mqtt(dev(obj, iface), prop(signal, params))),
        ('org.ofono.VoiceCallManager', 'CallAdded', lambda _a, obj, iface,
         signal, params: mqtt(dev(obj, iface), cadd(signal, params))),
        ('org.ofono.VoiceCallManager', 'CallRemoved', lambda _a, obj, iface,
         signal, params: mqtt(dev(obj, iface), crem(signal, params))),
        ('org.ofono.NetworkRegistration', 'PropertyChanged', lambda _a, obj,
         iface, signal, params: mqtt(dev(obj, iface), prop(signal, params))),
    ]
    [
        bus.subscribe(iface=iface, signal=signal, signal_fired=cb)
        for iface, signal, cb in if_list
    ]

    mqtt("monitor", payload="started", retain=True)

    loop = GLib.MainLoop()
    loop.run()
Пример #8
0
class Central:
    """
    Create a device in a central role and communicate with a peripheral device
    """
    def __init__(self, address):
        self.bus = SystemBus()
        self.mngr = self.bus.get(BLUEZ_SERVICE, '/')
        self._device_path = self._from_device_address(address)
        if self._device_path is None:
            raise KeyError(f'Device address [{address}] is not found.'
                           f'Use bluetoothctl to find what devices are nearby')
        self._adapter_path = '/'.join(self._device_path.split('/')[:-1])
        self.adapter = self.bus.get(BLUEZ_SERVICE,
                                    self._adapter_path)['org.bluez.Adapter1']
        self.device = self.bus.get(BLUEZ_SERVICE, self._device_path)
        self.chrcs = {}
        self._handlers = {}
        self.mainloop = GLib.MainLoop()

    def _from_device_address(self, addr):
        """Look up Device D-Bus object path from device address"""
        mng_objs = self.mngr.GetManagedObjects()
        for path in mng_objs:
            dev_addr = mng_objs[path].get(BLUEZ_DEV_IFACE,
                                          {}).get('Address', '')
            if addr.casefold() == dev_addr.casefold():
                return path
        return None

    def _get_device_chars(self):
        """Find all GATT characteristics for device. Store for look-up later"""
        mng_objs = self.mngr.GetManagedObjects()
        for path in mng_objs:
            chr_uuid = mng_objs[path].get(BLUEZ_CHR_IFACE, {}).get('UUID')
            if path.startswith(self._device_path) and chr_uuid:
                self.chrcs[chr_uuid] = self.bus.get(BLUEZ_SERVICE, path)

    def _get_uuid(self, path):
        """Get the Characteristics UUID from its D-Bus object path"""
        mng_objs = self.mngr.GetManagedObjects()
        return mng_objs[path].get(BLUEZ_CHR_IFACE, {}).get('UUID')

    def connect(self):
        """
        Connect to device.
        Wait for GATT services to be resolved before returning
        """
        self.device.Connect()
        while not self.device.ServicesResolved:
            sleep(0.5)
        self._get_device_chars()

    def disconnect(self):
        """Disconnect from device"""
        self.device.Disconnect()

    def char_write(self, uuid, value):
        """Write value to given GATT characteristic UUID"""
        if uuid.casefold() in self.chrcs:
            self.chrcs[uuid.casefold()].WriteValue(value, {})
        else:
            raise KeyError(f'UUID {uuid} not found')

    def char_read(self, uuid):
        """Read value of given GATT characteristic UUID"""
        if uuid.casefold() in self.chrcs:
            return self.chrcs[uuid.casefold()].ReadValue({})
        raise KeyError(f'UUID {uuid} not found')

    def _chrc_value_update(self, bus_name, path, signal_iface, signal_name,
                           notification):
        """
        Only send notifications to a users event handler when it is a
        GATT characteristics value that has changed
        """
        uuid = self._get_uuid(path)
        iface, props_changed, props_removed = notification
        if iface == BLUEZ_CHR_IFACE and 'Value' in props_changed:
            self._handlers[uuid.casefold()].user_handler(
                props_changed['Value'])

    def on_value_change(self, uuid, handler):
        """
        A function reference which will be called when a property
        value is changed for given GATT characteristic UUID if notifications
        are available
        """
        uuid = uuid.casefold()
        if uuid in self.chrcs:
            if all(('notify' not in self.chrcs[uuid].Flags, 'indicate'
                    not in self.chrcs[uuid].Flags)):
                raise NotImplementedError(
                    f'Notifications are not implemented on {uuid}')
            subs = self.bus.subscribe(iface='org.freedesktop.DBus.Properties',
                                      signal='PropertiesChanged',
                                      object=self.chrcs[uuid]._path,
                                      signal_fired=self._chrc_value_update)
            self._handlers[uuid] = PropChangedHandler(handler, subs)
            self.chrcs[uuid].StartNotify()
        else:
            raise KeyError(f'UUID {uuid} not found')

    def remove_notify(self, uuid):
        """Stop notifications for given GATT characteristic UUID"""
        uuid = uuid.casefold()
        if uuid in self.chrcs and uuid in self._handlers:
            self.chrcs[uuid.casefold()].StopNotify()
            self._handlers[uuid.casefold()].subscription.disconnect()
            del self._handlers[uuid]

    def wait_for_notifications(self):
        """
        Has the effect of block the code from exiting. In the background it
        starts an event loop to listen for updates from the device
        """
        try:
            self.mainloop.run()
        except KeyboardInterrupt:
            self.cleanup()

    def cleanup(self):
        """
        If you have the used `wait_for_notifications`, then this command
        will remove that blocking. This will stop the event loop, remove
        all notification subscriptions, disconnect from the peripheral device.
        """
        self.mainloop.quit()
        all_uuids = list(self._handlers.keys())
        for uuid in all_uuids:
            self.remove_notify(uuid)
        self.disconnect()
Пример #9
0
class Bluetooth:
    def __init__(self, name):
        self.__bus = SystemBus()
        self.__adapter = self.__bus.get(BLUEZ_SERVICE,
                                        'hci0')[INTERFACE['ADAPTER']]
        self.__set_alias(name)
        self.__player = None
        self.__change_callback = None

        self.__bus.subscribe(sender=BLUEZ_SERVICE,
                             signal='PropertiesChanged',
                             arg0=INTERFACE['ADAPTER'],
                             signal_fired=self.__adapter_handler)
        self.__bus.subscribe(sender=BLUEZ_SERVICE,
                             signal='PropertiesChanged',
                             arg0=INTERFACE['MEDIA_CONTROL'],
                             signal_fired=self.__mediacontrol_handler)
        self.__bus.subscribe(sender=BLUEZ_SERVICE,
                             signal='PropertiesChanged',
                             arg0=INTERFACE['MEDIA_PLAYER'],
                             signal_fired=self.__mediaplayer_handler)

    def start_discovery(self):
        self.__powered()
        self.__pairable()
        self.__discoverable()
        return self.__adapter.StartDiscovery()

    def set_on_change(self, callback):
        self.__change_callback = callback

    @property
    def device_name(self):
        device_object = self.__bus.get(
            BLUEZ_SERVICE, self.__player[INTERFACE['MEDIA_PLAYER']].Device)
        device = device_object[INTERFACE['DEVICE']]
        return device.Alias

    @property
    def current_track(self):
        player = self.__player[INTERFACE['MEDIA_PLAYER']]
        return {
            'title': player.Track.get('Title', ''),
            'album': player.Track.get('Album', ''),
            'artist': player.Track.get('Artist', ''),
            'genre': player.Track.get('Genre', ''),
            'track_number': player.Track.get('TrackNumber', 0),
            'number_of_tracks': player.Track.get('NumberOfTracks', 0),
            'duration_ms': player.Track.get('Duration', 0),
            'position_ms': player.Position,
            'status': player.Status.lower()
        }

    def play(self):
        try:
            self.__player[INTERFACE['MEDIA_PLAYER']].Play()
        except GLib.Error:
            log.warning('Can\'t play track, player not ready.')

    def pause(self):
        try:
            self.__player[INTERFACE['MEDIA_PLAYER']].Pause()
        except GLib.Error:
            log.warning('Can\'t pause track, player not ready.')

    def next(self):
        try:
            self.__player[INTERFACE['MEDIA_PLAYER']].Next()
        except GLib.Error:
            log.warning('Can\'t go to next track, player not ready.')

    def previous(self):
        try:
            self.__player[INTERFACE['MEDIA_PLAYER']].Previous()
        except GLib.Error:
            log.warning('Can\'t go to previous track, player not ready.')

    def shuffle(self, setting):
        shuffle_settings = ['off', 'alltracks', 'group']
        if setting not in shuffle_settings:
            return
        try:
            self.__player[INTERFACE['MEDIA_PLAYER']].Shuffle = setting
        except GLib.Error:
            log.warning('Can\'t set shuffle mode to %s, player not ready.',
                        setting)

    def repeat(self, setting):
        repeat_settings = ['off', 'singletrack', 'alltracks', 'group']
        if setting not in repeat_settings:
            return
        try:
            self.__player[INTERFACE['MEDIA_PLAYER']].Repeat = setting
        except GLib.Error:
            log.warning('Can\'t set repeat mode to %s, player not ready.',
                        setting)

    def __get_managed_objects(self):
        object_manager = self.__bus.get(
            BLUEZ_SERVICE, '/')['org.freedesktop.DBus.ObjectManager']
        return object_manager.GetManagedObjects()

    def __set_alias(self, alias):
        self.__adapter.Alias = alias

    def __powered(self):
        self.__adapter.Powered = True

    def __discoverable(self, timeout=90):
        self.__adapter.Discoverable = True
        self.__adapter.DiscoverableTimeout = timeout

    def __pairable(self, timeout=90):
        self.__adapter.Pairable = True
        self.__adapter.PairableTimeout = timeout

    def __get_devices(self):
        objects = self.__get_managed_objects()
        devices_filter = lambda item: INTERFACE['DEVICE'] in item[1]
        return dict(filter(devices_filter, objects.items()))

    def __get_paired_media_devices(self):
        devices = self.__get_devices()
        paired_media_filter = lambda item: item[1][INTERFACE['DEVICE']][
            'Paired'] and INTERFACE['MEDIA_CONTROL'] in item[1]
        return dict(filter(paired_media_filter, devices.items()))

    def __connect_to_paired_media_device(self):
        devices = self.__get_paired_media_devices()
        device_path = list(devices.keys())[0]
        device_object = self.__bus.get(BLUEZ_SERVICE, device_path)
        device = device_object[INTERFACE['DEVICE']]
        if device.Connected:
            log.info('Connected to device %s.', device.Name)
            player_path = device_object[INTERFACE['MEDIA_CONTROL']].Player
            self.__init_player(player_path)
        else:
            try:
                device.Connect()
            except GLib.GError as err:
                log.warning('Can\'t connect to device %s.', device.Alias)

    def __init_player(self, player_path):
        self.__player = self.__bus.get(BLUEZ_SERVICE, player_path)

    def __adapter_handler(self, sender, path, interface, signal, parameters):
        interface, properties, optional = parameters
        if 'Discovering' in properties:
            log.info('Discovering active. Looking for devices.')
        try:
            self.__connect_to_paired_media_device()
        except:
            log.info('No paired devices found.')

    def __mediacontrol_handler(self, sender, path, interface, signal,
                               parameters):
        interface, properties, optional = parameters
        if properties['Connected']:
            if 'Player' in properties:
                self.__init_player(properties['Player'])

    def __mediaplayer_handler(self, sender, path, interface, signal,
                              parameters):
        self.__change_callback()