コード例 #1
0
static void on_connection(pa_socket_client *c, pa_iochannel*io, void *userdata) {
    struct userdata *u = userdata;

    pa_socket_client_unref(u->client);
    u->client = NULL;

    if (!io) {
        pa_log("Connection failed: %s", pa_cstrerror(errno));
        pa_module_unload_request(u->module, TRUE);
        return;
    }

    pa_assert(!u->io);
    u->io = io;
    pa_iochannel_set_callback(u->io, io_callback, u);

    pa_log_debug("Connection established, authenticating ...");
}
コード例 #2
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);
}