diff options
author | Manuel Bachmann <manuel.bachmann@iot.bzh> | 2015-12-16 20:38:03 +0100 |
---|---|---|
committer | Manuel Bachmann <manuel.bachmann@iot.bzh> | 2015-12-16 20:38:49 +0100 |
commit | 241a06586b3602962874e6d2ac09e258ad6173d2 (patch) | |
tree | 20aab5fb5c5efa3516b9579256fc0652a83475af /plugins | |
parent | 785a37416c58fb6f86d3d89cbff240ce9f2d7e74 (diff) |
Initial Audio plugin
Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/CMakeLists.txt | 8 | ||||
-rw-r--r-- | plugins/audio/audio-alsa.c | 82 | ||||
-rw-r--r-- | plugins/audio/audio-alsa.h | 18 | ||||
-rw-r--r-- | plugins/audio/audio-api.c | 68 | ||||
-rw-r--r-- | plugins/audio/audio-api.h | 26 |
5 files changed, 181 insertions, 21 deletions
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 0ddaf453..76969380 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,11 +1,13 @@ -SET(AUDIO_PLUGIN audio/audio-api.c) SET(SESSION_PLUGIN session/token-api.c) SET(SAMPLE_PLUGINS samples/HelloWorld.c) +IF(alsa_FOUND) + SET(AUDIO_PLUGIN audio/audio-api.c audio/audio-alsa.c) +ENDIF(alsa_FOUND) IF(librtlsdr_FOUND) - SET(RADIO_PLUGIN radio/radio-rtlsdr.c radio/radio-api.c) + SET(RADIO_PLUGIN radio/radio-api.c radio/radio-rtlsdr.c) ENDIF(librtlsdr_FOUND) -SET(PLUGINS_SOURCES ${AUDIO_PLUGIN} ${SESSION_PLUGIN} ${RADIO_PLUGIN} ${SAMPLE_PLUGINS}) +SET(PLUGINS_SOURCES ${SESSION_PLUGIN} ${SAMPLE_PLUGINS} ${AUDIO_PLUGIN} ${RADIO_PLUGIN}) ADD_LIBRARY(plugins OBJECT ${PLUGINS_SOURCES}) INCLUDE_DIRECTORIES(${include_dirs}) diff --git a/plugins/audio/audio-alsa.c b/plugins/audio/audio-alsa.c new file mode 100644 index 00000000..8c08c8db --- /dev/null +++ b/plugins/audio/audio-alsa.c @@ -0,0 +1,82 @@ +#include "audio-api.h" +#include "audio-alsa.h" + +PUBLIC unsigned char _alsa_init (const char *name, audioCtxHandleT *ctx) { + + snd_pcm_t *dev; + snd_pcm_hw_params_t *params; + int num; + + if (snd_pcm_open (&dev, name, SND_PCM_STREAM_PLAYBACK, 0) < 0) + return 0; + + snd_pcm_hw_params_malloc (¶ms); + snd_pcm_hw_params_any (dev, params); + snd_pcm_hw_params_set_access (dev, params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format (dev, params, SND_PCM_FORMAT_S16_LE); + snd_pcm_hw_params_set_rate_near (dev, params, &ctx->rate, 0); + snd_pcm_hw_params_set_channels (dev, params, ctx->channels); + if (snd_pcm_hw_params (dev, params) < 0) { + snd_pcm_hw_params_free (params); + return 0; + } + snd_pcm_prepare (dev); + + /* allocate the global array if it hasn't been done */ + if (!dev_ctx) { + dev_ctx = (dev_ctx_T**) malloc (sizeof(dev_ctx_T)); + dev_ctx[0] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T)); + dev_ctx[0]->name = NULL; + dev_ctx[0]->dev = NULL; + } + + /* is a card with similar name already opened ? */ + for (num = 0; num < (sizeof(dev_ctx)/sizeof(dev_ctx_T)); num++) { + if (dev_ctx[num]->name && + !strcmp (dev_ctx[num]->name, name)) + return 0; + } + num++; + + /* it's not... let us add it to the global array */ + dev_ctx[num] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T)); + dev_ctx[num]->name = strdup (name); + dev_ctx[num]->dev = dev; + dev_ctx[num]->params = params; + + return 1; +} + +PUBLIC void _alsa_free (const char *name) { + + int num; + + for (num = 0; num < (sizeof(dev_ctx)/sizeof(dev_ctx_T)); num++) { + if (dev_ctx[num]->name && + !strcmp (dev_ctx[num]->name, name)) { + snd_pcm_close (dev_ctx[num]->dev); + snd_pcm_hw_params_free (dev_ctx[num]->params); + free (dev_ctx[num]->name); + dev_ctx[num]->name = NULL; + dev_ctx[num]->dev = NULL; + free(dev_ctx[num]); + return; + } + } +} + +PUBLIC void _alsa_play (unsigned int num, void *buf, int len) { + + if (!dev_ctx || !dev_ctx[num]) + return; + + int16_t *cbuf = (int16_t *)buf; + int frames = len / 2; + int res; + + if ((res = snd_pcm_writei (dev_ctx[num]->dev, cbuf, frames)) != frames) { + snd_pcm_recover (dev_ctx[num]->dev, res, 0); + snd_pcm_prepare (dev_ctx[num]->dev); + } + /* snd_pcm_drain (dev_ctx[num]->dev); */ +}
\ No newline at end of file diff --git a/plugins/audio/audio-alsa.h b/plugins/audio/audio-alsa.h new file mode 100644 index 00000000..a85f419d --- /dev/null +++ b/plugins/audio/audio-alsa.h @@ -0,0 +1,18 @@ +#ifndef AUDIO_ALSA_H +#define AUDIO_ALSA_H + +#include <alsa/asoundlib.h> + +#include "local-def.h" + +typedef struct dev_ctx dev_ctx_T; + +struct dev_ctx { + char *name; + snd_pcm_t *dev; + snd_pcm_hw_params_t *params; +}; + +static struct dev_ctx **dev_ctx = NULL; + +#endif /* AUDIO_ALSA_H */
\ No newline at end of file diff --git a/plugins/audio/audio-api.c b/plugins/audio/audio-api.c index 9d4f3cb6..547f97ed 100644 --- a/plugins/audio/audio-api.c +++ b/plugins/audio/audio-api.c @@ -16,36 +16,68 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "audio-api.h" +#include "audio-alsa.h" -#include "local-def.h" -STATIC json_object* wrongApi (AFB_request *request, void* handle) { - int zero=0; - int bug=1234; - int impossible; +/* ------ LOCAL HELPER FUNCTIONS --------- */ + +/* private client context creation ; default values */ +STATIC audioCtxHandleT* initAudioCtx () { + + audioCtxHandleT *ctx; + + ctx = malloc (sizeof(audioCtxHandleT)); + ctx->volume = 25; + ctx->rate = 22050; + ctx->channels = 2; + + return ctx; +} + +/* called when client session dies [e.g. client quits for more than 15mns] */ +STATIC json_object* freeAudio (AFB_clientCtx *client) { + + //releaseAudio (client->plugin->handle, client->ctx); + free (client->ctx); - impossible=bug/zero; + return jsonNewMessage (AFB_SUCCESS, "Released radio and client context"); } +/* ------ PUBLIC PLUGIN FUNCTIONS --------- */ -STATIC struct { - void * somedata; -} handle; +STATIC json_object* init (AFB_request *request) { /* AFB_SESSION_CREATE */ + audioCtxHandleT *ctx; + json_object *jresp; + + /* create a private client context */ + ctx = initAudioCtx(); + request->client->ctx = (audioCtxHandleT*)ctx; + + _alsa_init("default", ctx); + + jresp = json_object_new_object(); + json_object_object_add (jresp, "token", json_object_new_string (request->client->token)); +} -STATIC AFB_restapi pluginApis[]= { - {"ping" , AFB_SESSION_NONE, (AFB_apiCB)apiPingTest,"Ping Application Framework"}, - {"error" , AFB_SESSION_NONE, (AFB_apiCB)wrongApi , "Ping Application Framework"}, + +STATIC AFB_restapi pluginApis[]= { + {"init" , AFB_SESSION_CREATE, (AFB_apiCB)init , "Audio API - init"}, +// {"error" , AFB_SESSION_CHECK, (AFB_apiCB)wrongApi , "Ping Application Framework"}, {NULL} }; -PUBLIC AFB_plugin *alsaRegister () { - AFB_plugin *plugin = malloc (sizeof (AFB_plugin)); - plugin->type = AFB_PLUGIN_JSON; - plugin->info = "Application Framework Binder Service"; - plugin->prefix= "alsa"; - plugin->apis = pluginApis; +PUBLIC AFB_plugin *audioRegister () { + AFB_plugin *plugin = malloc (sizeof(AFB_plugin)); + plugin->type = AFB_PLUGIN_JSON; + plugin->info = "Application Framework Binder - Audio plugin"; + plugin->prefix = "audio"; + plugin->apis = pluginApis; + + plugin->freeCtxCB = freeAudio; + return (plugin); };
\ No newline at end of file diff --git a/plugins/audio/audio-api.h b/plugins/audio/audio-api.h new file mode 100644 index 00000000..0928f0fa --- /dev/null +++ b/plugins/audio/audio-api.h @@ -0,0 +1,26 @@ +#ifndef AUDIO_API_H +#define AUDIO_API_H + +#include "audio-alsa.h" + +/* global plugin handle, should store everything we may need */ +typedef struct { + int devCount; +} pluginHandleT; + +/* structure holding one audio card with current usage status */ +typedef struct { + char *name; + void *handle; /* handle to implementation (ALSA, PulseAudio...) */ + } audioDevT; + +/* private client context [will be destroyed when client leaves] */ +typedef struct { + audioDevT *radio; /* pointer to client audio card */ + unsigned int volume; /* audio volume : 0-100 */ + unsigned int rate; /* audio rate (Hz) */ + unsigned int channels; /* audio channels : 1(mono)/2(stereo)... */ +} audioCtxHandleT; + + +#endif /* AUDIO_API_H */
\ No newline at end of file |