Пример #1
0
static void test_fact_store_to_string (void) {
	void* p;
	p = NULL;
	{
		OhmFactStore* fs;
		OhmFact* fact;
		OhmFact* _tmp0;
		char* s;
		fs = ohm_fact_store_new ();
		fact = ohm_fact_new ("org.test.match");
		p = fact;
		g_object_add_weak_pointer (G_OBJECT (fact), &p);
		ohm_fact_set (fact, "field1", ohm_value_from_string ("test1"));
		ohm_fact_set (fact, "field2", ohm_value_from_int (42));
		ohm_fact_store_insert (fs, fact);
		_tmp0 = NULL;
		fact = (_tmp0 = ohm_fact_new ("org.test.match"), (fact == NULL ? NULL : (fact = (g_object_unref (fact), NULL))), _tmp0);
		ohm_fact_set (fact, "field3", ohm_value_from_int (42));
		ohm_fact_store_insert (fs, fact);
		s = ohm_fact_store_to_string (fs);
		g_assert (strstr (s, "field1 = ") != NULL);
		g_assert (strstr (s, "field2 = 42") != NULL);
		g_assert (p != NULL);
		(fs == NULL ? NULL : (fs = (g_object_unref (fs), NULL)));
		(fact == NULL ? NULL : (fact = (g_object_unref (fact), NULL)));
		s = (g_free (s), NULL);
	}
	g_assert (p == NULL);
}
Пример #2
0
static void test_fact_store_pattern_delete (void) {
#define FACT_NAME "com.nokia.ahoy"

	OhmFactStore     *fs;
	OhmFactStoreView *v1, *v2;
	OhmPattern       *p1, *p2;
	OhmFact          *f;

	fs = ohm_fact_store_new();
	v1 = ohm_fact_store_new_view(fs, NULL);
	v2 = ohm_fact_store_new_view(fs, NULL);
	
	p1 = ohm_pattern_new(FACT_NAME);
	p2 = ohm_pattern_new(FACT_NAME);
	
	ohm_fact_store_view_add(v1, OHM_STRUCTURE(p1));
	ohm_fact_store_view_add(v2, OHM_STRUCTURE(p2));

	g_object_unref(p1);
	g_object_unref(p2);

	f = ohm_fact_new(FACT_NAME);
	ohm_fact_store_insert(fs, f);

	ohm_fact_store_view_remove(v1, OHM_STRUCTURE(p1));
	g_object_unref(v1);
	
	f = ohm_fact_new(FACT_NAME);
	ohm_fact_store_insert(fs, f);
}
Пример #3
0
static void test_fact_store_view_two (void) {
	OhmFactStore* fs;
	OhmFactStoreView* v;
	OhmFactStoreView* v2;
	OhmPattern* _tmp0;
	OhmPattern* _tmp1;
	OhmFact* _tmp2;
	OhmFact* _tmp3;
	OhmFact* _tmp4;
	OhmFact* _tmp5;
	OhmFact* f;
	fs = ohm_fact_store_new ();
	v = ohm_fact_store_new_view (fs, NULL);
	v2 = ohm_fact_store_new_view (fs, NULL);
	_tmp0 = NULL;
	ohm_fact_store_view_add (v, OHM_STRUCTURE ((_tmp0 = ohm_pattern_new ("org.freedesktop.hello"))));
	(_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)));
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 0);
	_tmp2 = NULL;
	ohm_fact_store_insert (fs, (_tmp2 = ohm_fact_new ("org.freedesktop.match2")));
	(_tmp2 == NULL ? NULL : (_tmp2 = (g_object_unref (_tmp2), NULL)));
	_tmp3 = NULL;
	ohm_fact_store_insert (fs, (_tmp3 = ohm_fact_new ("org.freedesktop.hello")));
	(_tmp3 == NULL ? NULL : (_tmp3 = (g_object_unref (_tmp3), NULL)));
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 1);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v2)->change_set)) == 1);
	_tmp4 = NULL;
	ohm_fact_store_insert (fs, (_tmp4 = ohm_fact_new ("org.freedesktop.hello")));
	(_tmp4 == NULL ? NULL : (_tmp4 = (g_object_unref (_tmp4), NULL)));
	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 (v2)->change_set)) == 2);
	ohm_fact_store_change_set_reset (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set);
	g_assert (g_slist_length (ohm_fact_store_change_set_get_matches (OHM_FACT_STORE_SIMPLE_VIEW (v)->change_set)) == 0);
	_tmp5 = NULL;
	ohm_fact_store_insert (fs, (_tmp5 = ohm_fact_new ("org.freedesktop.hello")));
	(_tmp5 == NULL ? NULL : (_tmp5 = (g_object_unref (_tmp5), NULL)));
	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 (v2)->change_set)) == 3);
	f = ohm_fact_new ("org.freedesktop.self");
	ohm_fact_store_change_set_reset (OHM_FACT_STORE_SIMPLE_VIEW (v2)->change_set);
	ohm_fact_store_view_add (v, OHM_STRUCTURE (f));
	ohm_fact_store_insert (fs, f);
	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 (v2)->change_set)) == 0);
	(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)));
	(f == NULL ? NULL : (f = (g_object_unref (f), NULL)));
}
Пример #4
0
int fsif_add_factstore_entry(char *name, fsif_field_t *fldlist)
{
    OhmFact      *fact;
    fsif_field_t *fld;

    if (!name || !fldlist) {
        OHM_ERROR("resource: [%s] invalid arument", __FUNCTION__);
        return FALSE;
    }

    if ((fact = ohm_fact_new(name)) == NULL) {
        OHM_ERROR("resource: [%s] Can't create new fact", __FUNCTION__);
        return FALSE;
    }

    for (fld = fldlist;   fld->type != fldtype_invalid;   fld++) {
        set_field(fact, fld->type, fld->name, (void *)&fld->value);
    }

    if (ohm_fact_store_insert(fs, fact))
        OHM_DEBUG(DBG_FS, "factstore entry %s created", name);
    else {
        OHM_ERROR("resource: [%s] Can't add %s to factsore",
                  __FUNCTION__, name);
        return FALSE;
    }

    return TRUE;
}
Пример #5
0
static int profile_load_state(void)
{
    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    OhmFact *fact;
    GSList *l, *n;
    gchar key[128];
    GValue *value;
    FILE *fp;
    int err;
    
    if ((fp = fopen(PROFILE_SAVE_PATH, "r")) == NULL) {
        if (errno != ENOENT)
            OHM_ERROR("profile: could not load saved state from %s (%d: %s)",
                      PROFILE_SAVE_PATH, errno, strerror(errno));
        return errno;
    }

    /* remove any old profile facts */
    l = ohm_fact_store_get_facts_by_name(fs, FACTSTORE_PROFILE);
    while (l != NULL) {
        n = l->next;
        ohm_fact_store_remove(fs, l->data);
        l = n;
    }
    
    /* create new fact and populate it with saved fields */
    if ((fact = ohm_fact_new(FACTSTORE_PROFILE)) == NULL) {
        OHM_ERROR("profile: failed to create fact %s", FACTSTORE_PROFILE);
        fclose(fp);
        return ENOMEM;
    }
    
    while ((err = load_field(fp, key, sizeof(key), &value)) == 0)
        ohm_fact_set(fact, key, value);
    
    fclose(fp);
    
    if (err != ENOENT) {
        g_object_unref(fact);
        OHM_ERROR("profile: failed to load saved state");
        return err;
    }

    ohm_fact_store_insert(fs, fact);
    OHM_INFO("profile: saved state loaded");
    return 0;
}
Пример #6
0
static void test_fact_store_insert (void) {
	void* p;
	p = NULL;
	{
		OhmFactStore* fs;
		OhmFact* fact;
		fs = ohm_fact_store_new ();
		fact = ohm_fact_new ("org.test.match");
		p = fact;
		g_object_add_weak_pointer (G_OBJECT (fact), &p);
		ohm_fact_store_insert (fs, fact);
		g_assert (p != NULL);
		(fs == NULL ? NULL : (fs = (g_object_unref (fs), NULL)));
		(fact == NULL ? NULL : (fact = (g_object_unref (fact), NULL)));
	}
	g_assert (p == NULL);
}
Пример #7
0
/********************
 * create_variable
 ********************/
static int
create_variable(dres_t *dres, char *name, dres_init_t *fields)
{
    dres_init_t  *init;
    char         *field;
    dres_value_t *value;
    OhmFactStore *store = ohm_get_fact_store();
    OhmFact      *fact;
    GValue       *gval;

    if (store == NULL)
        return EINVAL;

    if ((fact = ohm_fact_new(name)) == NULL)
        return ENOMEM;

    for (init = fields; init != NULL; init = init->next) {
        field = init->field.name;
        value = &init->field.value;
        switch (value->type) {
        case DRES_TYPE_INTEGER: gval = ohm_value_from_int(value->v.i);    break;
        case DRES_TYPE_DOUBLE:  gval = ohm_value_from_double(value->v.d); break;
        case DRES_TYPE_STRING:  gval = ohm_value_from_string(value->v.s); break;
        case DRES_TYPE_UNKNOWN:
            DRES_ERROR("Missing field initialiser for fact field %s:%s.",
                       name, field);
            return EINVAL;
        default:
            DRES_ERROR("Invalid field initialiser for fact field %s:%s.",
                       name, field);
            return EINVAL;
        }

        ohm_fact_set(fact, field, gval);
    }

    if (!ohm_fact_store_insert(store, fact))
        return EINVAL;

    return 0;

    (void)dres;
}
Пример #8
0
static void test_fact_store_transaction_push_and_watch (void) {
	OhmFactStore* fs;
	OhmFact* fact;
	fs = ohm_fact_store_new ();
	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);
	ohm_fact_set (fact, "field", ohm_value_from_int (43));
	ohm_fact_store_transaction_pop (fs, FALSE);
	g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.match")) == 1);
	ohm_fact_store_transaction_push (fs);
	ohm_fact_store_transaction_push (fs);
	ohm_fact_store_remove (fs, fact);
	ohm_fact_store_transaction_pop (fs, FALSE);
	ohm_fact_store_transaction_pop (fs, FALSE);
	g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.match")) == 0);
	(fs == NULL ? NULL : (fs = (g_object_unref (fs), NULL)));
	(fact == NULL ? NULL : (fact = (g_object_unref (fact), NULL)));
}
Пример #9
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)));
}
Пример #10
0
static void test_fact_store_insert_remove (void) {
	void* p;
	void* pfs;
	void* pf;
	p = NULL;
	pfs = NULL;
	pf = NULL;
	{
		OhmFactStore* fs;
		OhmFact* fact1;
		OhmFact* fact2;
		fs = ohm_fact_store_new ();
		pfs = fs;
		g_object_add_weak_pointer (G_OBJECT (fs), &pfs);
		fact1 = ohm_fact_new ("org.test.fact1");
		ohm_fact_set (fact1, "field1", ohm_value_from_string ("test1"));
		ohm_fact_set (fact1, "field2", ohm_value_from_int (42));
		p = fact1;
		g_object_add_weak_pointer (G_OBJECT (fact1), &p);
		fact2 = ohm_fact_new ("org.test.fact2");
		ohm_fact_set (fact2, "field1", ohm_value_from_string ("test2"));
		ohm_fact_set (fact2, "field2", ohm_value_from_int (42));
		/* should not complain, does not exists*/
		ohm_fact_store_remove (fs, fact1);
		/* add+remove the same fact*/
		ohm_fact_store_insert (fs, fact1);
		ohm_fact_store_insert (fs, fact1);
		ohm_fact_store_remove (fs, fact1);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.fact1")) == 0);
		ohm_fact_store_insert (fs, fact1);
		ohm_fact_store_insert (fs, fact2);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.fact1")) == 1);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.fact2")) == 1);
		ohm_fact_store_remove (fs, fact2);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.fact1")) == 1);
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.fact2")) == 0);
		{
			gint i;
			i = 0;
			for (; i < 100; i++) {
				OhmFact* fact;
				char* _tmp1;
				char* _tmp0;
				fact = ohm_fact_new ("org.test.fact1");
				_tmp1 = NULL;
				_tmp0 = NULL;
				ohm_fact_set (fact, "alloc", ohm_value_from_string ((_tmp1 = g_strconcat ("test", (_tmp0 = g_strdup_printf ("%i", i)), NULL))));
				_tmp1 = (g_free (_tmp1), NULL);
				_tmp0 = (g_free (_tmp0), NULL);
				ohm_fact_store_insert (fs, fact);
				if (pf == NULL) {
					pf = fact;
					g_object_add_weak_pointer (G_OBJECT (fact), &pf);
				}
				(fact == NULL ? NULL : (fact = (g_object_unref (fact), NULL)));
			}
		}
		g_assert (g_slist_length (ohm_fact_store_get_facts_by_name (fs, "org.test.fact1")) == 101);
		g_assert (p != NULL);
		g_assert (pfs != NULL);
		g_assert (pf != NULL);
		(fs == NULL ? NULL : (fs = (g_object_unref (fs), NULL)));
		(fact1 == NULL ? NULL : (fact1 = (g_object_unref (fact1), NULL)));
		(fact2 == NULL ? NULL : (fact2 = (g_object_unref (fact2), NULL)));
	}
	g_assert (p == NULL);
	g_assert (pfs == NULL);
	g_assert (pf == NULL);
}
Пример #11
0
static gboolean profile_create_fact(const char *profile, profileval_t *values)
{

    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    GSList *list = NULL;
    OhmFact *fact = NULL;
    GValue *gval = NULL;

    if (!profile)
        return FALSE;

    /* get the previous fact with the profile name */

    list = ohm_fact_store_get_facts_by_name(fs, FACTSTORE_PROFILE);

    if (g_slist_length(list) > 1) {
        OHM_DEBUG(DBG_PROFILE, "Error: multiple profile facts");
        return FALSE;
    }

    if (g_slist_length(list) == 1) {
        fact = list->data;

        if (fact) {
            GSList *fields = NULL, *e = NULL;
            gboolean process = TRUE;

            /* remove existing fields */
            do {
                fields = ohm_fact_get_fields(fact);
                gboolean found = FALSE;

                for (e = fields; e != NULL; e = g_slist_next(e)) {
                    GQuark qk = (GQuark)GPOINTER_TO_INT(e->data);
                    const gchar *field_name = g_quark_to_string(qk);
                    ohm_fact_del(fact, field_name);
                    found = TRUE;
                    break;
                }

                if (!found)
                    process = FALSE;

            } while (process);
        }
    }
    else {
        /* no previous fact */
        OHM_DEBUG(DBG_PROFILE, "Creating a new profile fact");
        fact = ohm_fact_new(FACTSTORE_PROFILE);
        /* put the fact in the factstore -- this way we have the same
         * update semantics (update called on each key) */
        ohm_fact_store_insert(fs, fact); /* TODO: check return */
    }

    /* fill the fact with the profile name and the values */

    OHM_DEBUG(DBG_PROFILE, "setting key %s with value %s", PROFILE_NAME_KEY, profile);
    gval = ohm_value_from_string(profile);
    ohm_fact_set(fact, PROFILE_NAME_KEY, gval);

    if (values) {
        while (values->pv_key) {
            if (values->pv_val) {
                OHM_DEBUG(DBG_PROFILE, "setting key %s with value %s",
                          values->pv_key, values->pv_val);
                gval = ohm_value_from_string(values->pv_val);
                ohm_fact_set(fact, values->pv_key, gval);
            }
            values++;
        }
    }

    OHM_DEBUG(DBG_PROFILE, "created fact: fs: %p, fact: %p", fs, fact);

    profile_save_state(fact);
    
    return TRUE;
}
Пример #12
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;
}