/********************
 * fact_field_value
 ********************/
static char *
fact_field_value(OhmFact *fact, char *field, char *buf, size_t size)
{
    GValue *value, gstr = {0,};
    
    if ((value = ohm_fact_get(fact, field)) == NULL)
        return NULL;

    if (G_VALUE_HOLDS_STRING(value)) {
        snprintf(buf, size, (char *)g_value_get_string(value));
        return buf;
    }

    if (!g_value_type_transformable(G_VALUE_TYPE(value), G_TYPE_STRING))
        return NULL;
            
    g_value_init(&gstr, G_TYPE_STRING);
    if (!g_value_transform(value, &gstr))
        return NULL;
            
    snprintf(buf, size, "%s", g_value_get_string(&gstr));
    g_value_unset(&gstr);
    
    return buf;
}
Beispiel #2
0
static int profile_save_state(OhmFact *fact)
{
    FILE *fp;
    GSList *l;
    GQuark  q;
    const gchar *key;
    GValue *value;
    int err;
    
    if ((fp = fopen(PROFILE_SAVE_PATH, "w")) == NULL)
        return errno;

    for (l = ohm_fact_get_fields(fact); l != NULL; l = l->next) {
        q = (GQuark)GPOINTER_TO_INT(l->data);
        key = g_quark_to_string(q);
        value = ohm_fact_get(fact, key);

        if ((err = save_field(fp, key, value)) != 0) {
            fclose(fp);
            unlink(PROFILE_SAVE_PATH);
            return err;
        }
    }
    
    fflush(fp);
    /* fdatasync(fileno(fp)); */
    fclose(fp);

    OHM_INFO("Profile state saved.");
    return 0;
}
Beispiel #3
0
/* return TRUE if really disconnected, FALSE otherwise */
static gboolean disconnect_device(OhmFact *fact, const gchar *type)
{
    GValue *gval;
    
    OHM_DEBUG(DBG_BT, "Disconnecting fact %p profile %s", fact, type);

    if (!fact) {
        return FALSE;
    }

    gval = ohm_fact_get(fact, type);
    
    if (gval &&
            G_VALUE_TYPE(gval) == G_TYPE_STRING) {

        OHM_DEBUG(DBG_BT, "%s profile to be disconnected", type);
        dres_accessory_request(type, -1, 0);

        if (strcmp(type, BT_TYPE_HSP) == 0) {
            /* HSP device goes to disconnected state. We need to forget the
             * bluetooth override state. */
            run_policy_hook("bthsp_disconnect", 0, NULL);
        }
        return TRUE;
    }
    OHM_DEBUG(DBG_BT, "Could not get type information from the fact");

    return FALSE;
}
Beispiel #4
0
static gboolean bt_any_to_disconnected(const gchar *type,
        const gchar *path,
        enum bt_state prev_state,
        enum bt_state new_state)
{
    (void) new_state;
    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    OhmFact *bt_connected = bt_get_connected(path);
    GValue *gval = NULL;

    OHM_DEBUG(DBG_BT, "running dres with type %s and setting device off", type);
    
    if (!bt_connected)
        return FALSE;

    if (prev_state == BT_STATE_NONE ||
        prev_state == BT_STATE_CONNECTING ||
        prev_state == BT_STATE_DISCONNECTED ||
        !disconnect_device(bt_connected, type)) {
        OHM_DEBUG(DBG_BT, "there was nothing to disconnect");
    }

    /* see if the other profiles are also disconnected: if yes,
     * remove the fact */

    if (strcmp(type, BT_TYPE_A2DP) == 0) {
        gval = ohm_fact_get(bt_connected, BT_TYPE_HSP);
    }
    else {
        gval = ohm_fact_get(bt_connected, BT_TYPE_A2DP);
    }

    if ((gval == NULL ||
                G_VALUE_TYPE(gval) != G_TYPE_STRING ||
                strcmp(g_value_get_string(gval), BT_STATE_DISCONNECTED_S) == 0)) {
        ohm_fact_store_remove(fs, bt_connected);
        g_object_unref(bt_connected);
        bt_connected = NULL;
    }

    /* this is now ran in disconnect_device */
    /* dres_accessory_request(type, -1, 0); */

    return TRUE;
}
Beispiel #5
0
static void profile_value_change(const char *profile, const char *key,
                                 const char *val, const char *type, void *dummy)
{

    /* A value has changed in the currently active value */

    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    OhmFact *fact = NULL;

    /* get the previous fact with the profile name */
    GSList *list = ohm_fact_store_get_facts_by_name(fs, FACTSTORE_PROFILE);
    
    (void) profile;
    (void) type;
    (void) dummy;

    OHM_DEBUG(DBG_PROFILE, "profile value change: '%s', '%s'", key, val);

    if (g_slist_length(list) != 1) {
        OHM_DEBUG(DBG_PROFILE, "Error: there isn't a unique profile fact");
        return;
    }
    fact = list->data;
    if (fact && key) {
        GValue *gval = NULL;
        
        gval = ohm_fact_get(fact, key);
        if (gval &&
                G_VALUE_TYPE(gval) == G_TYPE_STRING &&
                strcmp(val, g_value_get_string(gval)) == 0) {
        
            /* the value is already there, no need to trigger an update */
            return;
        }

        gval = NULL;

        /* change the value */
        if (val)
            gval = ohm_value_from_string(val);

        OHM_DEBUG(DBG_PROFILE, "changing key %s with new value '%s'", key, val);
        ohm_fact_set(fact, key, gval);
    }
    else {
        OHM_DEBUG(DBG_PROFILE, "Error, no facts or empty key");
    }

    return;
}
Beispiel #6
0
static gboolean hsp_status_defined(OhmFact *fact)
{
    GValue *gval;

    if (!fact)
        return FALSE;

    gval = ohm_fact_get(fact, "hsp");

    if (gval == NULL)
        return FALSE;

    return TRUE;
}
Beispiel #7
0
static gboolean get_status(OhmFact *fact, const gchar *hfp_or_hsp)
{
    GValue *gval;

    if (!fact)
        return FALSE;

    gval = ohm_fact_get(fact, hfp_or_hsp);

    if (gval &&
            G_VALUE_TYPE(gval) == G_TYPE_INT &&
            g_value_get_int(gval) == 1)
        return TRUE;

    return FALSE;
}
/********************
 * fact_field_term
 ********************/
static int
fact_field_term(OhmFact *fact, char *field, term_t term)
{
    GValue *value;
    int     i;
    double  d;
    char   *s;

    if ((value = ohm_fact_get(fact, field)) == NULL)
        return FALSE;

    switch (G_VALUE_TYPE(value)) {
    case G_TYPE_INT:
        i = g_value_get_int(value);
        PL_put_integer(term, i); 
        break;
    case G_TYPE_UINT:
        i = g_value_get_uint(value);
        PL_put_integer(term, i); 
        break;
    case G_TYPE_LONG:
        i = g_value_get_long(value);
        PL_put_integer(term, i);
        break;
    case G_TYPE_ULONG:
        i = g_value_get_ulong(value);
        PL_put_integer(term, i);
        break;
    case G_TYPE_DOUBLE: 
        d = g_value_get_double(value);
        PL_put_float(term, d);
        break;
    case G_TYPE_FLOAT:
        d = 1.0 * g_value_get_float(value);
        PL_put_float(term, d);
        break;
    case G_TYPE_STRING:
        s = (char *)g_value_get_string(value);
        PL_put_atom_chars(term, s);
        break;
    default:
        return FALSE;
    }

    return TRUE;
}
Beispiel #9
0
/* get the fact representing the connected device */
static OhmFact * bt_get_connected(const gchar *path)
{
    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    OhmFact *ret = NULL;
    GSList *e, *list = ohm_fact_store_get_facts_by_name(fs, BT_DEVICE);

    for (e = list; e != NULL; e = g_slist_next(e)) {
        OhmFact *tmp = (OhmFact *) e->data;
        GValue *gval = ohm_fact_get(tmp, "bt_path");
        if (gval && G_VALUE_TYPE(gval) == G_TYPE_STRING
                && strcmp(path, g_value_get_string(gval)) == 0) {
            ret = e->data;
            break;
        }
    }

    return ret;
}
Beispiel #10
0
static int get_args(OhmFact *fact, argdsc_t *argdsc, void *args)
{
    argdsc_t *ad;
    GValue   *gv;
    void     *vptr;

    if (fact == NULL)
        return FALSE;

    for (ad = argdsc;    ad->type != argtype_invalid;   ad++) {
        vptr = args + ad->offs;

        if ((gv = ohm_fact_get(fact, ad->name)) == NULL)
            continue;

#if 0
        OHM_DEBUG(DBG_ACTION, "Got value type %d", G_VALUE_TYPE(gv));
#endif

        switch (ad->type) {

        case argtype_string:
            if (G_VALUE_TYPE(gv) == G_TYPE_STRING)
                *(const char **)vptr = g_value_get_string(gv);
            break;

        case argtype_integer:
            if (G_VALUE_TYPE(gv) == G_TYPE_INT)
                *(int *)vptr = g_value_get_int(gv);
            break;

        case argtype_unsigned:
            if (G_VALUE_TYPE(gv) == G_TYPE_ULONG)
                *(unsigned long *)vptr = g_value_get_ulong(gv);
            break;

        default:
            break;
        }
    }

    return TRUE;
}
Beispiel #11
0
static void test_fact_store_transaction_push_and_commit (void) {
	OhmFactStore* fs;
	OhmFactStoreView* v;
	OhmFactStoreView* v2;
	OhmFactStoreView* tpv;
	OhmPattern* _tmp0;
	OhmPattern* _tmp1;
	OhmFact* fact;
	GValue* val;
	fs = ohm_fact_store_new ();
	v = ohm_fact_store_new_view (fs, NULL);
	v2 = ohm_fact_store_new_view (fs, NULL);
	tpv = ohm_fact_store_new_transparent_view (fs, NULL);
	_tmp0 = NULL;
	ohm_fact_store_view_add (v, OHM_STRUCTURE ((_tmp0 = ohm_pattern_new ("org.test.match"))));
	(_tmp0 == NULL ? NULL : (_tmp0 = (g_object_unref (_tmp0), NULL)));
	_tmp1 = NULL;
	ohm_fact_store_view_add (v2, OHM_STRUCTURE ((_tmp1 = ohm_pattern_new ("org.freedesktop.hello"))));
	(_tmp1 == NULL ? NULL : (_tmp1 = (g_object_unref (_tmp1), NULL)));
	_tmp1 = NULL;
	ohm_fact_store_view_add (tpv, OHM_STRUCTURE ((_tmp1 = ohm_pattern_new ("org.test.match"))));
	(_tmp1 == NULL ? NULL : (_tmp1 = (g_object_unref (_tmp1), NULL)));
	_tmp1 = NULL;
	/* insertion*/
	ohm_fact_store_transaction_push (fs);
	{
		fact = ohm_fact_new ("org.test.match");
		ohm_fact_set (fact, "field", ohm_value_from_int (42));
		ohm_fact_store_insert (fs, fact);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.match")) == 1);
		g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 0);
		g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 1);
	}
	ohm_fact_store_transaction_pop (fs, FALSE);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 1);
	/* and from the fact store*/
	g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.match")) == 1);
	ohm_fact_set (fact, "field", ohm_value_from_int (43));
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 2);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 2);
	ohm_fact_store_transaction_push (fs);
	{
		ohm_fact_store_remove (fs, fact);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.match")) == 0);
		g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 2);
		g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 3);
	}
	ohm_fact_store_transaction_pop (fs, FALSE);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 3);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 3);
	g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.match")) == 0);
	/* update*/
	fact = ohm_fact_new ("org.test.match");
	ohm_fact_set (fact, "field", ohm_value_from_int (41));
	ohm_fact_store_insert (fs, fact);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 4);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 4);
	ohm_fact_store_transaction_push (fs);
	{
		GValue* val;
		val = ((GValue*) ohm_fact_get (fact, "field"));
		g_assert (g_value_get_int (val) == 41);
		ohm_fact_set (fact, "field", ohm_value_from_int (42));
		val = ((GValue*) ohm_fact_get (fact, "field"));
		g_assert (g_value_get_int (val) == 42);
		g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 4);
		g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 5);
	}
	ohm_fact_store_transaction_pop (fs, FALSE);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 5);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (tpv)->change_set)) == 5);
	val = ((GValue*) ohm_fact_get (fact, "field"));
	g_assert (g_value_get_int (val) == 42);
	(fs == NULL ? NULL : (fs = (g_object_unref (fs), NULL)));
	(v == NULL ? NULL : (v = (g_object_unref (v), NULL)));
	(v2 == NULL ? NULL : (v2 = (g_object_unref (v2), NULL)));
	(fact == NULL ? NULL : (fact = (g_object_unref (fact), NULL)));
}
Beispiel #12
0
static int is_spurious_event(char *device, int driver, int connected)
{
    /*
     * Filter out obviously spurious/duplicate events. Spurious events are
     * events that obviously do not represent any state change (eg. getting
     * a connected=0 event while already in disconnected state).
     */

    GSList  *list;
    OhmFact *fact;
    GValue  *gval;
    int      val, dmatch, cmatch, spurious = FALSE;
    OhmFactStore *store;

    store = ohm_fact_store_get_fact_store();
    list  = ohm_fact_store_get_facts_by_name(store, FACT_DEVICE_ACCESSIBLE);
    for ( ; list ; list = list->next) {
        fact = (OhmFact *)list->data;
        gval = ohm_fact_get(fact, "name");

        if (!gval || G_VALUE_TYPE(gval) != G_TYPE_STRING)
            continue;

        if (strcmp(g_value_get_string(gval), device))
            continue;

        if (driver != -1 && (gval = ohm_fact_get(fact, "driver")) != NULL) {
            switch (G_VALUE_TYPE(gval)) {
            case G_TYPE_INT:   val = g_value_get_int(gval);   break;
            case G_TYPE_UINT:  val = g_value_get_uint(gval);  break;
            case G_TYPE_LONG:  val = g_value_get_long(gval);  break;
            case G_TYPE_ULONG: val = g_value_get_ulong(gval); break;
            default:           val = driver;    /* ignored (ie. match) */
            }
            dmatch = (val == driver);
        }
        else
            dmatch = TRUE;
        
        if (connected != -1 && (gval=ohm_fact_get(fact,"connected")) != NULL) {
            switch (G_VALUE_TYPE(gval)) {
            case G_TYPE_INT:   val = g_value_get_int(gval);   break;
            case G_TYPE_UINT:  val = g_value_get_uint(gval);  break;
            case G_TYPE_LONG:  val = g_value_get_long(gval);  break;
            case G_TYPE_ULONG: val = g_value_get_ulong(gval); break;
            default:           val = connected; /* ignored (ie. match) */
            }
            cmatch = (val == connected);
        }
        else
            cmatch = TRUE;
        
        spurious = dmatch && cmatch; /* no change is a spurious event */
        break;
    }

    OHM_DEBUG(DBG_INFO, "%s, driver: %d, connected: %d is %sa spurious event",
              device, driver, connected, spurious ? "" : "not ");

    return spurious;
}
Beispiel #13
0
static void get_properties_update_fact_cb (DBusPendingCall *pending, void *user_data)
{
    DBusMessage *reply = NULL;
    DBusMessageIter iter, array_iter, dict_iter, variant_iter, uuid_iter;
    gchar **dbus_data = user_data;
    gchar *path = dbus_data[0];
    gchar *interface = dbus_data[1];
    gboolean is_hfp = FALSE, is_hsp = FALSE;
    OhmFact *bt_connected = NULL;

    g_free(dbus_data);

    if (pending == NULL) 
        goto error;

    reply = dbus_pending_call_steal_reply(pending);
    dbus_pending_call_unref(pending);
    pending = NULL;

    if (reply == NULL) {
        goto error;
    }

    if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
        goto error;
    }

    dbus_message_iter_init(reply, &iter);

    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
        goto error;
    }

    dbus_message_iter_recurse(&iter, &array_iter);

    while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_DICT_ENTRY) {

        /* the arg type will be DBUS_TYPE_INVALID at the end of the
         * array */

        gchar *key = NULL;
        int type;

        /* process the dicts */
        dbus_message_iter_recurse(&array_iter, &dict_iter);

        /* key must be string */
        if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
            goto error;
        }
        dbus_message_iter_get_basic(&dict_iter, &key);

        /* go on to the value */
        dbus_message_iter_next(&dict_iter);

        dbus_message_iter_recurse(&dict_iter, &variant_iter);
        type = dbus_message_iter_get_arg_type(&variant_iter);

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

            if (type == DBUS_TYPE_ARRAY) {
                dbus_message_iter_recurse(&variant_iter, &uuid_iter);
                while (dbus_message_iter_get_arg_type(&uuid_iter) == DBUS_TYPE_STRING) {
                    gchar *uuid = NULL;

                    dbus_message_iter_get_basic(&uuid_iter, &uuid);

                    if (!uuid)
                        break;

                    else if (strcmp(uuid, HFP_UUID) == 0) {
                        is_hfp = TRUE;
                    }
                    else if (strcmp(uuid, HSP_UUID) == 0) {
                        is_hsp = TRUE;
                    }
                    dbus_message_iter_next(&uuid_iter);
                }
            }
            else {
                OHM_DEBUG(DBG_BT, "Error: type '%u'\n",
                        dbus_message_iter_get_arg_type(&dict_iter));
            }
        }
        dbus_message_iter_next(&array_iter);
    }

    /* get the BT fact */
    OHM_DEBUG(DBG_BT, "Device %s %s HFP support",
            path, is_hfp ? "has" : "has not");

    OHM_DEBUG(DBG_BT, "Device %s %s HSP support",
            path, is_hsp ? "has" : "has not");

    if ((bt_connected = bt_get_connected(path)) != NULL) {

        GValue *gval_state = ohm_fact_get(bt_connected, BT_TYPE_HSP);
        GValue *gval_prev_state = ohm_fact_get(bt_connected, "bthsp_prev_state");
        const gchar *state = NULL, *prev_state = NULL;
        gboolean run_dres;

        define_hfp_status(bt_connected, is_hfp);
        define_hsp_status(bt_connected, is_hsp);

        if (gval_state != NULL &&
                G_VALUE_TYPE(gval_state) == G_TYPE_STRING) {
            state = g_value_get_string(gval_state);
        }

        if (gval_prev_state != NULL &&
                G_VALUE_TYPE(gval_prev_state) == G_TYPE_STRING) {
            prev_state = g_value_get_string(gval_prev_state);
        }

        OHM_DEBUG(DBG_BT, "running state transition from %s to %s from HFP/HSP status cb",
                prev_state ? prev_state : "NULL", state ? state : "NULL");

        run_dres = bt_state_transition(BT_TYPE_HSP, path, 
                map_to_state(prev_state), map_to_state(state));

        dres_all();
    }

error:

    if (reply)
        dbus_message_unref (reply);

    g_free(path);
    g_free(interface);

    return;
}
Beispiel #14
0
static gboolean bt_state_changed(const gchar *type,
        const gchar *path,
        const gchar *state)
{
    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    gchar *prev_state = NULL;
    OhmFact *bt_connected = bt_get_connected(path);
    gboolean run_dres = FALSE;
    GValue *gval_state;
    gboolean bt_audio_connected = FALSE;

    //OHM_DEBUG(DBG_BT, "type: %s, state: %s", type, state);

    if (strcmp(type, BT_TYPE_AUDIO) == 0) {
        if (bt_connected) {
            gval_state = ohm_value_from_string(state);
            ohm_fact_set(bt_connected, type, gval_state);
        }

        if (strcmp(state, BT_STATE_CONNECTED_S) == 0) {
            /* Get a2dp and hsp status if AudioSink or Headset changed to
             * connected or playing before Audio state changed to connected. */
            get_properties(path, BT_INTERFACE_A2DP, get_properties_cb);
            get_properties(path, BT_INTERFACE_HSP, get_properties_cb);
        }

        return TRUE;
    }

    if(bt_connected) {
        gval_state = ohm_fact_get(bt_connected, BT_TYPE_AUDIO);
        if (gval_state != NULL && G_VALUE_TYPE(gval_state) == G_TYPE_STRING) {
            bt_audio_connected =
                strcmp(g_value_get_string(gval_state), BT_STATE_CONNECTED_S) == 0 ? TRUE : FALSE;
        }
    }

    /* In pulseaudio module-bluetooth-device is loaded after BT Audio interface
     * gets connected. Need to wait until then to be able to route audio. */
    if ((strcmp(state, BT_STATE_CONNECTED_S) == 0 || strcmp(state, BT_STATE_PLAYING_S) == 0)
            && !bt_audio_connected) {
        OHM_DEBUG(DBG_BT, "type: %s, state: %s transition not allowed.", type, state);
        return TRUE;
    }


    /* Type is either HSP or A2DP. HFP is distinguished from HSW by a
     * flag in the BT fact. */

    if (!bt_connected) {
        GValue *gval = NULL;

        /* first time: create a new fact */
        /* TODO: check that this doesn't leak memory! */
        bt_connected = ohm_fact_new(BT_DEVICE);

        /* TODO: set the bthsp and bta2dp fields to "na" or "unknown"
         * values */
        if (bt_connected == NULL) {
            OHM_DEBUG(DBG_BT, "could not create the BT fact!");
            goto error;
        }
        else {

            /* add the object path to the bluetooth fact in order to
             * remember the device */

            gval = ohm_value_from_string(path);
            ohm_fact_set(bt_connected, "bt_path", gval);

            ohm_fact_store_insert(fs, bt_connected);
        }
    }
    else {
        gval_state = ohm_fact_get(bt_connected, type);

        if (gval_state != NULL &&
                G_VALUE_TYPE(gval_state) == G_TYPE_STRING) {
            /* copy the value so that we can overwrite the one in the
             * fact */
            prev_state = g_strdup(g_value_get_string(gval_state));
        }
    }

    OHM_DEBUG(DBG_BT, "type: %s, prev_state: %s, state: %s",
            type, prev_state ? prev_state : "NULL", state);

    gval_state = ohm_value_from_string(state);
    ohm_fact_set(bt_connected, type, gval_state);

    if (strcmp(type, BT_TYPE_HSP) == 0) {
        /* check if we already have the information about the accurate
         * mono profile status */
        if (!hfp_status_defined(bt_connected) ||
                !hsp_status_defined(bt_connected)) {

            /* We don't know the HFP or HSP status yet. Process the dres
             * only after we know the status. */

            OHM_DEBUG(DBG_BT, "querying HFP/HSP state for device %s", path);

            if (prev_state) {
                GValue *gval_prev_state = ohm_value_from_string(prev_state);
                ohm_fact_set(bt_connected, "bthsp_prev_state", gval_prev_state);
            }

            if (get_properties(path, BT_INTERFACE_DEVICE, get_properties_update_fact_cb)) {
                /* continue processing in the callback */
                goto end;
            }
        }
    }

    OHM_DEBUG(DBG_BT, "running state transition from %s to %s from BT status_changed cb",
            prev_state ? prev_state : "NULL", state ? state : "NULL");

    if (prev_state && state && strcmp(prev_state, BT_STATE_CONNECTING_S) == 0
        && strcmp(state, BT_STATE_PLAYING_S) == 0) {
        /* When state transition is not allowed state might change to playing.
         * In this case state change is from connecting to playing, and connected state
         * transition is not done. We need manually do it first */
        run_dres = bt_state_transition(type, path,
            map_to_state(prev_state), map_to_state(BT_STATE_CONNECTED_S));

        if (run_dres)
            dres_all();
    }

    run_dres = bt_state_transition(type, path, 
            map_to_state(prev_state), map_to_state(state));

    if (run_dres)
        dres_all();

end:
    g_free(prev_state);
    return TRUE;

error:

    return FALSE;
}
Beispiel #15
0
static int get_field(OhmFact *fact, fsif_fldtype_t type,char *name,void *vptr)
{
    GValue  *gv;

    if (!fact || !name || !(gv = ohm_fact_get(fact, name))) {
        OHM_ERROR("resource: [%s] Cant find field %s",
                  __FUNCTION__, name?name:"<null>");
        goto return_empty_value;
    }

    switch (type) {

    case fldtype_string:
        if (G_VALUE_TYPE(gv) != G_TYPE_STRING)
            goto type_mismatch;
        else
            *(const char **)vptr = g_value_get_string(gv);
        break;

    case fldtype_integer:
        switch (G_VALUE_TYPE(gv)) {
        case G_TYPE_LONG: *(long *)vptr = g_value_get_long(gv); break;
        case G_TYPE_INT:  *(long *)vptr = g_value_get_int(gv);  break;
        default:          goto type_mismatch;
        }
        break;

    case fldtype_unsignd:
        if (G_VALUE_TYPE(gv) != G_TYPE_ULONG)
            goto type_mismatch;
        else
            *(unsigned long *)vptr = g_value_get_ulong(gv);
        break;

    case fldtype_floating:
        if (G_VALUE_TYPE(gv) != G_TYPE_DOUBLE)
            goto type_mismatch;
        else
            *(double *)vptr = g_value_get_double(gv);
        break;

    case fldtype_time:
        if (G_VALUE_TYPE(gv) != G_TYPE_UINT64)
            goto type_mismatch;
        else
            *(time_t *)vptr = g_value_get_uint64(gv);
        break;

    default:
        break;
    }

    return TRUE;

 type_mismatch:
    OHM_ERROR("resource: [%s] Type mismatch when fetching field '%s'",
              __FUNCTION__,name);

 return_empty_value:
    switch (type) {
    case fldtype_string:      *(char              **)vptr = NULL;       break;
    case fldtype_integer:     *(long               *)vptr = 0;          break;
    case fldtype_unsignd:     *(unsigned long      *)vptr = 0;          break;
    case fldtype_floating:    *(double             *)vptr = 0.0;        break;
    case fldtype_time:        *(unsigned long long *)vptr = 0ULL;       break;
    default:                                                            break;
    }

    return FALSE;
}