[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Add a socket audio plugin
From: |
Trevor Saunders |
Subject: |
[PATCH] Add a socket audio plugin |
Date: |
Sun, 5 Dec 2010 01:12:26 -0500 |
The socket audio plugin writes the audio data out to a file descriptor.
Currently the file descriptor can be either a regular file or a unix
socket. The data is written out in a format similar to
http://freebsoft.org/doc/tts-api/tts-api.html#Audio-Retrieval.
---
src/modules/audio/Makefile.am | 2 +-
src/modules/audio/socket.c | 174 +++++++++++++++++++++++++++++++++
src/modules/audio/static_plugins.c.in | 3 +
src/modules/module_utils.c | 4 +
4 files changed, 182 insertions(+), 1 deletions(-)
create mode 100644 src/modules/audio/socket.c
diff --git a/src/modules/audio/Makefile.am b/src/modules/audio/Makefile.am
index 5c1d450..eda0e53 100644
--- a/src/modules/audio/Makefile.am
+++ b/src/modules/audio/Makefile.am
@@ -11,7 +11,7 @@ libsdaudio_la_LDFLAGS = -version-info \
$(LIB_SDAUDIO_CURRENT):$(LIB_SDAUDIO_REVISION):$(LIB_SDAUDIO_AGE)
libsdaudio_la_LIBADD = $(GLIB_LIBS) -lpthread \
$(ALSA_LIBS) $(LIBAO_LIBS) $(NAS_LIBS) $(PULSE_LIBS)
-libsdaudio_la_SOURCES = spd_audio.c spd_audio.h static_plugins.c
+libsdaudio_la_SOURCES = spd_audio.c spd_audio.h static_plugins.c socket.c
if alsa_support
libsdaudio_la_SOURCES += alsa.c
diff --git a/src/modules/audio/socket.c b/src/modules/audio/socket.c
new file mode 100644
index 0000000..6c1c46a
--- /dev/null
+++ b/src/modules/audio/socket.c
@@ -0,0 +1,174 @@
+
+#include<fcntl.h>
+#include<glib.h>
+#include<string.h>
+#include<stddef.h>
+#include<sys/socket.h>
+#include<sys/types.h>
+#include<sys/un.h>
+#include<unistd.h>
+
+#include<spd_audio_plugin.h>
+
+typedef enum{AUDIO_FILE, UNIX_SOCKET} AudioConnectionType;
+
+typedef struct{
+ AudioID id;
+ char *addr;
+ AudioConnectionType addr_type;
+ volatile int stop;
+} spd_socket_id_t;
+
+static int open_addr(spd_socket_id_t *id)
+{
+ int ret;
+
+ switch(id->addr_type){
+ case AUDIO_FILE:
+ return open(id->addr, O_WRONLY|O_CREAT);
+ break;
+ case UNIX_SOCKET:{
+ struct sockaddr_un addr;
+ int fd;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd < 0) return -1;
+
+ addr.sun_family = AF_UNIX;
+ if(PATH_MAX <= strlen(id->addr)) return -1;
+
+ strcpy(addr.sun_path, id->addr);
+ ret = connect(fd, (struct sockaddr*)&addr,
SUN_LEN(&addr));
+ if(ret < 0) return -1;
+
+ return fd;
+ } default:
+ return -1;
+ break;
+ }
+
+ /* we should never get here */
+ return -1;
+}
+
+static AudioID *socket_open(void **args)
+{
+ spd_socket_id_t *id;
+ int ret;
+
+ if(args == NULL) return NULL;
+ if(args[5] == NULL) return NULL;
+
+ id = g_malloc(sizeof(spd_socket_id_t));
+ id->addr = g_strdup(args[5]);
+ id->addr_type = (long) args[6];
+
+ return (AudioID*) id;
+}
+
+static int socket_play(AudioID *id, AudioTrack track)
+{
+ spd_socket_id_t *socket_id = (spd_socket_id_t*) id;
+ int ret, fd, bytes_per_sample;
+ long num_bytes, out_bytes;
+ char *header, *format_str;
+
+ if(id == NULL) return -1;
+
+ switch(id->format){
+ case SPD_AUDIO_LE:
+ format_str = "le";
+ break;
+ case SPD_AUDIO_BE:
+ format_str = "be";
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ switch(track.bits){
+ case 8:
+ bytes_per_sample = 1;
+ break;
+ case 16:
+ bytes_per_sample = 2;
+ break;
+ default:
+ return -1;
+ }
+
+ fd = open_addr((spd_socket_id_t*)id);
+ if(fd < 0) return -1;
+
+ /* we don't really want to force the open to be non-blocking, although
that should probably be fine, so we use fcntl here */
+ ret = fcntl(fd, F_SETFL, O_NONBLOCK);
+ if(ret != 0){
+ close(fd);
+ return -1;
+ }
+
+ out_bytes = 0;
+ num_bytes = track.num_samples * bytes_per_sample;
+ header = g_strdup_printf("data_length=%u\r\nsample_rate=%u\r\nchannels"
+ "=%d\r\narchitecture=%d%s\r\n\r\n", num_bytes,
+ track.sample_rate, track.num_channels, track.bits,
format_str);
+
+ write(fd, header, strlen(header));
+ do{
+ ret = write(fd, &((char*)track.samples)[out_bytes], num_bytes -
out_bytes);
+ out_bytes += ret;
+ }while((out_bytes < num_bytes) && (ret >= 0) && (socket_id->stop == 0));
+
+ close(fd);
+
+ return 0;
+}
+
+static int socket_stop(AudioID *id)
+{
+ if(id == NULL) return -1;
+
+ ((spd_socket_id_t*) id)->stop = 1;
+
+ return 0;
+}
+
+static int socket_set_volume(AudioID *id, int rate)
+{
+ /* un implemented */
+
+ return 0;
+}
+
+static void socket_set_loglevel(int level)
+{
+ /* not implemented */
+}
+
+static char const *socket_get_playcmd(void)
+{
+ /* is there something real we can return here */
+ return NULL;
+}
+
+static int socket_close(AudioID *id)
+{
+ g_free(((spd_socket_id_t*)id)->addr);
+ g_free(id);
+
+ return 0;
+}
+
+static spd_audio_plugin_t socket_functions = {
+ "socket",
+ socket_open,
+ socket_play,
+ socket_stop,
+ socket_close,
+ socket_set_volume,
+ socket_set_loglevel,
+ socket_get_playcmd,
+};
+
+spd_audio_plugin_t *socket_plugin_get(void) {return &socket_functions;}
diff --git a/src/modules/audio/static_plugins.c.in
b/src/modules/audio/static_plugins.c.in
index 055f4d1..52f7443 100644
--- a/src/modules/audio/static_plugins.c.in
+++ b/src/modules/audio/static_plugins.c.in
@@ -30,9 +30,12 @@
@STATIC_AUDIO_PLUGINS_EXTERN@
+extern spd_audio_plugin_t const *socket_plugin_get(void);
+
static spd_audio_plugin_t const * (* spd_audio_static_plugins[]) (void) =
{
@STATIC_AUDIO_PLUGINS_GET@
+ socket_plugin_get,
0
};
diff --git a/src/modules/module_utils.c b/src/modules/module_utils.c
index 6aa7568..d0ec6b2 100644
--- a/src/modules/module_utils.c
+++ b/src/modules/module_utils.c
@@ -274,6 +274,10 @@ do_audio(void)
else SET_AUDIO_STR(audio_nas_server, 3)
else SET_AUDIO_STR(audio_pulse_server, 4)
else SET_AUDIO_STR(audio_pulse_min_length, 5)
+ else SET_AUDIO_STR(audio_socket_addr, 6)
+ else if(strcmp(cur_item, "audio_socket_type") == 0){
+ module_audio_pars[7] = (char*)
atol(cur_value);
+ }
else err=2; /* Unknown parameter */
}
g_free(line);
--
1.7.2.3
- [PATCH] Add a socket audio plugin,
Trevor Saunders <=