示例#1
0
pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
    void *data;

    pa_assert(b);
    pa_assert(spec);

    data = pa_memblock_acquire(b);
    pa_silence_memory(data, pa_memblock_get_length(b), spec);
    pa_memblock_release(b);

    return b;
}
示例#2
0
pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
    void *data;

    pa_assert(c);
    pa_assert(c->memblock);
    pa_assert(spec);

    data = pa_memblock_acquire(c->memblock);
    pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
    pa_memblock_release(c->memblock);

    return c;
}
示例#3
0
文件: module-oss.c 项目: Thread974/pa
/* Called from IO context */
static int unsuspend(struct userdata *u) {
    int m;
    pa_sample_spec ss, *ss_original;
    int frag_size, in_frag_size, out_frag_size;
    int in_nfrags, out_nfrags;
    struct audio_buf_info info;

    pa_assert(u);
    pa_assert(u->fd < 0);

    m = u->mode;

    pa_log_info("Trying resume...");

    if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) {
        pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno));
        return -1;
    }

    if (m != u->mode) {
        pa_log_warn("Resume failed, couldn't open device with original access mode.");
        goto fail;
    }

    if (u->nfrags >= 2 && u->frag_size >= 1)
        if (pa_oss_set_fragments(u->fd, u->nfrags, u->orig_frag_size) < 0) {
            pa_log_warn("Resume failed, couldn't set original fragment settings.");
            goto fail;
        }

    ss = *(ss_original = u->sink ? &u->sink->sample_spec : &u->source->sample_spec);
    if (pa_oss_auto_format(u->fd, &ss) < 0 || !pa_sample_spec_equal(&ss, ss_original)) {
        pa_log_warn("Resume failed, couldn't set original sample format settings.");
        goto fail;
    }

    if (ioctl(u->fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
        pa_log_warn("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
        goto fail;
    }

    in_frag_size = out_frag_size = frag_size;
    in_nfrags = out_nfrags = u->nfrags;

    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
        in_frag_size = info.fragsize;
        in_nfrags = info.fragstotal;
    }

    if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
        out_frag_size = info.fragsize;
        out_nfrags = info.fragstotal;
    }

    if ((u->source && (in_frag_size != (int) u->in_fragment_size || in_nfrags != (int) u->in_nfrags)) ||
        (u->sink && (out_frag_size != (int) u->out_fragment_size || out_nfrags != (int) u->out_nfrags))) {
        pa_log_warn("Resume failed, input fragment settings don't match.");
        goto fail;
    }

    if (u->use_mmap) {
        if (u->source) {
            if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
                pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno));
                goto fail;
            }
        }

        if (u->sink) {
            if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
                pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno));
                if (u->in_mmap && u->in_mmap != MAP_FAILED) {
                    munmap(u->in_mmap, u->in_hwbuf_size);
                    u->in_mmap = NULL;
                }

                goto fail;
            }

            pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
        }
    }

    u->out_mmap_current = u->in_mmap_current = 0;
    u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0;

    pa_assert(!u->rtpoll_item);

    build_pollfd(u);

    if (u->sink && u->sink->get_volume)
        u->sink->get_volume(u->sink);
    if (u->source && u->source->get_volume)
        u->source->get_volume(u->source);

    pa_log_info("Resumed successfully...");

    return 0;

fail:
    pa_close(u->fd);
    u->fd = -1;
    return -1;
}
示例#4
0
文件: module-oss.c 项目: Thread974/pa
static int trigger(struct userdata *u, pa_bool_t quick) {
    int enable_bits = 0, zero = 0;

    pa_assert(u);

    if (u->fd < 0)
        return 0;

    pa_log_debug("trigger");

    if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state))
        enable_bits |= PCM_ENABLE_INPUT;

    if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
        enable_bits |= PCM_ENABLE_OUTPUT;

    pa_log_debug("trigger: %i", enable_bits);


    if (u->use_mmap) {

        if (!quick)
            ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero);

#ifdef SNDCTL_DSP_HALT
        if (enable_bits == 0)
            if (ioctl(u->fd, SNDCTL_DSP_HALT, NULL) < 0)
                pa_log_warn("SNDCTL_DSP_HALT: %s", pa_cstrerror(errno));
#endif

        if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0)
            pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));

        if (u->sink && !(enable_bits & PCM_ENABLE_OUTPUT)) {
            pa_log_debug("clearing playback buffer");
            pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &u->sink->sample_spec);
        }

    } else {

        if (enable_bits)
            if (ioctl(u->fd, SNDCTL_DSP_POST, NULL) < 0)
                pa_log_warn("SNDCTL_DSP_POST: %s", pa_cstrerror(errno));

        if (!quick) {
            /*
             * Some crappy drivers do not start the recording until we
             * read something.  Without this snippet, poll will never
             * register the fd as ready.
             */

            if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
                uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size);

                if (pa_read(u->fd, buf, u->in_fragment_size, NULL) < 0) {
                    pa_log("pa_read() failed: %s", pa_cstrerror(errno));
                    pa_xfree(buf);
                    return -1;
                }

                pa_xfree(buf);
            }
        }
    }

    return 0;
}
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *memchunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case SINK_MESSAGE_RENDER:

            /* Handle the request from the JACK thread */

            if (u->sink->thread_info.state == PA_SINK_RUNNING) {
                pa_memchunk chunk;
                size_t nbytes;
                void *p;

                pa_assert(offset > 0);
                nbytes = (size_t) offset * pa_frame_size(&u->sink->sample_spec);

                pa_sink_render_full(u->sink, nbytes, &chunk);

                p = (uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index;
                pa_deinterleave(p, u->buffer, u->channels, sizeof(float), (unsigned) offset);
                pa_memblock_release(chunk.memblock);

                pa_memblock_unref(chunk.memblock);
            } else {
                unsigned c;
                pa_sample_spec ss;

                /* Humm, we're not RUNNING, hence let's write some silence */

                ss = u->sink->sample_spec;
                ss.channels = 1;

                for (c = 0; c < u->channels; c++)
                    pa_silence_memory(u->buffer[c], (size_t) offset * pa_sample_size(&ss), &ss);
            }

            u->frames_in_buffer = (jack_nframes_t) offset;
            u->saved_frame_time = * (jack_nframes_t*) data;
            u->saved_frame_time_valid = TRUE;

            return 0;

        case SINK_MESSAGE_BUFFER_SIZE:
            pa_sink_set_max_request_within_thread(u->sink, (size_t) offset * pa_frame_size(&u->sink->sample_spec));
            return 0;

        case SINK_MESSAGE_ON_SHUTDOWN:
            pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
            return 0;

        case PA_SINK_MESSAGE_GET_LATENCY: {
            jack_nframes_t l, ft, d;
            size_t n;

            /* This is the "worst-case" latency */
            l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer;

            if (u->saved_frame_time_valid) {
                /* Adjust the worst case latency by the time that
                 * passed since we last handed data to JACK */

                ft = jack_frame_time(u->client);
                d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0;
                l = l > d ? l - d : 0;
            }

            /* Convert it to usec */
            n = l * pa_frame_size(&u->sink->sample_spec);
            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);

            return 0;
        }

    }

    return pa_sink_process_msg(o, code, data, offset, memchunk);
}
示例#6
0
/* This is called whenever new data may is available */
static void stream_read_callback(pa_stream *s, size_t length, void *userdata) {

    pa_assert(s);
    pa_assert(length > 0);

    if (raw) {
        pa_assert(!sndfile);

        if (stdio_event)
            mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT);

        while (pa_stream_readable_size(s) > 0) {
            const void *data;

            if (pa_stream_peek(s, &data, &length) < 0) {
                pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context)));
                quit(1);
                return;
            }

            pa_assert(length > 0);

            /* If there is a hole in the stream, we generate silence, except
             * if it's a passthrough stream in which case we skip the hole. */
            if (data || !(flags & PA_STREAM_PASSTHROUGH)) {
                buffer = pa_xrealloc(buffer, buffer_length + length);
                if (data)
                    memcpy((uint8_t *) buffer + buffer_length, data, length);
                else
                    pa_silence_memory((uint8_t *) buffer + buffer_length, length, &sample_spec);

                buffer_length += length;
            }

            pa_stream_drop(s);
        }

    } else {
        pa_assert(sndfile);

        while (pa_stream_readable_size(s) > 0) {
            sf_count_t bytes;
            const void *data;

            if (pa_stream_peek(s, &data, &length) < 0) {
                pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context)));
                quit(1);
                return;
            }

            pa_assert(length > 0);

            if (!data && (flags & PA_STREAM_PASSTHROUGH)) {
                pa_stream_drop(s);
                continue;
            }

            if (!data && length > silence_buffer_length) {
                silence_buffer = pa_xrealloc(silence_buffer, length);
                pa_silence_memory((uint8_t *) silence_buffer + silence_buffer_length, length - silence_buffer_length, &sample_spec);
                silence_buffer_length = length;
            }

            if (writef_function) {
                size_t k = pa_frame_size(&sample_spec);

                if ((bytes = writef_function(sndfile, data ? data : silence_buffer, (sf_count_t) (length/k))) > 0)
                    bytes *= (sf_count_t) k;

            } else
                bytes = sf_write_raw(sndfile, data ? data : silence_buffer, (sf_count_t) length);

            if (bytes < (sf_count_t) length)
                quit(1);

            pa_stream_drop(s);
        }
    }
}
示例#7
0
/* Sink and source states are passed as arguments, because this is called
 * during state changes, and we need the new state, but thread_info.state
 * has not yet been updated. */
static void trigger(struct userdata *u, pa_sink_state_t sink_state, pa_source_state_t source_state, bool quick) {
    int enable_bits = 0, zero = 0;

    pa_assert(u);

    if (u->fd < 0)
        return;

    pa_log_debug("trigger");

    if (u->source && PA_SOURCE_IS_OPENED(source_state))
        enable_bits |= PCM_ENABLE_INPUT;

    if (u->sink && PA_SINK_IS_OPENED(sink_state))
        enable_bits |= PCM_ENABLE_OUTPUT;

    pa_log_debug("trigger: %i", enable_bits);

    if (u->use_mmap) {

        if (!quick)
            ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero);

#ifdef SNDCTL_DSP_HALT
        if (enable_bits == 0)
            if (ioctl(u->fd, SNDCTL_DSP_HALT, NULL) < 0)
                pa_log_warn("SNDCTL_DSP_HALT: %s", pa_cstrerror(errno));
#endif

        if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0)
            pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));

        if (u->sink && !(enable_bits & PCM_ENABLE_OUTPUT)) {
            pa_log_debug("clearing playback buffer");
            pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &u->sink->sample_spec);
        }

    } else {

        if (enable_bits)
            if (ioctl(u->fd, SNDCTL_DSP_POST, NULL) < 0)
                pa_log_warn("SNDCTL_DSP_POST: %s", pa_cstrerror(errno));

        if (!quick) {
            /*
             * Some crappy drivers do not start the recording until we
             * read something.  Without this snippet, poll will never
             * register the fd as ready.
             */

            if (u->source && PA_SOURCE_IS_OPENED(source_state)) {
                uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size);

                /* XXX: Shouldn't this be done only when resuming the source?
                 * Currently this code path is executed also when resuming the
                 * sink while the source is already running. */

                if (pa_read(u->fd, buf, u->in_fragment_size, NULL) < 0)
                    pa_log("pa_read() failed: %s", pa_cstrerror(errno));

                pa_xfree(buf);
            }
        }
    }
}