static int sink_process_msg(pa_msgobject * o, int code, void *data,
                            int64_t offset, pa_memchunk * chunk)
{
    int r;
    struct userdata *u = PA_SINK(o)->userdata;
    int state;
    switch (code) {
    case PA_SINK_MESSAGE_SET_STATE:
        state = PA_PTR_TO_UINT(data);
        r = pa_sink_process_msg(o, code, data, offset, chunk);
        if (r >= 0) {
            pa_log("sink cork req state =%d, now state=%d\n", state,
                   (int) (u->sink->state));
        }
        return r;

    case PA_SINK_MESSAGE_GET_LATENCY: {
        size_t n = 0;
        n += u->memchunk_sink.length;

        *((pa_usec_t *) data) =
            pa_bytes_to_usec(n, &u->sink->sample_spec);
        return 0;
    }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#2
0
static int sink_process_msg(
        pa_msgobject *o,
        int code,
        void *data,
        int64_t offset,
        pa_memchunk *chunk) {

    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {
        case PA_SINK_MESSAGE_SET_STATE:

            if (pa_sink_get_state(u->sink) == PA_SINK_SUSPENDED || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
                if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING || PA_PTR_TO_UINT(data) == PA_SINK_IDLE)
                    u->timestamp = pa_rtclock_now();
            }

            break;

        case PA_SINK_MESSAGE_GET_LATENCY: {
            pa_usec_t now;

            now = pa_rtclock_now();
            *((int64_t*) data) = (int64_t)u->timestamp - (int64_t)now;

            return 0;
        }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#3
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY: {
            pa_usec_t w, r;

            r = pa_smoother_get(u->smoother, pa_rtclock_now());
            w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec);

            *((int64_t*) data) = (int64_t)w - r;
            return 0;
        }

        case SINK_MESSAGE_PASS_SOCKET: {
            struct pollfd *pollfd;

            pa_assert(!u->rtpoll_item);

            u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
            pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
            pollfd->fd = u->fd;
            pollfd->events = pollfd->revents = 0;

            return 0;
        }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
static int
sink_process_msg(
    pa_msgobject *o,
    int code,
    void *data,
    int64_t offset,
    pa_memchunk *chunk)
{
    struct userdata *u = PA_SINK(o)->userdata;
    
    switch (code) {
        case PA_SINK_MESSAGE_SET_STATE:
            pa_log("mesg set state");
            if (PA_PTR_TO_INT(data) == PA_SINK_RUNNING)
                u->timestamp = pa_rtclock_now();
        break;
        
        case PA_SINK_MESSAGE_GET_LATENCY:
        {
            pa_usec_t now;
            pa_log("mesg get latency");
            now = pa_rtclock_now();
            *((pa_usec_t*)data) = u->timestamp > now ? u->timestamp - now : 0;
            return 0;            
        }
    }
    pa_log("sink message: %u", code);
    return pa_sink_process_msg(o, code, data, offset, chunk);
}
/* Called from I/O thread context */
static int raw_sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

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

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY: {
            pa_usec_t usec = 0;

            if (PA_MSGOBJECT(u->master_sink)->process_msg(PA_MSGOBJECT(u->master_sink), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
                usec = 0;

            *((pa_usec_t*) data) = usec;
            return 0;
        }

        case PA_SINK_MESSAGE_ADD_INPUT: {
            pa_sink_input *i = PA_SINK_INPUT(data);
            if (i == u->hw_sink_input) {
                pa_log_error("Denied loop connection");
                // TODO: This does not work... we should do something more deny connection..
                return -1;
            }

            break;
        }

    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#6
0
/* Called from I/O thread context */
static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY:

            /* The sink is _put() before the sink input is, so let's
             * make sure we don't access it in that time. Also, the
             * sink input is first shut down, the sink second. */
            if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
                !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
                *((pa_usec_t*) data) = 0;
                return 0;
            }

            *((pa_usec_t*) data) =

                /* Get the latency of the master sink */
                pa_sink_get_latency_within_thread(u->sink_input->sink) +

                /* Add the latency internal to our sink input on top */
                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);

            return 0;
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#7
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {
    case PA_SINK_MESSAGE_SET_STATE:

        if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
            pa_rtclock_get(&u->timestamp);

        break;

    case PA_SINK_MESSAGE_GET_LATENCY: {
        struct timeval now;

        pa_rtclock_get(&now);

        if (pa_timeval_cmp(&u->timestamp, &now) > 0)
            *((pa_usec_t*) data) = 0;
        else
            *((pa_usec_t*) data) = pa_timeval_diff(&u->timestamp, &now);
        break;
    }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#8
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_SET_STATE:

            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {

                case PA_SINK_SUSPENDED:
                    pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));

                    pa_smoother_pause(u->smoother, pa_rtclock_now());
                    break;

                case PA_SINK_IDLE:
                case PA_SINK_RUNNING:

                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED)
                        pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE);

                    break;

                case PA_SINK_UNLINKED:
                case PA_SINK_INIT:
                case PA_SINK_INVALID_STATE:
                    ;
            }

            break;

        case PA_SINK_MESSAGE_GET_LATENCY: {
            pa_usec_t w, r;

            r = pa_smoother_get(u->smoother, pa_rtclock_now());
            w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec);

            *((pa_usec_t*) data) = w > r ? w - r : 0;
            return 0;
        }

        case SINK_MESSAGE_PASS_SOCKET: {
            struct pollfd *pollfd;

            pa_assert(!u->rtpoll_item);

            u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
            pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
            pollfd->fd = u->fd;
            pollfd->events = pollfd->revents = 0;

            return 0;
        }
    }

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

    switch (code) {
        case PA_SINK_MESSAGE_GET_LATENCY: {
            int negative;
            pa_usec_t remote_latency;

            if (!PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
                *((pa_usec_t*) data) = 0;
                return 0;
            }

            if (!u->stream) {
                *((pa_usec_t*) data) = 0;
                return 0;
            }

            if (pa_stream_get_state(u->stream) != PA_STREAM_READY) {
                *((pa_usec_t*) data) = 0;
                return 0;
            }

            if (pa_stream_get_latency(u->stream, &remote_latency, &negative) < 0) {
                *((pa_usec_t*) data) = 0;
                return 0;
            }

            *((pa_usec_t*) data) = remote_latency;
            return 0;
        }
        case PA_SINK_MESSAGE_SET_STATE:
            if (!u->stream || pa_stream_get_state(u->stream) != PA_STREAM_READY)
                break;

            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
                case PA_SINK_SUSPENDED: {
                    cork_stream(u, true);
                    break;
                }
                case PA_SINK_IDLE:
                case PA_SINK_RUNNING: {
                    cork_stream(u, false);
                    break;
                }
                case PA_SINK_INVALID_STATE:
                case PA_SINK_INIT:
                case PA_SINK_UNLINKED:
                    break;
            }
            break;
    }
    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#10
0
static int process_message(
    pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk)
{
    switch (code) {
    case PA_SINK_MESSAGE_GET_LATENCY:
        /* if sink has additional internal latency, it may report it here */
        *((pa_usec_t*)data) = 0;
        return 0;
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#11
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY:
            *((pa_usec_t*) data) = sink_get_latency(u, &PA_SINK(o)->sample_spec);
            return 0;

        case PA_SINK_MESSAGE_SET_STATE:

            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {

                case PA_SINK_SUSPENDED:

                    pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));

                    pa_smoother_pause(u->smoother, pa_rtclock_now());

                    if (!u->source || u->source_suspended) {
                        if (suspend(u) < 0)
                            return -1;
                    }
                    u->sink_suspended = true;
                    break;

                case PA_SINK_IDLE:
                case PA_SINK_RUNNING:

                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
                        pa_smoother_resume(u->smoother, pa_rtclock_now(), true);

                        if (!u->source || u->source_suspended) {
                            if (unsuspend(u) < 0)
                                return -1;
                            u->sink->get_volume(u->sink);
                            u->sink->get_mute(u->sink);
                        }
                        u->sink_suspended = false;
                    }
                    break;

                case PA_SINK_INVALID_STATE:
                case PA_SINK_UNLINKED:
                case PA_SINK_INIT:
                    ;
            }

            break;
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#12
0
/* Called from I/O thread context */
static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY:

            /* there's no real latency here */
            *((pa_usec_t*) data) = 0;

            return 0;
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#13
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY: {
            size_t n = 0;

            n += u->memchunk.length;

            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
            return 0;
        }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#14
0
static int sink_process_msg(pa_msgobject *o, int code, void *data,
	int64_t offset, pa_memchunk *chunk)
{
	struct context *context = PA_SINK(o)->userdata;
	pa_usec_t now;
	long latency;

	pa_log_debug("sink_process_msg: code %d", code);

	switch (code)
	{

		case PA_SINK_MESSAGE_SET_VOLUME: /* 3 */
			break;

		case PA_SINK_MESSAGE_SET_MUTE: /* 6 */
			break;

		case PA_SINK_MESSAGE_GET_LATENCY: /* 7 */
			now = pa_rtclock_now();
			latency = context->timestamp > now ? context->timestamp - now : 0ULL;
			pa_log_debug("sink_process_msg: latency %ld", latency);
			*((pa_usec_t*) data) = latency;
			return 0;

		case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: /* 8 */
			break;

		case PA_SINK_MESSAGE_SET_STATE: /* 9 */
			if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING) /* 0 */
			{
				pa_log("sink_process_msg: running");

				context->timestamp = pa_rtclock_now();
			}
			else
			{
				pa_log("sink_process_msg: not running");
				close_send(context);
			}
			break;

	}

	return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#15
0
static int process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u;

    if (pa_sink_isinstance(o)) {
        u = PA_SINK(o)->userdata;

        switch (code) {

            case PA_SINK_MESSAGE_GET_LATENCY: {
                pa_usec_t r = 0;
                if (u->hwo)
                    r = sink_get_latency(u);
                *((pa_usec_t*) data) = r;
                return 0;
            }

        }

        return pa_sink_process_msg(o, code, data, offset, chunk);
    }

    if (pa_source_isinstance(o)) {
        u = PA_SOURCE(o)->userdata;

        switch (code) {

            case PA_SOURCE_MESSAGE_GET_LATENCY: {
                pa_usec_t r = 0;
                if (u->hwi)
                    r = source_get_latency(u);
                *((pa_usec_t*) data) = r;
                return 0;
            }

        }

        return pa_source_process_msg(o, code, data, offset, chunk);
    }

    return -1;
}
/* Called from I/O thread context */
static int voip_sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

    case VOICE_SINK_GET_SIDE_INFO_QUEUE_PTR: {
        /* TODO: Make sure there is only one client (or multiple queues) */
        if (!u->dl_sideinfo_queue) {
            pa_log_warn("Side info queue not set");
        }
        *((pa_queue **) data) = u->dl_sideinfo_queue;
        pa_log_debug("Side info queue (%p) passed to client", (void *) u->dl_sideinfo_queue);
        return 0;
    }

    case PA_SINK_MESSAGE_GET_LATENCY: {
        pa_usec_t usec = 0;

        if (PA_MSGOBJECT(u->raw_sink)->process_msg(PA_MSGOBJECT(u->raw_sink), PA_SINK_MESSAGE_GET_LATENCY, &usec, (int64_t)0, NULL) < 0)
            usec = 0;

        *((pa_usec_t*) data) = usec;
        return 0;
    }

    case PA_SINK_MESSAGE_ADD_INPUT: {
        pa_sink_input *i = PA_SINK_INPUT(data);
        if (i == u->hw_sink_input) {
            pa_log_error("Denied loop connection");
            // TODO: How to deny connection...
            return -1;
        }
        // Pass trough to pa_sink_process_msg
        break;
    }

    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#17
0
/* Called from I/O thread context */
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY:

            /* The sink is _put() before the sink input is, so let's
             * make sure we don't access it yet */
            if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
                !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
                *((int64_t*) data) = 0;
                return 0;
            }

            *((int64_t*) data) =
                /* Get the latency of the master sink */
                pa_sink_get_latency_within_thread(u->sink_input->sink, true) +

                /* Add the latency internal to our sink input on top */
                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);

            return 0;

        case PA_SINK_MESSAGE_SET_STATE: {
            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);

            /* When set to running or idle for the first time, request a rewind
             * of the master sink to make sure we are heard immediately */
            if ((new_state == PA_SINK_IDLE || new_state == PA_SINK_RUNNING) && u->sink->thread_info.state == PA_SINK_INIT) {
                pa_log_debug("Requesting rewind due to state change.");
                pa_sink_input_request_rewind(u->sink_input, 0, false, true, true);
            }
            break;
        }
    }

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

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY: {
            size_t n = 0;
            int l;

#ifdef FIONREAD
            if (ioctl(u->fd, FIONREAD, &l) >= 0 && l > 0)
                n = (size_t) l;
#endif

            n += u->memchunk.length;

            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
            return 0;
        }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#19
0
/* Called from IO context */
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY: {
            pa_usec_t r = 0;

            if (u->fd >= 0) {
                if (u->use_mmap)
                    r = mmap_sink_get_latency(u);
                else
                    r = io_sink_get_latency(u);
            }

            *((int64_t*) data) = (int64_t)r;

            return 0;
        }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
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);
}
示例#21
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;

    switch (code) {

    case PA_SINK_MESSAGE_SET_STATE:

        switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {

        case PA_SINK_SUSPENDED:
            pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));

            pa_smoother_pause(u->smoother, pa_rtclock_now());

            /* Issue a FLUSH if we are connected */
            if (u->fd >= 0) {
                pa_raop_flush(u->raop);
            }
            break;

        case PA_SINK_IDLE:
        case PA_SINK_RUNNING:

            if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
                pa_smoother_resume(u->smoother, pa_rtclock_now(), true);

                /* The connection can be closed when idle, so check to
                   see if we need to reestablish it */
                if (u->fd < 0)
                    pa_raop_connect(u->raop);
                else
                    pa_raop_flush(u->raop);
            }

            break;

        case PA_SINK_UNLINKED:
        case PA_SINK_INIT:
        case PA_SINK_INVALID_STATE:
            ;
        }

        break;

    case PA_SINK_MESSAGE_GET_LATENCY: {
        pa_usec_t w, r;

        r = pa_smoother_get(u->smoother, pa_rtclock_now());
        w = pa_bytes_to_usec((u->offset - u->encoding_overhead + (u->encoded_memchunk.length / u->encoding_ratio)), &u->sink->sample_spec);

        *((pa_usec_t*) data) = w > r ? w - r : 0;
        return 0;
    }

    case SINK_MESSAGE_PASS_SOCKET: {
        struct pollfd *pollfd;

        pa_assert(!u->rtpoll_item);

        u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
        pollfd->fd = u->fd;
        pollfd->events = POLLOUT;
        /*pollfd->events = */pollfd->revents = 0;

        if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
            /* Our stream has been suspended so we just flush it.... */
            pa_raop_flush(u->raop);
        }
        return 0;
    }

    case SINK_MESSAGE_RIP_SOCKET: {
        if (u->fd >= 0) {
            pa_close(u->fd);
            u->fd = -1;
        } else
            /* FIXME */
            pa_log("We should not get to this state. Cannot rip socket if not connected.");

        if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {

            pa_log_debug("RTSP control connection closed, but we're suspended so let's not worry about it... we'll open it again later");

            if (u->rtpoll_item)
                pa_rtpoll_item_free(u->rtpoll_item);
            u->rtpoll_item = NULL;
        } else {
            /* Question: is this valid here: or should we do some sort of:
               return pa_sink_process_msg(PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL);
               ?? */
            pa_module_unload_request(u->module, true);
        }
        return 0;
    }
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
示例#22
0
文件: module-oss.c 项目: Thread974/pa
/* Called from IO context */
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;
    int ret;
    pa_bool_t do_trigger = FALSE, quick = TRUE;

    switch (code) {

        case PA_SINK_MESSAGE_GET_LATENCY: {
            pa_usec_t r = 0;

            if (u->fd >= 0) {
                if (u->use_mmap)
                    r = mmap_sink_get_latency(u);
                else
                    r = io_sink_get_latency(u);
            }

            *((pa_usec_t*) data) = r;

            return 0;
        }

        case PA_SINK_MESSAGE_SET_STATE:

            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {

                case PA_SINK_SUSPENDED:
                    pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));

                    if (!u->source || u->source_suspended) {
                        if (suspend(u) < 0)
                            return -1;
                    }

                    do_trigger = TRUE;

                    u->sink_suspended = TRUE;
                    break;

                case PA_SINK_IDLE:
                case PA_SINK_RUNNING:

                    if (u->sink->thread_info.state == PA_SINK_INIT) {
                        do_trigger = TRUE;
                        quick = u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state);
                    }

                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {

                        if (!u->source || u->source_suspended) {
                            if (unsuspend(u) < 0)
                                return -1;
                            quick = FALSE;
                        }

                        do_trigger = TRUE;

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

                        u->sink_suspended = FALSE;
                    }

                    break;

                case PA_SINK_INVALID_STATE:
                case PA_SINK_UNLINKED:
                case PA_SINK_INIT:
                    ;
            }

            break;

    }

    ret = pa_sink_process_msg(o, code, data, offset, chunk);

    if (ret >= 0 && do_trigger) {
        if (trigger(u, quick) < 0)
            return -1;
    }

    return ret;
}
示例#23
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;
    int err;
    audio_info_t info;

    switch (code) {
    case PA_SINK_MESSAGE_GET_LATENCY: {
        pa_usec_t r = 0;

        if (u->fd >= 0) {

            err = ioctl(u->fd, AUDIO_GETINFO, &info);
            pa_assert(err >= 0);

            r += pa_bytes_to_usec(u->written_bytes, &PA_SINK(o)->sample_spec);
            r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &PA_SINK(o)->sample_spec);

            if (u->memchunk.memblock)
                r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec);
        }

        *((pa_usec_t*) data) = r;

        return 0;
    }

    case PA_SINK_MESSAGE_SET_VOLUME:
        if (u->fd >= 0) {
            AUDIO_INITINFO(&info);

            info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
            assert(info.play.gain <= AUDIO_MAX_GAIN);

            if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
                if (errno == EINVAL)
                    pa_log("AUDIO_SETINFO: Unsupported volume.");
                else
                    pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
            } else {
                return 0;
            }
        }
        break;

    case PA_SINK_MESSAGE_GET_VOLUME:
        if (u->fd >= 0) {
            err = ioctl(u->fd, AUDIO_GETINFO, &info);
            assert(err >= 0);

            pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
                info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);

            return 0;
        }
        break;

    case PA_SINK_MESSAGE_SET_MUTE:
        if (u->fd >= 0) {
            AUDIO_INITINFO(&info);

            info.output_muted = !!PA_PTR_TO_UINT(data);

            if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
                pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
            else
                return 0;
        }
        break;

    case PA_SINK_MESSAGE_GET_MUTE:
        if (u->fd >= 0) {
            err = ioctl(u->fd, AUDIO_GETINFO, &info);
            pa_assert(err >= 0);

            *(int*)data = !!info.output_muted;

            return 0;
        }
        break;
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}