Example #1
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);
}
Example #2
0
static gboolean check_func(GSource *source) {
    pa_glib_mainloop *g = (pa_glib_mainloop*) source;
    pa_io_event *e;

    g_assert(g);

    if (g->n_enabled_defer_events)
        return TRUE;
    else if (g->n_enabled_time_events) {
        pa_time_event *t;
        GTimeVal now;
        struct timeval tvnow;

        t = find_next_time_event(g);
        g_assert(t);

        g_get_current_time(&now);
        tvnow.tv_sec = now.tv_sec;
        tvnow.tv_usec = now.tv_usec;

        if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0)
            return TRUE;
    }

    for (e = g->io_events; e; e = e->next)
        if (!e->dead && e->poll_fd.revents != 0)
            return TRUE;

    return FALSE;
}
Example #3
0
static gboolean prepare_func(GSource *source, gint *timeout) {
    pa_glib_mainloop *g = (pa_glib_mainloop*) source;

    g_assert(g);
    g_assert(timeout);

    scan_dead(g);

    if (g->n_enabled_defer_events) {
        *timeout = 0;
        return TRUE;
    } else if (g->n_enabled_time_events) {
        pa_time_event *t;
        GTimeVal now;
        struct timeval tvnow;
        pa_usec_t usec;

        t = find_next_time_event(g);
        g_assert(t);

        g_get_current_time(&now);
        tvnow.tv_sec = now.tv_sec;
        tvnow.tv_usec = now.tv_usec;

        if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
            *timeout = 0;
            return TRUE;
        }
        usec = pa_timeval_diff(&t->timeval, &tvnow);
        *timeout = (gint) (usec / 1000);
    } else
        *timeout = -1;

    return FALSE;
}
Example #4
0
static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
    pa_glib_mainloop *g = (pa_glib_mainloop*) source;
    pa_io_event *e;

    g_assert(g);

    if (g->n_enabled_defer_events) {
        pa_defer_event *d;

        for (d = g->defer_events; d; d = d->next) {
            if (d->dead || !d->enabled)
                continue;

            break;
        }

        g_assert(d);

        d->callback(&g->api, d, d->userdata);
        return TRUE;
    }

    if (g->n_enabled_time_events) {
        GTimeVal now;
        struct timeval tvnow;
        pa_time_event *t;

        t = find_next_time_event(g);
        g_assert(t);

        g_get_current_time(&now);
        tvnow.tv_sec = now.tv_sec;
        tvnow.tv_usec = now.tv_usec;

        if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {

            /* Disable time event */
            glib_time_restart(t, NULL);

            t->callback(&g->api, t, &t->timeval, t->userdata);
            return TRUE;
        }
    }

    for (e = g->io_events; e; e = e->next)
        if (!e->dead && e->poll_fd.revents != 0) {
            e->callback(&g->api, e, e->poll_fd.fd, map_flags_from_glib(e->poll_fd.revents), e->userdata);
            e->poll_fd.revents = 0;
            return TRUE;
        }

    return FALSE;
}
Example #5
0
static void thread_func(void *userdata) {
    struct userdata *u = userdata;

    pa_assert(u);

    pa_log_debug("Thread starting up");

    pa_thread_mq_install(&u->thread_mq);
    pa_rtpoll_install(u->rtpoll);

    pa_rtclock_get(&u->timestamp);

    for (;;) {
        int ret;

        /* Render some data and drop it immediately */
        if (u->sink->thread_info.state == PA_SINK_RUNNING) {
            struct timeval now;

            pa_rtclock_get(&now);

            if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
                pa_sink_skip(u->sink, u->block_size);
                pa_timeval_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
            }

            pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
        } else
            pa_rtpoll_set_timer_disabled(u->rtpoll);

        /* Hmm, nothing to do. Let's sleep */
        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
            goto fail;

        if (ret == 0)
            goto finish;
    }

fail:
    /* If this was no regular exit from the loop we have to continue
     * processing messages until we received PA_MESSAGE_SHUTDOWN */
    pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
    pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);

finish:
    pa_log_debug("Thread shutting down");
}
Example #6
0
static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
    struct timeval wc_now, rt_now;

    pa_assert(tv);

    pa_gettimeofday(&wc_now);
    pa_rtclock_get(&rt_now);

    /* pa_timeval_sub() saturates on underflow! */

    if (pa_timeval_cmp(&rt_now, tv) < 0)
        pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now));
    else
        pa_timeval_sub(&wc_now, pa_timeval_diff(&rt_now, tv));

    *tv = wc_now;

    return tv;
}
Example #7
0
static void work(void *p) {

    pa_log_notice("CPU%i: Created thread.", PA_PTR_TO_UINT(p));

    pa_make_realtime(12);

#ifdef HAVE_PTHREAD_SETAFFINITY_NP
{
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
    cpuset_t mask;
#else
    cpu_set_t mask;
#endif

    CPU_ZERO(&mask);
    CPU_SET((size_t) PA_PTR_TO_UINT(p), &mask);
    pa_assert_se(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == 0);
}
#endif

    for (;;) {
        struct timeval now, end;
        uint64_t usec;

        pa_log_notice("CPU%i: Sleeping for 1s", PA_PTR_TO_UINT(p));
        pa_msleep(1000);

        usec =
            (uint64_t) ((((double) rand())*(double)(msec_upper-msec_lower)*PA_USEC_PER_MSEC)/RAND_MAX) +
            (uint64_t) ((uint64_t) msec_lower*PA_USEC_PER_MSEC);

        pa_log_notice("CPU%i: Freezing for %ims", PA_PTR_TO_UINT(p), (int) (usec/PA_USEC_PER_MSEC));

        pa_rtclock_get(&end);
        pa_timeval_add(&end, usec);

        do {
            pa_rtclock_get(&now);
        } while (pa_timeval_cmp(&now, &end) < 0);
    }
}
Example #8
0
static pa_time_event* glib_time_new(
        pa_mainloop_api*m,
        const struct timeval *tv,
        pa_time_event_cb_t cb,
        void *userdata) {

    pa_glib_mainloop *g;
    pa_time_event *e;

    g_assert(m);
    g_assert(m->userdata);
    g_assert(cb);

    g = m->userdata;

    e = pa_xnew(pa_time_event, 1);
    e->mainloop = g;
    e->dead = 0;

    if ((e->enabled = !!tv)) {
        e->timeval = *tv;
        g->n_enabled_time_events++;

        if (g->cached_next_time_event) {
            g_assert(g->cached_next_time_event->enabled);

            if (pa_timeval_cmp(tv, &g->cached_next_time_event->timeval) < 0)
                g->cached_next_time_event = e;
        }
    }

    e->callback = cb;
    e->userdata = userdata;
    e->destroy_callback = NULL;

    PA_LLIST_PREPEND(pa_time_event, g->time_events, e);

    return e;
}
Example #9
0
static void glib_time_restart(pa_time_event*e, const struct timeval *tv) {
    g_assert(e);
    g_assert(!e->dead);

    if (e->enabled && !tv) {
        g_assert(e->mainloop->n_enabled_time_events > 0);
        e->mainloop->n_enabled_time_events--;
    } else if (!e->enabled && tv)
        e->mainloop->n_enabled_time_events++;

    if ((e->enabled = !!tv))
        e->timeval = *tv;

    if (e->mainloop->cached_next_time_event == e)
        e->mainloop->cached_next_time_event = NULL;

    if (e->mainloop->cached_next_time_event && e->enabled) {
        g_assert(e->mainloop->cached_next_time_event->enabled);

        if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
            e->mainloop->cached_next_time_event = e;
    }
}
Example #10
0
static pa_time_event* find_next_time_event(pa_glib_mainloop *g) {
    pa_time_event *t, *n = NULL;
    g_assert(g);

    if (g->cached_next_time_event)
        return g->cached_next_time_event;

    for (t = g->time_events; t; t = t->next) {

        if (t->dead || !t->enabled)
            continue;

        if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
            n = t;

            /* Shortcut for tv = { 0, 0 } */
            if (n->timeval.tv_sec <= 0)
                break;
        }
    }

    g->cached_next_time_event = n;
    return n;
}