~schnouki/pustule

340056bf2714347739ebf32233882991a73af801 — Thomas Jost 7 years ago 7c3be33
Add pustule-get-volume
3 files changed, 52 insertions(+), 2 deletions(-)

M guile.c
M pulse.c
M pustule.h
M guile.c => guile.c +20 -0
@@ 23,6 23,7 @@
#include <string.h>

#include <libguile.h>
#include <pthread.h>
#include <pulse/pulseaudio.h>

#include "pustule.h"


@@ 34,6 35,8 @@ struct pustule_exported_func {
    scm_t_subr func;
    const char* doc;
} exported_funcs[] = {
    {"pustule-get-volume", 1, 0, 0, &pustule_get_volume,
     "Gets the volume of the sink whose index is SINK-IDX (an integer)."},
    {"pustule-set-volume", 2, 0, 0, &pustule_set_volume,
     "Sets the volume of the sink whose index is SINK-IDX (an integer) to\n"
     "VOLUME (a number between 0 and 1)."},


@@ 44,6 47,23 @@ struct pustule_exported_func {
SCM sink_added_hook = NULL;
SCM sink_removed_hook = NULL;

/* Get the volume for the specified sink */
SCM pustule_get_volume(SCM idx) {
    pustule_volume_t vol = {0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};

    /* Query the volume with PulseAudio */
    pthread_mutex_lock(&(vol.mutex));
    sink_get_info(scm_to_uint32(idx), &vol);
    pthread_cond_wait(&(vol.cond), &(vol.mutex));

    /* Cleanup */
    pthread_mutex_unlock(&(vol.mutex));
    pthread_mutex_destroy(&(vol.mutex));
    pthread_cond_destroy(&(vol.cond));

    return scm_from_double(vol.volume);
}

/* Set volume for the specified sink */
SCM pustule_set_volume(SCM idx, SCM volume) {
    uint32_t idx_ = scm_to_uint32(idx);

M pulse.c => pulse.c +20 -1
@@ 81,5 81,24 @@ void sink_info_callback(pa_context* ctx, const pa_sink_input_info* i, int eol, v
    if (i->proplist)
        event->proplist = pa_proplist_copy(i->proplist);

    pustule_handle_sink_event(event);
    if (userdata) {
        /* Explicit query */
        pustule_volume_t* vol = (pustule_volume_t*) userdata;
        pthread_mutex_lock(&(vol->mutex));
        vol->volume = ((double) pa_cvolume_avg(&(i->volume))) / PA_VOLUME_NORM;
        pthread_cond_broadcast(&(vol->cond));
        pthread_mutex_unlock(&(vol->mutex));
    }
    else {
        /* Event callback */
        pustule_handle_sink_event(event);
    }
}

/* Query info about a sink */
void sink_get_info(uint32_t idx, pustule_volume_t* vol) {
    pa_threaded_mainloop_lock(paloop);
    pa_operation* op = pa_context_get_sink_input_info(pactx, idx, sink_info_callback, (void*) vol);
    pa_operation_unref(op);
    pa_threaded_mainloop_unlock(paloop);
}

M pustule.h => pustule.h +12 -1
@@ 23,10 23,11 @@
#define PUSTULE_VERSION "pustule 0.1"

#include <libguile.h>
#include <pthread.h>
#include <pulse/pulseaudio.h>

/* Data structures */
typedef struct _pustule_sink_event_t {
typedef struct {
    enum {SINK_ADDED, SINK_REMOVED} type;
    uint32_t index;
    char* name;


@@ 38,12 39,22 @@ typedef struct _pustule_sink_event_t {
    pa_proplist* proplist;
} pustule_sink_event_t;

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

/* PulseAudio callbacks */
void sink_event_callback(pa_context* ctx, pa_subscription_event_type_t t, uint32_t idx, void* userdata);
void sink_info_callback(pa_context* ctx, const pa_sink_input_info* i, int eol, void* userdata);
void state_callback(pa_context* ctx, void* userdata);

/* PulseAudio functions */
void sink_get_info(uint32_t idx, pustule_volume_t* vol);

/* Guile functions */
SCM pustule_get_volume(SCM idx);
SCM pustule_set_volume(SCM idx, SCM volume);

/* Guile helpers */