summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bachmann <manuel.bachmann@iot.bzh>2015-12-16 20:38:03 +0100
committerManuel Bachmann <manuel.bachmann@iot.bzh>2015-12-16 20:38:49 +0100
commit241a06586b3602962874e6d2ac09e258ad6173d2 (patch)
tree20aab5fb5c5efa3516b9579256fc0652a83475af
parent785a37416c58fb6f86d3d89cbff240ce9f2d7e74 (diff)
Initial Audio plugin
Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
-rw-r--r--CMakeLists.txt8
-rw-r--r--README.md1
-rw-r--r--include/proto-def.h5
-rw-r--r--plugins/CMakeLists.txt8
-rw-r--r--plugins/audio/audio-alsa.c82
-rw-r--r--plugins/audio/audio-alsa.h18
-rw-r--r--plugins/audio/audio-api.c68
-rw-r--r--plugins/audio/audio-api.h26
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/rest-api.c4
10 files changed, 196 insertions, 27 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af98b389..a3ab4c37 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,8 +37,12 @@ PKG_CHECK_MODULES(json-c REQUIRED json-c)
PKG_CHECK_MODULES(libmicrohttpd REQUIRED libmicrohttpd)
PKG_CHECK_MODULES(uuid REQUIRED uuid)
# Optional plugin dependencies
+PKG_CHECK_MODULES(alsa alsa)
PKG_CHECK_MODULES(librtlsdr librtlsdr>=0.5.0)
+IF(alsa_FOUND)
+ MESSAGE(STATUS "ALSA found ; will compile Audio plugin... (PLUGIN)")
+ENDIF(alsa_FOUND)
IF(librtlsdr_FOUND)
MESSAGE(STATUS "librtlsdr found ; will compile Radio plugin... (PLUGIN)")
ENDIF(librtlsdr_FOUND)
@@ -46,8 +50,8 @@ ENDIF(librtlsdr_FOUND)
INCLUDE(FindThreads)
FIND_PACKAGE(Threads)
-SET(include_dirs ${INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include ${json-c_INCLUDE_DIRS} ${libmicrohttpd_INCLUDE_DIRS} ${librtlsdr_INCLUDE_DIRS})
-SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${librtlsdr_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} -lmagic -lm)
+SET(include_dirs ${INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include ${json-c_INCLUDE_DIRS} ${libmicrohttpd_INCLUDE_DIRS} ${uuid_INCLUDE_DIRS} ${alsa_INCLUDE_DIRS} ${librtlsdr_INCLUDE_DIRS})
+SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${alsa_LIBRARIES} ${librtlsdr_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} -lmagic -lm)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(plugins)
diff --git a/README.md b/README.md
index cb23e45c..5846f001 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ industry requirementsas the primary target for this code is AGL.
optionally, for plugins :
+ * alsa ("libasound2-dev/alsa-devel");
* rtl-sdr >= 0.5.0 (fetch and build from "git://git.osmocom.org/rtl-sdr");
and the following tools:
diff --git a/include/proto-def.h b/include/proto-def.h
index fc3a9cfa..4241b4b9 100644
--- a/include/proto-def.h
+++ b/include/proto-def.h
@@ -34,10 +34,9 @@ void initPlugins (AFB_session *session);
typedef AFB_plugin* (*AFB_pluginCB)();
PUBLIC AFB_plugin* tokenRegister ();
-PUBLIC AFB_plugin* dbusRegister ();
-PUBLIC AFB_plugin* alsaRegister ();
-PUBLIC AFB_plugin* radioRegister ();
+PUBLIC AFB_plugin* audioRegister ();
PUBLIC AFB_plugin* helloWorldRegister ();
+PUBLIC AFB_plugin* radioRegister ();
// Session handling
PUBLIC AFB_error sessionCheckdir (AFB_session *session);
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 (&params);
+ 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
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 50e3ef37..ebf023af 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,3 +1,6 @@
+IF(alsa_FOUND)
+ ADD_DEFINITIONS(-DHAVE_AUDIO_PLUGIN=1)
+ENDIF(alsa_FOUND)
IF(librtlsdr_FOUND)
ADD_DEFINITIONS(-DHAVE_RADIO_PLUGIN=1)
ENDIF(librtlsdr_FOUND)
diff --git a/src/rest-api.c b/src/rest-api.c
index 06b6ea87..c7f4b03e 100644
--- a/src/rest-api.c
+++ b/src/rest-api.c
@@ -615,8 +615,10 @@ void initPlugins(AFB_session *session) {
int i = 0;
plugins[i++] = tokenRegister(session),
- plugins[i++] = alsaRegister(session),
plugins[i++] = helloWorldRegister(session),
+#ifdef HAVE_AUDIO_PLUGIN
+ plugins[i++] = audioRegister(session),
+#endif
#ifdef HAVE_RADIO_PLUGIN
plugins[i++] = radioRegister(session),
#endif