void pa__done(pa_module*m) {
    struct userdata *u;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    /* See comments in source_output_kill_cb() above regarding
     * destruction order! */

    if (u->source_output)
        pa_source_output_unlink(u->source_output);

    if (u->source)
        pa_source_unlink(u->source);

    if (u->source_output)
        pa_source_output_unref(u->source_output);

    if (u->source)
        pa_source_unref(u->source);

    if (u->sink)
        pa_sink_unref(u->sink);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    if (u->sink_memblockq)
         pa_memblockq_free(u->sink_memblockq);

    pa_xfree(u);
}
static void connection_free(pa_object *o) {
    connection *c = CONNECTION(o);
    pa_assert(c);

    if (c->playback.current_memblock)
        pa_memblock_unref(c->playback.current_memblock);

    if (c->input_memblockq)
        pa_memblockq_free(c->input_memblockq);
    if (c->output_memblockq)
        pa_memblockq_free(c->output_memblockq);

    pa_xfree(c);
}
int pa_play_memchunk(
        pa_sink *sink,
        const pa_sample_spec *ss,
        const pa_channel_map *map,
        const pa_memchunk *chunk,
        pa_cvolume *volume,
        pa_proplist *p,
        uint32_t *sink_input_index) {

    pa_memblockq *q;
    int r;
    pa_memchunk silence;

    pa_assert(sink);
    pa_assert(ss);
    pa_assert(chunk);

    pa_silence_memchunk_get(&sink->core->silence_cache, sink->core->mempool, &silence, ss, 0);
    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 1, 1, 0, &silence);
    pa_memblock_unref(silence.memblock);

    pa_assert_se(pa_memblockq_push(q, chunk) >= 0);

    if ((r = pa_play_memblockq(sink, ss, map, q, volume, p, sink_input_index)) < 0) {
        pa_memblockq_free(q);
        return r;
    }

    return 0;
}
示例#4
0
void pa__done(pa_module*m) {
    struct userdata *u;
    pa_assert(m);

    if (!(u = m->userdata))
        return;

    if (u->sap_event)
        m->core->mainloop->time_free(u->sap_event);

    if (u->source_output) {
        pa_source_output_unlink(u->source_output);
        pa_source_output_unref(u->source_output);
    }

    pa_rtp_context_destroy(&u->rtp_context);

    pa_sap_send(&u->sap_context, 1);
    pa_sap_context_destroy(&u->sap_context);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    pa_xfree(u);
}
示例#5
0
int pa_play_memchunk(
        pa_sink *sink,
        const pa_sample_spec *ss,
        const pa_channel_map *map,
        const pa_memchunk *chunk,
        pa_cvolume *volume,
        pa_proplist *p,
        uint32_t *sink_input_index) {

    pa_memblockq *q;
    int r;

    pa_assert(sink);
    pa_assert(ss);
    pa_assert(chunk);

    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 1, 1, 0, NULL);
    pa_assert_se(pa_memblockq_push(q, chunk) >= 0);

    if ((r = pa_play_memblockq(sink, ss, map, q, volume, p, sink_input_index)) < 0) {
        pa_memblockq_free(q);
        return r;
    }

    return 0;
}
示例#6
0
static void memblockq_stream_free(pa_object *o) {
    memblockq_stream *u = MEMBLOCKQ_STREAM(o);
    pa_assert(u);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    pa_xfree(u);
}
示例#7
0
/* Called from main context */
static void file_stream_free(pa_object *o) {
    file_stream *u = FILE_STREAM(o);
    pa_assert(u);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    if (u->sndfile)
        sf_close(u->sndfile);

    pa_xfree(u);
}
示例#8
0
void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q) {
    memblockq_stream *u;

    pa_sink_input_assert_ref(i);
    u = MEMBLOCKQ_STREAM(i->userdata);
    memblockq_stream_assert_ref(u);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    if ((u->memblockq = q)) {
        pa_memblockq_set_prebuf(q, 0);
        pa_memblockq_set_silence(q, NULL);
        pa_memblockq_willneed(q);
    }
}
void pa__done(pa_module*m) {
    struct userdata *u;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    teardown(u);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    if (u->asyncmsgq)
        pa_asyncmsgq_unref(u->asyncmsgq);

    pa_xfree(u);
}
void pa__done(pa_module*m) {
    struct userdata *u;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    if (u->unload_de) {
        u->core->mainloop->defer_free(u->unload_de);
        u->unload_de = NULL;
    }

    cmtspeech_dbus_unload(u);

    cmtspeech_connection_unload(u);

    cmtspeech_delete_source_output(u);

    cmtspeech_delete_sink_input(u);

    if (u->mainloop_handler) {
        u->mainloop_handler->parent.free((pa_object *)u->mainloop_handler);
        u->mainloop_handler = NULL;
    }

    if (u->local_sideinfoq) {
        pa_queue_free(u->local_sideinfoq, NULL);
        u->local_sideinfoq = NULL;
    }

    if (u->dl_memblockq) {
        pa_memblockq_free(u->dl_memblockq);
        u->dl_memblockq = NULL;
    }

    if (u->sink_name)
        pa_xfree(u->sink_name);

    if (u->source_name)
        pa_xfree(u->source_name);

    pa_xfree(u);
}
示例#11
0
void pa__done(pa_module*m) {
    struct userdata *u;
    unsigned c;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    /* See comments in sink_input_kill_cb() above regarding
     * destruction order! */

    if (u->sink_input)
        pa_sink_input_unlink(u->sink_input);

    if (u->sink)
        pa_sink_unlink(u->sink);

    if (u->sink_input)
        pa_sink_input_unref(u->sink_input);

    if (u->sink)
        pa_sink_unref(u->sink);

    for (c = 0; c < u->channels; c++)
        if (u->handle[c]) {
            if (u->descriptor->deactivate)
                u->descriptor->deactivate(u->handle[c]);
            u->descriptor->cleanup(u->handle[c]);
        }

    if (u->output != u->input)
        pa_xfree(u->output);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    pa_xfree(u->input);

    pa_xfree(u->control);

    pa_xfree(u);
}
void pa__done(pa_module*m) {
    struct userdata *u;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    /* See comments in sink_input_kill_cb() above regarding
     * destruction order! */

    if (u->sink_input)
        pa_sink_input_unlink(u->sink_input);

    if (u->sink)
        pa_sink_unlink(u->sink);

    if (u->sink_input)
        pa_sink_input_unref(u->sink_input);

    if (u->sink)
        pa_sink_unref(u->sink);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    if (u->hrir_data)
        pa_xfree(u->hrir_data);

    if (u->input_buffer)
        pa_xfree(u->input_buffer);

    if (u->mapping_left)
        pa_xfree(u->mapping_left);
    if (u->mapping_right)
        pa_xfree(u->mapping_right);

    pa_xfree(u);
}
示例#13
0
static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
    memblockq_stream *u;

    pa_sink_input_assert_ref(i);
    pa_assert(chunk);
    u = MEMBLOCKQ_STREAM(i->userdata);
    memblockq_stream_assert_ref(u);

    if (!u->memblockq)
        return -1;

    if (pa_memblockq_peek(u->memblockq, chunk) < 0) {

        if (pa_sink_input_safe_to_remove(i)) {

            pa_memblockq_free(u->memblockq);
            u->memblockq = NULL;

            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMBLOCKQ_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
        }

        return -1;
    }

    /* If there's no memblock, there's going to be data in the memblockq after
     * a gap with length chunk->length. Drop the the gap and peek the actual
     * data. There should always be some data coming - hence the assert. The
     * gap will occur if the memblockq is rewound beyond index 0.*/
    if (!chunk->memblock) {
        pa_memblockq_drop(u->memblockq, chunk->length);
        pa_assert_se(pa_memblockq_peek(u->memblockq, chunk) >= 0);
    }

    chunk->length = PA_MIN(chunk->length, nbytes);
    pa_memblockq_drop(u->memblockq, chunk->length);

    return 0;
}
示例#14
0
/* Called from main context */
static void source_output_free(pa_object* mo) {
    pa_source_output *o = PA_SOURCE_OUTPUT(mo);

    pa_assert(o);
    pa_assert_ctl_context();
    pa_assert(pa_source_output_refcnt(o) == 0);

    if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
        pa_source_output_unlink(o);

    pa_log_info("Freeing output %u \"%s\"", o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)));

    if (o->thread_info.delay_memblockq)
        pa_memblockq_free(o->thread_info.delay_memblockq);

    if (o->thread_info.resampler)
        pa_resampler_free(o->thread_info.resampler);

    if (o->proplist)
        pa_proplist_free(o->proplist);

    pa_xfree(o->driver);
    pa_xfree(o);
}
示例#15
0
/*** Deallocate stuff ***/
void voice_clear_up(struct userdata *u) {
    pa_assert(u);

    if (u->mainloop_handler) {
        u->mainloop_handler->parent.free((pa_object *)u->mainloop_handler);
        u->mainloop_handler = NULL;
    }

    if (u->hw_sink_input) {
        pa_sink_input_unlink(u->hw_sink_input);
        pa_sink_input_unref(u->hw_sink_input);
        u->hw_sink_input = NULL;
    }

    if (u->raw_sink) {
        pa_sink_unlink(u->raw_sink);
        pa_sink_unref(u->raw_sink);
        u->raw_sink = NULL;
    }

    if (u->dl_memblockq) {
        pa_memblockq_free(u->dl_memblockq);
        u->dl_memblockq = NULL;
    }

    if (u->voip_sink) {
        pa_sink_unlink(u->voip_sink);
        pa_sink_unref(u->voip_sink);
        u->voip_sink = NULL;
    }

    if (u->hw_source_output) {
        pa_source_output_unlink(u->hw_source_output);
        pa_source_output_unref(u->hw_source_output);
        u->hw_source_output = NULL;
    }

    if (u->voip_source) {
        pa_source_unlink(u->voip_source);
        pa_source_unref(u->voip_source);
        u->voip_source = NULL;
    }

    if (u->raw_source) {
        pa_source_unlink(u->raw_source);
        pa_source_unref(u->raw_source);
        u->raw_source = NULL;
    }

    if (u->hw_source_memblockq) {
        pa_memblockq_free(u->hw_source_memblockq);
        u->hw_source_memblockq = NULL;
    }

    if (u->ul_memblockq) {
        pa_memblockq_free(u->ul_memblockq);
        u->ul_memblockq = NULL;
    }

    if (u->dl_sideinfo_queue) {
        pa_queue_free(u->dl_sideinfo_queue, NULL, u);
        u->dl_sideinfo_queue = NULL;
    }

    voice_aep_ear_ref_unload(u);

    if (u->aep_silence_memchunk.memblock) {
        pa_memblock_unref(u->aep_silence_memchunk.memblock);
        pa_memchunk_reset(&u->aep_silence_memchunk);
    }

    if (u->sink_temp_buff) {
        pa_xfree(u->sink_temp_buff);
        u->sink_temp_buff = NULL;
    }

    if (u->sink_subscription) {
        pa_subscription_free(u->sink_subscription);
        u->sink_subscription = NULL;
    }

    if (u->sink_proplist_changed_slot) {
        pa_hook_slot_free(u->sink_proplist_changed_slot);
        u->sink_proplist_changed_slot = NULL;
    }

    if (u->source_proplist_changed_slot) {
        pa_hook_slot_free(u->source_proplist_changed_slot);
        u->source_proplist_changed_slot = NULL;
    }

    voice_convert_free(u);
    voice_memchunk_pool_unload(u);
    voice_unload_event_forwarder(u);
}
示例#16
0
/* Called from main context */
int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t save) {
    pa_resampler *new_resampler;

    pa_source_output_assert_ref(o);
    pa_assert_ctl_context();
    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
    pa_assert(!o->source);
    pa_source_assert_ref(dest);

    if (!pa_source_output_may_move_to(o, dest))
        return -1;

    if (o->thread_info.resampler &&
        pa_sample_spec_equal(pa_resampler_input_sample_spec(o->thread_info.resampler), &dest->sample_spec) &&
        pa_channel_map_equal(pa_resampler_input_channel_map(o->thread_info.resampler), &dest->channel_map))

        /* Try to reuse the old resampler if possible */
        new_resampler = o->thread_info.resampler;

    else if ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
             !pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) ||
             !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) {

        /* Okey, we need a new resampler for the new source */

        if (!(new_resampler = pa_resampler_new(
                      o->core->mempool,
                      &dest->sample_spec, &dest->channel_map,
                      &o->sample_spec, &o->channel_map,
                      o->requested_resample_method,
                      ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                      ((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
                      (o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
            pa_log_warn("Unsupported resampling operation.");
            return -PA_ERR_NOTSUPPORTED;
        }
    } else
        new_resampler = NULL;

    if (o->moving)
        o->moving(o, dest);

    o->source = dest;
    o->save_source = save;
    pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL);

    if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
        o->source->n_corked++;

    /* Replace resampler */
    if (new_resampler != o->thread_info.resampler) {
        if (o->thread_info.resampler)
            pa_resampler_free(o->thread_info.resampler);
        o->thread_info.resampler = new_resampler;

        pa_memblockq_free(o->thread_info.delay_memblockq);

        o->thread_info.delay_memblockq = pa_memblockq_new(
                0,
                MEMBLOCKQ_MAXLENGTH,
                0,
                pa_frame_size(&o->source->sample_spec),
                0,
                1,
                0,
                &o->source->silence);
        o->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
    }

    pa_source_update_status(dest);

    pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0);

    pa_log_debug("Successfully moved source output %i to %s.", o->index, dest->name);

    /* Notify everyone */
    pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], o);
    pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);

    return 0;
}
示例#17
0
/* Called from IO thread context */
static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
    file_stream *u;

    pa_sink_input_assert_ref(i);
    pa_assert(chunk);
    u = FILE_STREAM(i->userdata);
    file_stream_assert_ref(u);

    if (!u->memblockq)
        return -1;

    for (;;) {
        pa_memchunk tchunk;
        size_t fs;
        void *p;
        sf_count_t n;

        if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
            chunk->length = PA_MIN(chunk->length, length);
            pa_memblockq_drop(u->memblockq, chunk->length);
            return 0;
        }

        if (!u->sndfile)
            break;

        tchunk.memblock = pa_memblock_new(i->sink->core->mempool, length);
        tchunk.index = 0;

        p = pa_memblock_acquire(tchunk.memblock);

        if (u->readf_function) {
            fs = pa_frame_size(&i->sample_spec);
            n = u->readf_function(u->sndfile, p, (sf_count_t) (length/fs));
        } else {
            fs = 1;
            n = sf_read_raw(u->sndfile, p, (sf_count_t) length);
        }

        pa_memblock_release(tchunk.memblock);

        if (n <= 0) {
            pa_memblock_unref(tchunk.memblock);

            sf_close(u->sndfile);
            u->sndfile = NULL;
            break;
        }

        tchunk.length = (size_t) n * fs;

        pa_memblockq_push(u->memblockq, &tchunk);
        pa_memblock_unref(tchunk.memblock);
    }

    if (pa_sink_input_safe_to_remove(i)) {
        pa_memblockq_free(u->memblockq);
        u->memblockq = NULL;

        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
    }

    return -1;
}
示例#18
0
int main(int argc, char *argv[]) {
    int ret;

    pa_mempool *p;
    pa_memblockq *bq;
    pa_memchunk chunk1, chunk2, chunk3, chunk4;
    pa_memchunk silence;
    pa_sample_spec ss = {
        .format = PA_SAMPLE_S16LE,
        .rate = 48000,
        .channels = 1
    };

    pa_log_set_level(PA_LOG_DEBUG);

    p = pa_mempool_new(FALSE, 0);

    pa_assert_se(silence.memblock = pa_memblock_new_fixed(p, (char*) "__", 2, 1));
    silence.index = 0;
    silence.length = pa_memblock_get_length(silence.memblock);

    pa_assert_se(bq = pa_memblockq_new("test memblockq", 0, 200, 10, &ss, 4, 4, 40, &silence));

    pa_assert_se(chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1));
    chunk1.index = 0;
    chunk1.length = 2;

    pa_assert_se(chunk2.memblock = pa_memblock_new_fixed(p, (char*) "XX22", 4, 1));
    chunk2.index = 2;
    chunk2.length = 2;

    pa_assert_se(chunk3.memblock = pa_memblock_new_fixed(p, (char*) "3333", 4, 1));
    chunk3.index = 0;
    chunk3.length = 4;

    pa_assert_se(chunk4.memblock = pa_memblock_new_fixed(p, (char*) "44444444", 8, 1));
    chunk4.index = 0;
    chunk4.length = 8;

    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    ret = pa_memblockq_push(bq, &chunk2);
    assert(ret == 0);

    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);

    ret = pa_memblockq_push(bq, &chunk4);
    assert(ret == 0);

    pa_memblockq_seek(bq, -6, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);

    pa_memblockq_seek(bq, -2, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    pa_memblockq_seek(bq, -10, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk4);
    assert(ret == 0);

    pa_memblockq_seek(bq, 10, 0, TRUE);

    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    pa_memblockq_seek(bq, -6, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk2);
    assert(ret == 0);

    /* Test splitting */
    pa_memblockq_seek(bq, -12, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    pa_memblockq_seek(bq, 20, 0, TRUE);

    /* Test merging */
    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);
    pa_memblockq_seek(bq, -2, 0, TRUE);

    chunk3.index += 2;
    chunk3.length -= 2;
    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);

    pa_memblockq_seek(bq, 30, PA_SEEK_RELATIVE, TRUE);

    dump(bq);

    pa_memblockq_rewind(bq, 52);

    dump(bq);

    pa_memblockq_free(bq);
    pa_memblock_unref(silence.memblock);
    pa_memblock_unref(chunk1.memblock);
    pa_memblock_unref(chunk2.memblock);
    pa_memblock_unref(chunk3.memblock);
    pa_memblock_unref(chunk4.memblock);

    pa_mempool_free(p);

    return 0;
}