Exemplo n.º 1
0
/* Called from the IO thread. */
static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
    struct userdata *u;

    pa_assert(s);
    pa_assert_se(u = s->userdata);

    /* It may be that only the suspend cause is changing, in which case there's
     * nothing to do. */
    if (new_state == s->thread_info.state)
        return 0;

    switch (new_state) {

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

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

        case PA_SINK_IDLE:
        case PA_SINK_RUNNING:

            if (s->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:
            ;
    }

    return 0;
}
Exemplo n.º 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:

            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);
}
Exemplo n.º 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*) 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);
}
Exemplo n.º 4
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);
}