Example #1
0
static gboolean bt_delete_all_facts()
{
    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    GSList *list = ohm_fact_store_get_facts_by_name(fs, BT_DEVICE);
    gboolean resolve_all = FALSE;

    OHM_DEBUG(DBG_BT, "Bluez went away!");

    while (list) {

        OhmFact *bt_connected = (OhmFact *) list->data;

        gboolean disconnect_a2dp = disconnect_device(bt_connected, BT_TYPE_A2DP);
        gboolean disconnect_hsp = disconnect_device(bt_connected, BT_TYPE_HSP);

        ohm_fact_store_remove(fs, bt_connected);
        g_object_unref(bt_connected);

        if (disconnect_a2dp || disconnect_hsp)
            resolve_all = TRUE;

        list = ohm_fact_store_get_facts_by_name(fs, BT_DEVICE);
    }

    return resolve_all;
}
Example #2
0
void fsif_init(OhmPlugin *plugin)
{
    (void)plugin;

    fs = ohm_fact_store_get_fact_store();

    updated_id  = g_signal_connect(G_OBJECT(fs), "updated" , G_CALLBACK(updated_cb) , NULL);
    inserted_id = g_signal_connect(G_OBJECT(fs), "inserted", G_CALLBACK(inserted_cb), NULL);
    removed_id  = g_signal_connect(G_OBJECT(fs), "removed" , G_CALLBACK(removed_cb) , NULL);
}
Example #3
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;
}
Example #4
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;
}
Example #5
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;
}
Example #6
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;
}
Example #7
0
void action_init(OhmPlugin *plugin)
{
    char *register_name        = "signaling.register_enforcement_point";
    char *unregister_name      = "signaling.unregister_enforcement_point";
    char *register_signature   = (char *)register_ep_SIGNATURE;
    char *unregister_signature = (char *)unregister_ep_SIGNATURE;
    char *signals[]            = {"dsp_actions", NULL};

    (void)plugin;

    ENTER;

    ohm_module_find_method(register_name,
                           &register_signature,
                           (void *)&register_ep);
    ohm_module_find_method(unregister_name,
                           &unregister_signature,
                           (void *)&unregister_ep);

    if (!register_ep || !unregister_ep) {
        OHM_ERROR("dspep: can't find mandatory signaling methods. "
                  "DSP enforcement point disabled");
    }
    else {
        if ((conn = register_ep("dspep", signals)) == NULL) {
            OHM_ERROR("dspep: failed to register to receive '%s' signals. "
                      "DSP enforcement point disabled", signals[0]);
        }
        else {
            factstore    = ohm_fact_store_get_fact_store();

            decision_id  = g_signal_connect(conn, "on-decision",
                                            G_CALLBACK(decision_signal_cb),
                                            NULL);
            keychange_id = g_signal_connect(conn, "on-key-change",
                                            G_CALLBACK(key_change_signal_cb),
                                            NULL);            

            OHM_INFO("dspep: DSP enforcement point enabled");
        }
    }

    LEAVE;
}
Example #8
0
void fsif_exit(OhmPlugin *plugin)
{
    (void)plugin;

    fs = ohm_fact_store_get_fact_store();

    if (g_signal_handler_is_connected(G_OBJECT(fs), updated_id)) {
        g_signal_handler_disconnect(G_OBJECT(fs), updated_id);
        updated_id = 0;
    }
    if (g_signal_handler_is_connected(G_OBJECT(fs), inserted_id)) {
        g_signal_handler_disconnect(G_OBJECT(fs), inserted_id);
        inserted_id = 0;
    }
    if (g_signal_handler_is_connected(G_OBJECT(fs), removed_id)) {
        g_signal_handler_disconnect(G_OBJECT(fs), removed_id);
        removed_id = 0;
    }
}
Example #9
0
DBusHandlerResult bt_device_removed(DBusConnection *c, DBusMessage * msg, void *data)
{

    /* This is called apparently anytime a device does not tell that it
     * has been removed itself. We somehow need to ensure that this
     * device actually is a HSP or A2DP device. */

    OhmFactStore *fs = ohm_fact_store_get_fact_store();
    gchar *path = NULL;
    (void) data;
    (void) c;

    if (!msg)
        goto end;

    if (dbus_message_get_args(msg,
                NULL,
                DBUS_TYPE_OBJECT_PATH,
                &path,
                DBUS_TYPE_INVALID)) {

        OhmFact *bt_connected = bt_get_connected(path);

        if (bt_connected) {

            gboolean disconnect_a2dp = disconnect_device(bt_connected, BT_TYPE_A2DP);
            gboolean disconnect_hsp = disconnect_device(bt_connected, BT_TYPE_HSP);

            ohm_fact_store_remove(fs, bt_connected);
            g_object_unref(bt_connected);

            if (disconnect_a2dp || disconnect_hsp)
                dres_all();
        }
        /* else a bt device disconnected but there were no known bt headsets
         * connected, just disregard */
    }

end:

    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
Example #10
0
static void plugin_init(OhmPlugin *plugin)
{
    (void)plugin;

    GObject       *conn = NULL;
    gulong         decision_cb;
    gulong         keychange_cb;
    const char    *port_str;
    char          *e;
    unsigned short port;
    char *signals[] = {
        "video_actions",
        NULL
    };

    OHM_DEBUG_INIT(video);

    OHM_INFO("Video EP: init ...");

    do {

        if (!(port_str = ohm_plugin_get_param(plugin, "notification-port")))
            port = VIDEOEP_NOTIFICATION_PORT;
        else {
            port = strtoul(port_str, &e, 10);

            if (*e != '\0') {
                OHM_ERROR("videoep: invalid notification port '%s'", port_str);
                port = VIDEOEP_NOTIFICATION_PORT;
            }
        }

        if (register_ep == NULL) {
            OHM_ERROR("videoep: 'signaling.register_enforcement_point()' "
                      "not found");
            break;
        }

        if ((conn = register_ep("videoep", signals)) == NULL) {
            OHM_ERROR("videoep: Failed to initialize VieoEP");
            break;
        }

        if ((videoep = malloc(sizeof(*videoep))) == NULL) {
            OHM_ERROR("videoep: Can't allocate memory for 'videoep'");
            break;
        }

        decision_cb  = g_signal_connect(conn, "on-decision",
                                        G_CALLBACK(decision_signal_cb),
                                        (gpointer)videoep);
        keychange_cb = g_signal_connect(conn, "on-key-change",
                                        G_CALLBACK(key_change_signal_cb),
                                        (gpointer)videoep);
        

        memset(videoep, 0, sizeof(*videoep));
        videoep->fs   = ohm_fact_store_get_fact_store();
        videoep->conn = conn;
        videoep->decision_cb  = decision_cb;
        videoep->keychange_cb = keychange_cb; 
        videoep->xr = xrt_init(":0");
        videoep->notif = notify_init(port);

        xrt_connect_to_xserver(videoep->xr);

        return;                 /* everything went OK */

    } while(0);

    /* Something failed */
    if (conn != NULL)
        unregister_ep(videoep->conn);

    free(videoep);
}
Example #11
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;
}
Example #12
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;
}
Example #13
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;
}
/********************
 * pl_fact_exists
 ********************/
static foreign_t
pl_fact_exists(term_t pl_name,
               term_t pl_fields, term_t pl_list, control_t handle)
{
    context_t  *ctx;
    char       *name, factname[64];
    fid_t       frame;
    term_t      pl_values;
    OhmFact    *f;
    
    switch (PL_foreign_control(handle)) {
    case PL_FIRST_CALL:
        if (!PL_is_list(pl_fields) || /*!PL_is_list(pl_list) ||*/
            !PL_get_chars(pl_name, &name, CVT_ALL))
            PL_fail;
        strncpy(factname, name, sizeof(factname));
        factname[sizeof(factname)-1] = '\0';

        if ((ctx = malloc(sizeof(*ctx))) == NULL)
            PL_fail;
        memset(ctx, 0, sizeof(*ctx));
        
        if (get_field_names(ctx, pl_fields) != 0) {
            free(ctx);
            PL_fail;
        }
        
        ctx->store = ohm_fact_store_get_fact_store();
        ctx->facts = ohm_fact_store_get_facts_by_name(ctx->store, factname);
        break;
        
    case PL_REDO:
        ctx = PL_foreign_context_address(handle);
        break;
        
    case PL_CUTTED:
        ctx = PL_foreign_context_address(handle);
        goto nomore;

    default:
        PL_fail;
    }


    /* XXX TODO: shouldn't we discard the frame here instead of closing them */

    frame = PL_open_foreign_frame();
    while (ctx->facts != NULL) {
        f = (OhmFact *)ctx->facts->data;
        ctx->facts = g_slist_next(ctx->facts);

        if (!fact_values(ctx, f, &pl_values) && PL_unify(pl_list, pl_values)) {
            PL_close_foreign_frame(frame); /* PL_discard_foreign_frame ??? */
            PL_retry_address(ctx);
        }
        
        PL_rewind_foreign_frame(frame);
    }
    PL_close_foreign_frame(frame);  /* PL_discard_foreign_frame ??? */
    
 nomore:
    if (ctx->fields)
        free(ctx->fields);
    free(ctx);
    PL_fail;
}