speechd-discuss
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]