~schnouki/pustule

e61282b3422c6bc97872743ba03f9922e0348554 — Thomas Jost 4 years ago b306719
Prepare for having different event types
4 files changed, 48 insertions(+), 36 deletions(-)

M events.c
M guile.c
M pulse.c
M pustule.h
M events.c => events.c +10 -8
@@ 29,7 29,7 @@

/* Event queue structure */
typedef struct _event_queue_entry_t {
    pustule_input_event_t* event;
    pustule_event_t* event;
    struct _event_queue_entry_t* next;
} event_queue_entry_t;



@@ 46,22 46,24 @@ void pustule_run() {
        pthread_cond_wait(&event_queue_cond, &event_queue_mutex);
        while (event_queue_first) {
            event_queue_entry_t* first = event_queue_first;
            pustule_input_event_t* event = first->event;
            pustule_event_t* event = first->event;
            event_queue_first = first->next;
            if (!event)
                continue;

            pustule_input_event_t* iev = &event->input_event;

            pthread_mutex_unlock(&event_queue_mutex);

            SCM index = scm_from_uint32(event->index);
            SCM index = scm_from_uint32(iev->index);
            if ((event->type == INPUT_ADDED) && scm_is_false(scm_hook_empty_p(input_added_hook))) {
                SCM info = scm_from_input_event(event);
                SCM args = scm_list_2(index, info);
                scm_run_hook(input_added_hook, args);
                if (event->proplist)
                    pa_proplist_free(event->proplist);
                free(event->name);
                free(event->driver);
                if (iev->proplist)
                    pa_proplist_free(iev->proplist);
                free(iev->name);
                free(iev->driver);
            }
            else if ((event->type == INPUT_REMOVED) && scm_is_false(scm_hook_empty_p(input_removed_hook))) {
                scm_run_hook(input_removed_hook, scm_list_1(index));


@@ 73,7 75,7 @@ void pustule_run() {
}

/* Handle input events from PulseAudio */
void pustule_handle_input_event(pustule_input_event_t* event) {
void pustule_handle_event(pustule_event_t* event) {
    pthread_mutex_lock(&event_queue_mutex);

    event_queue_entry_t* entry = scm_gc_malloc_pointerless(sizeof(event_queue_entry_t), "event queue entry");

M guile.c => guile.c +12 -11
@@ 79,27 79,28 @@ SCM pustule_set_volume(SCM idx, SCM volume) {
}

/* Convert an input event to an association list */
SCM scm_from_input_event(pustule_input_event_t* event) {
SCM scm_from_input_event(pustule_event_t* event) {
    pustule_input_event_t* iev = &event->input_event;
    SCM info = SCM_EOL;
    info = scm_acons(scm_from_utf8_string("name"),            scm_from_utf8_string(event->name),                info);
    info = scm_acons(scm_from_utf8_string("driver"),          scm_from_utf8_string(event->driver),              info);
    info = scm_acons(scm_from_utf8_string("muted"),           event->mute ? SCM_BOOL_T : SCM_BOOL_F,            info);
    info = scm_acons(scm_from_utf8_string("volume_writable"), event->volume_writable ? SCM_BOOL_T : SCM_BOOL_F, info);
    if (event->has_volume) {
        double vol = ((double) pa_cvolume_avg(&(event->volume))) / PA_VOLUME_NORM;
    info = scm_acons(scm_from_utf8_string("name"),            scm_from_utf8_string(iev->name),                info);
    info = scm_acons(scm_from_utf8_string("driver"),          scm_from_utf8_string(iev->driver),              info);
    info = scm_acons(scm_from_utf8_string("muted"),           iev->mute ? SCM_BOOL_T : SCM_BOOL_F,            info);
    info = scm_acons(scm_from_utf8_string("volume_writable"), iev->volume_writable ? SCM_BOOL_T : SCM_BOOL_F, info);
    if (iev->has_volume) {
        double vol = ((double) pa_cvolume_avg(&(iev->volume))) / PA_VOLUME_NORM;
        info = scm_acons(scm_from_utf8_string("volume"), scm_from_double(vol), info);

        vol = pa_sw_volume_to_dB(pa_cvolume_avg(&(event->volume)));
        vol = pa_sw_volume_to_dB(pa_cvolume_avg(&(iev->volume)));
        info = scm_acons(scm_from_utf8_string("volume_db"), scm_from_double(vol), info);
    }
    else {
        info = scm_acons(scm_from_utf8_string("volume"), SCM_BOOL_F, info);
    }
    if (event->proplist && !pa_proplist_isempty(event->proplist)) {
    if (iev->proplist && !pa_proplist_isempty(iev->proplist)) {
        void* state = NULL;
        const char* key;
        while ((key = pa_proplist_iterate(event->proplist, &state)) != NULL) {
            const char* value = pa_proplist_gets(event->proplist, key);
        while ((key = pa_proplist_iterate(iev->proplist, &state)) != NULL) {
            const char* value = pa_proplist_gets(iev->proplist, key);
            info = scm_acons(scm_from_utf8_string(key), scm_from_utf8_string(value), info);
        }
    }

M pulse.c => pulse.c +15 -14
@@ 52,12 52,12 @@ void input_event_callback(pa_context* ctx, pa_subscription_event_type_t t, uint3
    }
    else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
        // Input removed: directly call the corresponding callback
        pustule_input_event_t* event = malloc(sizeof(pustule_input_event_t));
        pustule_event_t* event = malloc(sizeof(pustule_event_t));
        if (!event) abort();

        event->type = INPUT_REMOVED;
        event->index = idx;
        pustule_handle_input_event(event);
        event->input_event.index = idx;
        pustule_handle_event(event);
    }
}



@@ 65,21 65,22 @@ void input_event_callback(pa_context* ctx, pa_subscription_event_type_t t, uint3
void input_info_callback(pa_context* ctx, const pa_sink_input_info* i, int eol, void* userdata) {
    if (!i) return;

    pustule_input_event_t* event = malloc(sizeof(pustule_input_event_t));
    pustule_event_t* event = malloc(sizeof(pustule_event_t));
    if (!event) abort();
    pustule_input_event_t* iev = &event->input_event;

    event->type = INPUT_ADDED;
    event->index = i->index;
    event->name = strdup(i->name);
    event->driver = strdup(i->name);
    event->mute = i->mute;
    event->volume_writable = i->volume_writable;
    event->has_volume = i->has_volume;
    event->volume = i->volume;
    iev->index = i->index;
    iev->name = strdup(i->name);
    iev->driver = strdup(i->name);
    iev->mute = i->mute;
    iev->volume_writable = i->volume_writable;
    iev->has_volume = i->has_volume;
    iev->volume = i->volume;

    event->proplist = NULL;
    iev->proplist = NULL;
    if (i->proplist)
        event->proplist = pa_proplist_copy(i->proplist);
        iev->proplist = pa_proplist_copy(i->proplist);

    if (userdata) {
        /* Explicit query */


@@ 91,7 92,7 @@ void input_info_callback(pa_context* ctx, const pa_sink_input_info* i, int eol, 
    }
    else {
        /* Event callback */
        pustule_handle_input_event(event);
        pustule_handle_event(event);
    }
}


M pustule.h => pustule.h +11 -3
@@ 28,7 28,6 @@

/* Data structures */
typedef struct {
    enum {INPUT_ADDED, INPUT_REMOVED} type;
    uint32_t index;
    char* name;
    char* driver;


@@ 40,6 39,15 @@ typedef struct {
} pustule_input_event_t;

typedef struct {
    enum {
        INPUT_ADDED, INPUT_REMOVED,
    } type;
    union {
        pustule_input_event_t input_event;
    };
} pustule_event_t;

typedef struct {
    double volume;
    pthread_mutex_t mutex;
    pthread_cond_t cond;


@@ 59,11 67,11 @@ SCM pustule_set_volume(SCM idx, SCM volume);

/* Guile helpers */
void pustule_init_guile();
SCM scm_from_input_event(pustule_input_event_t* event);
SCM scm_from_input_event(pustule_event_t* event);

/* Pustule event loop */
void pustule_run();
void pustule_handle_input_event(pustule_input_event_t* event);
void pustule_handle_event(pustule_event_t* event);

/* Global variables */
extern pa_context* pactx;