ed trx850
ed trx850

Reputation: 1

Bluez 5.48 - How to force the Bluetooth transport state from active to idle - embedded sink end

I have the usual situation where iOS applications are not providing pause and play signals to the sink via AVRCP DBus signalling. Android is fine. The only indication of a paused stream on many iOS apps ( if still maximised ) is the transport state will go idle after some time. If the user toggles between pause and play there's no way of knowing this sink end ( i.e. embedded speaker ) apart from actual audio. Android will signal pause and play over AVRCP on the apps I've tested. On iOS once the transport is idle a "play" will immediately place the transport back into an active state. So... Is there a way, Bash, Python, C or whatever that I can force the transport of a connected device ( i.e. iPad ) from active=>idle from the embedded sink side? If it were possible I would then know whenever "play" is pressed making the transport active again. Thanks!

Upvotes: 0

Views: 1021

Answers (1)

Parthiban
Parthiban

Reputation: 2330

In short, you need to listen to PropertiesChanged signal on org.bluez.MediaTransport1 interface and parse the signal for state change.

You can register to Bluez DBUS interface as below during initialization.

g_dbus_connection_signal_subscribe(conn, "org.bluez", "org.freedesktop.DBus.Properties",
                "PropertiesChanged", NULL, "org.bluez.MediaTransport1", G_DBUS_SIGNAL_FLAGS_NONE,
                bluez_signal_transport_changed, NULL, NULL);

Below sample is the functionality which parses for state change signal,

static void bluez_signal_transport_changed(GDBusConnection *conn, const gchar *sender,
        const gchar *path, const gchar *interface, const gchar *signal, GVariant *params,
        void *userdata) {
    (void)conn;
    (void)sender;
    (void)interface;
    (void)userdata;

    const gchar *signature = g_variant_get_type_string(params);
    GVariantIter *properties = NULL;
    GVariantIter *unknown = NULL;
    GVariant *value = NULL;
    struct ba_transport *t;
    const char *iface;
    const char *key;

    if (strcmp(signature, "(sa{sv}as)") != 0) {
        error("Invalid signature for %s: %s != %s", signal, signature, "(sa{sv}as)");
        goto fail;
    }    

    g_variant_get(params, "(&sa{sv}as)", &iface, &properties, &unknown);
    debug("Signal: %s: %s", signal, iface);

    while (g_variant_iter_next(properties, "{&sv}", &key, &value)) {

        if (strcmp(key, "State") == 0) {

            if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
                error("Invalid argument type for %s: %s != %s", key,
                        g_variant_get_type_string(value), "s");
                goto fail;
            }

             printf("state is %s\n", g_variant_get_string(value, NULL));  
        }

        g_variant_unref(value);
        value = NULL;
    }

fail:
    if (properties != NULL)
        g_variant_iter_free(properties);
    if (value != NULL)
        g_variant_unref(value);
}

Where g_variant_get_string(value, NULL)) will provide you the current state and you decide the SINK operation based on the current state.

Upvotes: 1

Related Questions