Audio plugin is now ported to new API and builds again.
Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
add_compile_options(-Wall -Wextra -Wconversion)
add_compile_options(-Wno-unused-parameter) # frankly not using a parameter does it care?
+add_compile_options(-Wno-sign-compare -Wno-sign-conversion)
add_compile_options(-Werror=maybe-uninitialized)
add_compile_options(-Werror=implicit-function-declaration)
add_compile_options(-ffunction-sections -fdata-sections)
${libmicrohttpd_INCLUDE_DIRS}
${uuid_INCLUDE_DIRS}
${dbus_INCLUDE_DIRS}
-# ${alsa_INCLUDE_DIRS}
-# ${pulseaudio_INCLUDE_DIRS}
+ ${alsa_INCLUDE_DIRS}
+ ${pulseaudio_INCLUDE_DIRS}
# ${librtlsdr_INCLUDE_DIRS}
# ${gupnp_INCLUDE_DIRS}
${openssl_INCLUDE_DIRS}
${libmicrohttpd_LIBRARIES}
${uuid_LIBRARIES}
${dbus_LIBRARIES}
-# ${alsa_LIBRARIES}
-# ${pulseaudio_LIBRARIES}
+ ${alsa_LIBRARIES}
+ ${pulseaudio_LIBRARIES}
# ${librtlsdr_LIBRARIES}
# ${gupnp_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
ADD_SUBDIRECTORY(afm-main-plugin)
ADD_SUBDIRECTORY(session)
ADD_SUBDIRECTORY(samples)
-#ADD_SUBDIRECTORY(audio)
+ADD_SUBDIRECTORY(audio)
#ADD_SUBDIRECTORY(radio)
#ADD_SUBDIRECTORY(media)
SND_MIXER_SCHN_SIDE_RIGHT
};
-PUBLIC unsigned char _alsa_init (const char *name, audioCtxHandleT *ctx) {
+static struct dev_ctx_alsa **dev_ctx_a = NULL;
+
+
+unsigned char _alsa_init (const char *name, audioCtxHandleT *ctx) {
snd_pcm_t *dev;
snd_pcm_hw_params_t *params;
/* allocate the global array if it hasn't been done */
if (!dev_ctx_a) {
- dev_ctx_a = (dev_ctx_alsa_T**) malloc (sizeof(dev_ctx_alsa_T));
+ dev_ctx_a = (dev_ctx_alsa_T**) malloc (sizeof(dev_ctx_alsa_T*));
dev_ctx_a[0] = (dev_ctx_alsa_T*) malloc (sizeof(dev_ctx_alsa_T));
dev_ctx_a[0]->name = NULL;
dev_ctx_a[0]->dev = NULL;
}
/* is a card with similar name already opened ? */
- for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T)); num++) {
+ for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T*)); num++) {
if (dev_ctx_a[num]->name &&
!strcmp (dev_ctx_a[num]->name, name))
return 0;
num++;
/* it's not... let us add it to the global array */
- dev_ctx_a = (dev_ctx_alsa_T**) realloc (dev_ctx_a, (num+1)*sizeof(dev_ctx_alsa_T));
+ dev_ctx_a = (dev_ctx_alsa_T**) realloc (dev_ctx_a, (num+1)*sizeof(dev_ctx_alsa_T*));
dev_ctx_a[num] = (dev_ctx_alsa_T*) malloc (sizeof(dev_ctx_alsa_T));
dev_ctx_a[num]->name = strdup (name);
dev_ctx_a[num]->dev = dev;
ctx->idx = num;
ctx->name = strdup (name);
- if (verbose) fprintf (stderr, "Successfully initialized ALSA backend.\n");
+ fprintf (stderr, "Successfully initialized ALSA backend.\n");
return 1;
}
-PUBLIC void _alsa_free (const char *name) {
+void _alsa_free (const char *name) {
int num;
- for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T)); num++) {
+ for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T*)); num++) {
if (dev_ctx_a[num]->name &&
!strcmp (dev_ctx_a[num]->name, name)) {
snd_pcm_close (dev_ctx_a[num]->dev);
}
}
-PUBLIC void _alsa_play (int num) {
+void _alsa_play (int num) {
if (!dev_ctx_a || !dev_ctx_a[num] || dev_ctx_a[num]->thr_should_run ||
access (AUDIO_BUFFER, F_OK) == -1)
pthread_create (&dev_ctx_a[num]->thr, NULL, _alsa_play_thread_fn, (void*)dev_ctx_a[num]);
}
-PUBLIC void _alsa_stop (int num) {
+void _alsa_stop (int num) {
if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->thr_should_run)
return;
pthread_join (dev_ctx_a[num]->thr, NULL);
}
-PUBLIC unsigned int _alsa_get_volume (int num, unsigned int channel) {
+unsigned int _alsa_get_volume (int num, unsigned int channel) {
if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm)
return 0;
snd_mixer_selem_get_playback_volume (dev_ctx_a[num]->mixer_elm, SCHANNELS[channel], &dev_ctx_a[num]->vol);
- return (int)(dev_ctx_a[num]->vol*100)/dev_ctx_a[num]->vol_max;
+ return (unsigned int)(dev_ctx_a[num]->vol*100)/dev_ctx_a[num]->vol_max;
}
-PUBLIC void _alsa_set_volume (int num, unsigned int channel, unsigned int vol) {
+void _alsa_set_volume (int num, unsigned int channel, unsigned int vol) {
if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm ||
vol > 100)
return;
snd_mixer_selem_set_playback_volume (dev_ctx_a[num]->mixer_elm, SCHANNELS[channel], (vol*dev_ctx_a[num]->vol_max)/100);
-
}
-PUBLIC void _alsa_set_volume_all (int num, unsigned int vol) {
+void _alsa_set_volume_all (int num, unsigned int vol) {
if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm ||
vol > 100)
snd_mixer_selem_set_playback_volume_all (dev_ctx_a[num]->mixer_elm, (vol*dev_ctx_a[num]->vol_max)/100);
}
-PUBLIC unsigned char _alsa_get_mute (int num) {
+unsigned char _alsa_get_mute (int num) {
int mute = 0;
snd_mixer_elem_t *elm_m;
return (unsigned char)!mute;
}
-PUBLIC void _alsa_set_mute (int num, unsigned char tomute) {
+void _alsa_set_mute (int num, unsigned char tomute) {
snd_mixer_elem_t *elm_m;
int mute;
snd_mixer_selem_set_playback_switch_all (elm_m, !mute);
}
-PUBLIC void _alsa_set_rate (int num, unsigned int rate) {
+void _alsa_set_rate (int num, unsigned int rate) {
if (!dev_ctx_a || !dev_ctx_a[num])
return;
snd_pcm_hw_params_set_rate_near (dev_ctx_a[num]->dev, dev_ctx_a[num]->params, &rate, 0);
}
-PUBLIC void _alsa_set_channels (int num, unsigned int channels) {
+void _alsa_set_channels (int num, unsigned int channels) {
if (!dev_ctx_a || !dev_ctx_a[num])
return;
/* ---- LOCAL THREADED FUNCTIONS ---- */
-STATIC void* _alsa_play_thread_fn (void *ctx) {
+void* _alsa_play_thread_fn (void *ctx) {
dev_ctx_alsa_T *dev_ctx_a = (dev_ctx_alsa_T *)ctx;
FILE *file = NULL;
#include <alsa/asoundlib.h>
#include "audio-api.h"
-#include "local-def.h"
+
+#define AUDIO_BUFFER "/tmp/audio_buf"
typedef struct dev_ctx_alsa dev_ctx_alsa_T;
unsigned char thr_finished;
};
-PUBLIC unsigned char _alsa_init (const char *, audioCtxHandleT *);
-PUBLIC void _alsa_free (const char *);
-PUBLIC void _alsa_play (int);
-PUBLIC void _alsa_stop (int);
-PUBLIC unsigned int _alsa_get_volume (int, unsigned int);
-PUBLIC void _alsa_set_volume (int, unsigned int, unsigned int);
-PUBLIC void _alsa_set_volume_all (int, unsigned int);
-PUBLIC unsigned char _alsa_get_mute (int);
-PUBLIC void _alsa_set_mute (int, unsigned char);
-PUBLIC void _alsa_set_channels (int, unsigned int);
-STATIC void* _alsa_play_thread_fn (void *);
-
-static struct dev_ctx_alsa **dev_ctx_a = NULL;
+unsigned char _alsa_init (const char *, audioCtxHandleT *);
+void _alsa_free (const char *);
+void _alsa_play (int);
+void _alsa_stop (int);
+unsigned int _alsa_get_volume (int, unsigned int);
+void _alsa_set_volume (int, unsigned int, unsigned int);
+void _alsa_set_volume_all (int, unsigned int);
+unsigned char _alsa_get_mute (int);
+void _alsa_set_mute (int, unsigned char);
+void _alsa_set_channels (int, unsigned int);
+
+void* _alsa_play_thread_fn (void *);
#endif /* AUDIO_ALSA_H */
#define _GNU_SOURCE
#include <stdlib.h>
+#include <json-c/json.h>
#include "audio-api.h"
#include "audio-alsa.h"
/* ------ BACKEND FUNCTIONS ------- */
-void _backend_init (const char *name, audioCtxHandleT *ctx) {
+unsigned char _backend_init (const char *name, audioCtxHandleT *ctx) {
char *backend_env = getenv ("AFB_AUDIO_OUTPUT");
unsigned char res = 0;
#endif
res = _alsa_init (name, ctx);
- if (!res && verbose)
+ if (!res)
fprintf (stderr, "Could not initialize Audio backend\n");
+
+ return res;
}
void _backend_free (audioCtxHandleT *ctx) {
/* ------ LOCAL HELPER FUNCTIONS --------- */
-/* private client context creation ; default values */
-STATIC audioCtxHandleT* initAudioCtx () {
+/* private client context constructor ; default values */
+static audioCtxHandleT* initAudioCtx () {
audioCtxHandleT *ctx;
int i;
ctx = malloc (sizeof(audioCtxHandleT));
ctx->audio_dev = NULL;
+ ctx->name = NULL;
ctx->idx = -1;
for (i = 0; i < 8; i++)
ctx->volume[i] = 25;
return ctx;
}
-STATIC AFB_error releaseAudio (audioCtxHandleT *ctx) {
+static void releaseAudioCtx (void *context) {
+
+ audioCtxHandleT *ctx = (audioCtxHandleT*) context;
/* power it off */
_backend_free (ctx);
/* clean client context */
+ ctx->audio_dev = NULL;
+ if (ctx->name)
+ free (ctx->name);
ctx->idx = -1;
-
- return AFB_SUCCESS;
-}
-
-/* called when client session dies [e.g. client quits for more than 15mns] */
-STATIC void freeAudio (void *context) {
- free (context);
+ free (ctx);
}
/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
-STATIC void init (struct afb_req request) { /* AFB_SESSION_CHECK */
+static void init (struct afb_req request) { /* AFB_SESSION_CHECK */
+ audioCtxHandleT *ctx = (audioCtxHandleT*) afb_req_context_get(request);
json_object *jresp;
/* create a private client context */
- if (!request.context)
- request.context = initAudioCtx();
+ if (!ctx) {
+ ctx = initAudioCtx();
+ afb_req_context_set (request, ctx, releaseAudioCtx);
+ }
- _backend_init("default", request.context);
+ if (!_backend_init ("default", ctx)) {
+ afb_req_fail (request, "failed", "backend initialization failed");
+ }
jresp = json_object_new_object();
- json_object_object_add (jresp, "info", json_object_new_string ("Audio initialized"));
-
- afb_req_success (request, jresp, "Audio initiliazed");
+ json_object_object_add (jresp, "init", json_object_new_string ("success"));
+ afb_req_success (request, jresp, "Audio initialized");
}
-STATIC void volume (struct afb_req request) { /* AFB_SESSION_CHECK */
+static void volume (struct afb_req request) { /* AFB_SESSION_CHECK */
- audioCtxHandleT *ctx = (audioCtxHandleT*)request.context;
- const char *value = afb_req_argument (request, "value");
+ audioCtxHandleT *ctx = (audioCtxHandleT*) afb_req_context_get(request);
+ struct afb_arg arg = afb_req_get (request, "value");
+ const char *value = arg.value;
json_object *jresp;
unsigned int volume[8], i;
char *volume_i;
if (100 < volume[0]) {
free (volume_i);
- //request.errcode = MHD_HTTP_SERVICE_UNAVAILABLE;
- afb_req_fail (request, "Failed", "Volume must be between 0 and 100");
+ afb_req_fail (request, "failed", "volume must be between 0 and 100");
return;
}
ctx->volume[0] = volume[0];
afb_req_success (request, jresp, "Audio - Volume changed");
}
-STATIC void channels (struct afb_req request) { /* AFB_SESSION_CHECK */
+static void channels (struct afb_req request) { /* AFB_SESSION_CHECK */
- audioCtxHandleT *ctx = (audioCtxHandleT*)request.context;
- const char *value = afb_req_argument (request, "value");
+ audioCtxHandleT *ctx = (audioCtxHandleT*) afb_req_context_get(request);
+ struct afb_arg arg = afb_req_get (request, "value");
+ const char *value = arg.value;
json_object *jresp = json_object_new_object();
char channels_str[256];
afb_req_success (request, jresp, "Audio - Channels set");
}
-STATIC void mute (struct afb_req request) { /* AFB_SESSION_CHECK */
+static void mute (struct afb_req request) { /* AFB_SESSION_CHECK */
- audioCtxHandleT *ctx = (audioCtxHandleT*)request.context;
- const char *value = afb_req_argument (request, "value");
+ audioCtxHandleT *ctx = (audioCtxHandleT*) afb_req_context_get(request);
+ struct afb_arg arg = afb_req_get (request, "value");
+ const char *value = arg.value;
json_object *jresp = json_object_new_object();
/* no "?value=" parameter : return current state */
afb_req_success (request, jresp, "Audio - Mute set");
}
-STATIC void play (struct afb_req request) { /* AFB_SESSION_CHECK */
+static void play (struct afb_req request) { /* AFB_SESSION_CHECK */
- audioCtxHandleT *ctx = (audioCtxHandleT*)request.context;
- const char *value = afb_req_argument (request, "value");
+ audioCtxHandleT *ctx = (audioCtxHandleT*) afb_req_context_get(request);
+ struct afb_arg arg = afb_req_get (request, "value");
+ const char *value = arg.value;
json_object *jresp = json_object_new_object();
/* no "?value=" parameter : return current state */
afb_req_success (request, jresp, "Audio - Play");
}
-STATIC void ping (struct afb_req request) { /* AFB_SESSION_NONE */
+static void ping (struct afb_req request) { /* AFB_SESSION_NONE */
afb_req_success (request, NULL, "Audio - Ping success");
}
-STATIC const struct AFB_restapi pluginApis[]= {
+static const struct AFB_restapi pluginApis[]= {
{"init" , AFB_SESSION_CHECK, init , "Audio API - init"},
{"volume" , AFB_SESSION_CHECK, volume , "Audio API - volume"},
{"channels", AFB_SESSION_CHECK, channels , "Audio API - channels"},
{NULL}
};
-STATIC const struct AFB_plugin plug_desc = {
+static const struct AFB_plugin pluginDesc = {
.type = AFB_PLUGIN_JSON,
.info = "Application Framework Binder - Audio plugin",
.prefix = "audio",
.apis = pluginApis
};
+
+const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf)
+{
+ return &pluginDesc;
+}
#include "audio-api.h"
#include "audio-pulse.h"
-PUBLIC unsigned char _pulse_init (const char *name, audioCtxHandleT *ctx) {
+static struct alsa_info **alsa_info = NULL;
+static struct dev_ctx_pulse **dev_ctx_p = NULL;
+static unsigned int client_count = 0;
+
+
+unsigned char _pulse_init (const char *name, audioCtxHandleT *ctx) {
pa_mainloop *pa_loop;
pa_mainloop_api *pa_api;
pa_mainloop_iterate (pa_loop, 0, &ret);
if (ret == -1) {
- if (verbose) fprintf (stderr, "Stopping PulseAudio backend...\n");
+ fprintf (stderr, "Stopping PulseAudio backend...\n");
return 0;
}
if (ret >= 0) {
/* found a matching sink from callback */
- if (verbose) fprintf (stderr, "Success : using sink n.%d\n", error);
+ fprintf (stderr, "Success : using sink n.%d\n", error);
ctx->audio_dev = (void*)dev_ctx_p[ret];
break;
}
client_count++;
- if (verbose) fprintf (stderr, "Successfully initialized PulseAudio backend.\n");
+ fprintf (stderr, "Successfully initialized PulseAudio backend.\n");
return 1;
}
-PUBLIC void _pulse_free (audioCtxHandleT *ctx) {
+void _pulse_free (audioCtxHandleT *ctx) {
int num, i;
}
}
-PUBLIC void _pulse_play (audioCtxHandleT *ctx) {
+void _pulse_play (audioCtxHandleT *ctx) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
pthread_create (&dev_ctx_p_c->thr, NULL, _pulse_play_thread_fn, (void*)dev_ctx_p_c);
}
-PUBLIC void _pulse_stop (audioCtxHandleT *ctx) {
+void _pulse_stop (audioCtxHandleT *ctx) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
pthread_join (dev_ctx_p_c->thr, NULL);
}
-PUBLIC unsigned int _pulse_get_volume (audioCtxHandleT *ctx, unsigned int channel) {
+unsigned int _pulse_get_volume (audioCtxHandleT *ctx, unsigned int channel) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
return dev_ctx_p_c->volume.values[channel];
}
-PUBLIC void _pulse_set_volume (audioCtxHandleT *ctx, unsigned int channel, unsigned int vol) {
+void _pulse_set_volume (audioCtxHandleT *ctx, unsigned int channel, unsigned int vol) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
struct pa_cvolume volume;
_pulse_refresh_sink (dev_ctx_p_c);
}
-PUBLIC void _pulse_set_volume_all (audioCtxHandleT *ctx, unsigned int vol) {
+void _pulse_set_volume_all (audioCtxHandleT *ctx, unsigned int vol) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
struct pa_cvolume volume;
_pulse_refresh_sink (dev_ctx_p_c);
}
-PUBLIC unsigned char _pulse_get_mute (audioCtxHandleT *ctx) {
+unsigned char _pulse_get_mute (audioCtxHandleT *ctx) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
return (unsigned char)dev_ctx_p_c->mute;
}
-PUBLIC void _pulse_set_mute (audioCtxHandleT *ctx, unsigned char mute) {
+void _pulse_set_mute (audioCtxHandleT *ctx, unsigned char mute) {
dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
/* ---- LOCAL CALLBACK FUNCTIONS ---- */
-STATIC void _pulse_context_cb (pa_context *context, void *data) {
+void _pulse_context_cb (pa_context *context, void *data) {
pa_context_state_t state = pa_context_get_state (context);
dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T *)data;
pa_context_get_sink_info_list (context, _pulse_sink_list_cb, (void*)dev_ctx_p_t);
}
-STATIC void _pulse_sink_list_cb (pa_context *context, const pa_sink_info *info,
+void _pulse_sink_list_cb (pa_context *context, const pa_sink_info *info,
int eol, void *data) {
dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T *)data;
for (i = 0; i < (sizeof(cards)/sizeof(char*)); i++) {
if (!strcmp (cards[i], dev_ctx_p_t->card_name[0])) {
/* it did : stop there and succeed */
- if (verbose) fprintf (stderr, "Found matching sink : %s\n", info->name);
+ fprintf (stderr, "Found matching sink : %s\n", info->name);
pa_mainloop_quit (dev_ctx_p_t->pa_loop, num);
}
}
for (i = 0; i < (sizeof(cards)/sizeof(char*)); i++) {
if (!strcmp (cards[i], dev_ctx_p_t->card_name[0])) {
/* it did : stop there and succeed */
- if (verbose) fprintf (stderr, "Found matching sink : %s\n", info->name);
+ fprintf (stderr, "Found matching sink : %s\n", info->name);
pa_mainloop_quit (dev_ctx_p_t->pa_loop, num);
}
}
}
-STATIC void _pulse_sink_info_cb (pa_context *context, const pa_sink_info *info,
+void _pulse_sink_info_cb (pa_context *context, const pa_sink_info *info,
int eol, void *data) {
dev_ctx_pulse_T *dev_ctx_p_c = (dev_ctx_pulse_T *)data;
/* ---- LOCAL THREADED FUNCTIONS ---- */
-STATIC void* _pulse_play_thread_fn (void *ctx) {
+void* _pulse_play_thread_fn (void *ctx) {
dev_ctx_pulse_T *dev_ctx_p_c = (dev_ctx_pulse_T *)ctx;
FILE *file = NULL;
#include <pulse/error.h>
#include "audio-alsa.h"
-#include "local-def.h"
typedef struct dev_ctx_pulse dev_ctx_pulse_T;
typedef struct alsa_info alsa_info_T;
char *synonyms;
};
-PUBLIC unsigned char _pulse_init (const char *, audioCtxHandleT *);
-PUBLIC void _pulse_free (audioCtxHandleT *);
-PUBLIC void _pulse_play (audioCtxHandleT *);
-PUBLIC void _pulse_stop (audioCtxHandleT *);
-PUBLIC unsigned int _pulse_get_volume (audioCtxHandleT *, unsigned int);
-PUBLIC void _pulse_set_volume (audioCtxHandleT *, unsigned int, unsigned int);
-PUBLIC void _pulse_set_volume_all (audioCtxHandleT *, unsigned int);
-PUBLIC unsigned char _pulse_get_mute (audioCtxHandleT *);
-PUBLIC void _pulse_set_mute (audioCtxHandleT *, unsigned char);
+unsigned char _pulse_init (const char *, audioCtxHandleT *);
+void _pulse_free (audioCtxHandleT *);
+void _pulse_play (audioCtxHandleT *);
+void _pulse_stop (audioCtxHandleT *);
+unsigned int _pulse_get_volume (audioCtxHandleT *, unsigned int);
+void _pulse_set_volume (audioCtxHandleT *, unsigned int, unsigned int);
+void _pulse_set_volume_all (audioCtxHandleT *, unsigned int);
+unsigned char _pulse_get_mute (audioCtxHandleT *);
+void _pulse_set_mute (audioCtxHandleT *, unsigned char);
-STATIC void _pulse_context_cb (pa_context *, void *);
-STATIC void _pulse_sink_list_cb (pa_context *, const pa_sink_info *, int, void *);
-STATIC void _pulse_sink_info_cb (pa_context *, const pa_sink_info *, int, void *);
-STATIC void* _pulse_play_thread_fn (void *);
-PUBLIC void _pulse_refresh_sink (dev_ctx_pulse_T *);
-
-static struct alsa_info **alsa_info = NULL;
-static struct dev_ctx_pulse **dev_ctx_p = NULL;
-static unsigned int client_count = 0;
+void _pulse_context_cb (pa_context *, void *);
+void _pulse_sink_list_cb (pa_context *, const pa_sink_info *, int, void *);
+void _pulse_sink_info_cb (pa_context *, const pa_sink_info *, int, void *);
+void* _pulse_play_thread_fn (void *);
+void _pulse_refresh_sink (dev_ctx_pulse_T *);
#endif /* AUDIO_PULSE_H */