Пример #1
0
static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
    connection *c = CONNECTION(o);
    connection_assert_ref(c);

    if (!c->protocol)
        return -1;

    switch (code) {
        case CONNECTION_MESSAGE_REQUEST_DATA:
            do_work(c);
            break;

        case CONNECTION_MESSAGE_POST_DATA:
/*             pa_log("got data %u", chunk->length); */
            pa_memblockq_push_align(c->output_memblockq, chunk);
            do_work(c);
            break;

        case CONNECTION_MESSAGE_UNLINK_CONNECTION:
            connection_unlink(c);
            break;
    }

    return 0;
}
Пример #2
0
static void do_work(connection *c) {
    connection_assert_ref(c);

    if (c->dead)
        return;

    if (pa_iochannel_is_readable(c->io))
        if (do_read(c) < 0)
            goto fail;

    if (!c->sink_input && pa_iochannel_is_hungup(c->io))
        goto fail;

    if (pa_iochannel_is_writable(c->io))
        if (do_write(c) < 0)
            goto fail;

    return;

fail:

    if (c->sink_input) {

        /* If there is a sink input, we first drain what we already have read before shutting down the connection */
        c->dead = TRUE;

        pa_iochannel_free(c->io);
        c->io = NULL;

        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
    } else
        connection_unlink(c);
}
Пример #3
0
static void client_kill_cb(pa_client *client) {
    connection*c;

    pa_assert(client);
    c = CONNECTION(client->userdata);
    pa_assert(c);

    connection_unlink(c);
}
Пример #4
0
static void server_disconnect_all(LassiServer *ls, gboolean clear_order) {

    while (ls->connections)
        connection_unlink(ls->connections->data, clear_order);

    if (clear_order) {
        lassi_list_free(ls->order);
        ls->order = NULL;
    }
}
Пример #5
0
void pa_simple_protocol_disconnect(pa_simple_protocol *p, pa_module *m) {
    connection *c;
    void *state = NULL;

    pa_assert(p);
    pa_assert(m);

    while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
        if (c->options->module == m)
            connection_unlink(c);
}
Пример #6
0
void lassi_server_disconnect(LassiServer *ls, const char *id, gboolean remove_from_order) {
    LassiConnection *lc;

    g_assert(ls);
    g_assert(id);

    if ((lc = g_hash_table_lookup(ls->connections_by_id, id)))
        connection_unlink(lc, remove_from_order);
    else if (remove_from_order) {
        GList *i = g_list_find_custom(ls->order, id, (GCompareFunc) strcmp);

        if (i)
            ls->order = g_list_delete_link(ls->order, i);
    }
}
Пример #7
0
void pa_simple_protocol_unref(pa_simple_protocol *p) {
    connection *c;
    pa_assert(p);
    pa_assert(PA_REFCNT_VALUE(p) >= 1);

    if (PA_REFCNT_DEC(p) > 0)
        return;

    while ((c = pa_idxset_first(p->connections, NULL)))
        connection_unlink(c);

    pa_idxset_free(p->connections, NULL);

    pa_assert_se(pa_shared_remove(p->core, "simple-protocol") >= 0);

    pa_xfree(p);
}
Пример #8
0
static int signal_node_removed(LassiConnection *lc, DBusMessage *m) {
    const char *id, *address;
    DBusError e;
    LassiConnection *k;
    gboolean remove_from_order;
    LassiServer *ls = lc->server;

    dbus_error_init(&e);

    if (!(dbus_message_get_args(m, &e,
                                DBUS_TYPE_STRING, &id,
                                DBUS_TYPE_STRING, &address,
                                DBUS_TYPE_BOOLEAN, &remove_from_order,
                                DBUS_TYPE_INVALID))) {
        g_warning("Received invalid message: %s", e.message);
        dbus_error_free(&e);
        return -1;
    }

    if (strcmp(id, lc->server->id) == 0) {
        g_debug("We've been kicked ourselves.");

        server_disconnect_all(lc->server, TRUE);
        return 0;
    }

    if (remove_from_order) {
        GList *i = g_list_find_custom(ls->order, id, (GCompareFunc) strcmp);

        if (i)
            ls->order = g_list_delete_link(ls->order, i);
    }

    if ((k = g_hash_table_lookup(lc->server->connections_by_id, id)))
        connection_unlink(k, remove_from_order);

    server_broadcast(ls, m, lc == k ? NULL : lc);

    return 0;
}
Пример #9
0
void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simple_options *o) {
    connection *c = NULL;
    char pname[128];
    pa_client_new_data client_data;

    pa_assert(p);
    pa_assert(io);
    pa_assert(o);

    if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
        pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
        pa_iochannel_free(io);
        return;
    }

    c = pa_msgobject_new(connection);
    c->parent.parent.free = connection_free;
    c->parent.process_msg = connection_process_msg;
    c->io = io;
    pa_iochannel_set_callback(c->io, io_callback, c);

    c->sink_input = NULL;
    c->source_output = NULL;
    c->input_memblockq = c->output_memblockq = NULL;
    c->protocol = p;
    c->options = pa_simple_options_ref(o);
    c->playback.current_memblock = NULL;
    c->playback.memblock_index = 0;
    c->dead = false;
    c->playback.underrun = true;
    pa_atomic_store(&c->playback.missing, 0);

    pa_client_new_data_init(&client_data);
    client_data.module = o->module;
    client_data.driver = __FILE__;
    pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
    pa_proplist_setf(client_data.proplist, PA_PROP_APPLICATION_NAME, "Simple client (%s)", pname);
    pa_proplist_sets(client_data.proplist, "simple-protocol.peer", pname);
    c->client = pa_client_new(p->core, &client_data);
    pa_client_new_data_done(&client_data);

    if (!c->client)
        goto fail;

    c->client->kill = client_kill_cb;
    c->client->userdata = c;

    if (o->playback) {
        pa_sink_input_new_data data;
        pa_memchunk silence;
        size_t l;
        pa_sink *sink;

        if (!(sink = pa_namereg_get(c->protocol->core, o->default_sink, PA_NAMEREG_SINK))) {
            pa_log("Failed to get sink.");
            goto fail;
        }

        pa_sink_input_new_data_init(&data);
        data.driver = __FILE__;
        data.module = o->module;
        data.client = c->client;
        pa_sink_input_new_data_set_sink(&data, sink, false);
        pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
        pa_sink_input_new_data_set_sample_spec(&data, &o->sample_spec);

        pa_sink_input_new(&c->sink_input, p->core, &data);
        pa_sink_input_new_data_done(&data);

        if (!c->sink_input) {
            pa_log("Failed to create sink input.");
            goto fail;
        }

        c->sink_input->parent.process_msg = sink_input_process_msg;
        c->sink_input->pop = sink_input_pop_cb;
        c->sink_input->process_rewind = sink_input_process_rewind_cb;
        c->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
        c->sink_input->kill = sink_input_kill_cb;
        c->sink_input->userdata = c;

        pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY);

        l = (size_t) ((double) pa_bytes_per_second(&o->sample_spec)*PLAYBACK_BUFFER_SECONDS);
        pa_sink_input_get_silence(c->sink_input, &silence);
        c->input_memblockq = pa_memblockq_new(
                "simple protocol connection input_memblockq",
                0,
                l,
                l,
                &o->sample_spec,
                (size_t) -1,
                l/PLAYBACK_BUFFER_FRAGMENTS,
                0,
                &silence);
        pa_memblock_unref(silence.memblock);

        pa_iochannel_socket_set_rcvbuf(io, l);

        pa_atomic_store(&c->playback.missing, (int) pa_memblockq_pop_missing(c->input_memblockq));

        pa_sink_input_put(c->sink_input);
    }

    if (o->record) {
        pa_source_output_new_data data;
        size_t l;
        pa_source *source;

        if (!(source = pa_namereg_get(c->protocol->core, o->default_source, PA_NAMEREG_SOURCE))) {
            pa_log("Failed to get source.");
            goto fail;
        }

        pa_source_output_new_data_init(&data);
        data.driver = __FILE__;
        data.module = o->module;
        data.client = c->client;
        pa_source_output_new_data_set_source(&data, source, false);
        pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
        pa_source_output_new_data_set_sample_spec(&data, &o->sample_spec);

        pa_source_output_new(&c->source_output, p->core, &data);
        pa_source_output_new_data_done(&data);

        if (!c->source_output) {
            pa_log("Failed to create source output.");
            goto fail;
        }
        c->source_output->push = source_output_push_cb;
        c->source_output->kill = source_output_kill_cb;
        c->source_output->get_latency = source_output_get_latency_cb;
        c->source_output->userdata = c;

        pa_source_output_set_requested_latency(c->source_output, DEFAULT_SOURCE_LATENCY);

        l = (size_t) (pa_bytes_per_second(&o->sample_spec)*RECORD_BUFFER_SECONDS);
        c->output_memblockq = pa_memblockq_new(
                "simple protocol connection output_memblockq",
                0,
                l,
                0,
                &o->sample_spec,
                1,
                0,
                0,
                NULL);
        pa_iochannel_socket_set_sndbuf(io, l);

        pa_source_output_put(c->source_output);
    }

    pa_idxset_put(p->connections, c, NULL);

    return;

fail:
    connection_unlink(c);
}
Пример #10
0
/* Called from main context */
static void source_output_kill_cb(pa_source_output *o) {
    pa_source_output_assert_ref(o);

    connection_unlink(CONNECTION(o->userdata));
}
Пример #11
0
/* Called from main context */
static void sink_input_kill_cb(pa_sink_input *i) {
    pa_sink_input_assert_ref(i);

    connection_unlink(CONNECTION(i->userdata));
}
Пример #12
0
static DBusHandlerResult message_function(DBusConnection *c, DBusMessage *m, void *userdata) {
    DBusError e;
    LassiConnection *lc = userdata;

    g_assert(c);
    g_assert(m);
    g_assert(lc);

    dbus_error_init(&e);

    /*     g_debug("[%s] interface=%s, path=%s, member=%s serial=%u", */
    /*             lc->id, */
    /*             dbus_message_get_interface(m), */
    /*             dbus_message_get_path(m), */
    /*             dbus_message_get_member(m), */
    /*             dbus_message_get_serial(m)); */

    if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
        goto fail;

    else if (dbus_message_is_signal(m, LASSI_INTERFACE, "Hello")) {
        if (signal_hello(lc, m) < 0)
            goto fail;

    } else if (lc->id) {

        if (dbus_message_is_signal(m, LASSI_INTERFACE, "NodeAdded")) {

            if (signal_node_added(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "NodeRemoved")) {

            if (signal_node_removed(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "UpdateGrab")) {

            if (signal_update_grab(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "UpdateOrder")) {

            if (signal_update_order(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "KeyEvent")) {

            if (signal_key_event(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "MotionEvent")) {

            if (signal_motion_event(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "ButtonEvent")) {

            if (signal_button_event(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "AcquireClipboard")) {

            if (signal_acquire_clipboard(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "ReturnClipboard")) {

            if (signal_return_clipboard(lc, m) < 0)
                goto fail;

        } else if (dbus_message_is_method_call(m, LASSI_INTERFACE, "GetClipboard")) {

            if (method_get_clipboard(lc, m) < 0)
                goto fail;

        } else
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

    } else
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

    return DBUS_HANDLER_RESULT_HANDLED;

fail:

    dbus_error_free(&e);

    connection_unlink(lc, TRUE);

    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}