speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

WIP audio in server


From: Trevor Saunders
Subject: WIP audio in server
Date: Thu, 13 Aug 2015 18:43:32 -0400

On Mon, Aug 10, 2015 at 08:21:00PM -0600, Jeremy Whiting wrote:
> Ok, last patch of the day. Undone items:
> 
> 1. Audio socket cleanup. Not sure what needs to be done here. Should
> the socket files get deleted during shutdown, etc.

is there some reason to use a socket instead of just pipe(2) then you
wouldn't need to deal with this at all?

> 2. Stopping audio (probably can be done from parse_stop in parse.c
> 3. Play command use which is only used in generic.c

iirc a couple other modules ivona and festival I think do there own
thing where the synth is a separate process and does its own audio I
think.  I don't really have any great ideas here.

Have you considered using a process separate from the main server for
audio output?  I guess its not all that complicated, but it might allow
us to sandbox a bit more of speech dispatcher.

Trev

> 
> BR,
> Jeremy
> 
> On Mon, Aug 10, 2015 at 7:05 PM, Jeremy Whiting <jpwhiting at kde.org> wrote:
> > Ok, another update. This time audio parameters are coming from the
> > user's config (I think, GlobalFDSet getting initialized is a mystery
> > to me so far because of macros and dotconf callbacks. Seems to work
> > here though.
> >
> > BR,
> > Jeremy
> >
> >
> > On Mon, Aug 10, 2015 at 5:43 PM, Jeremy Whiting <jpwhiting at kde.org> 
> > wrote:
> >> Ok, here's a working patch. A few things I'll fix before this is ready
> >> for master though.
> >>
> >> 1. Audio initialization needs to come from the config files again.
> >> 2. Audio socket cleanup.
> >> 3. Documentation changes for this big change in how spd works.
> >> 4. How to request the server stop playing audio (or maybe it knows
> >> because it's telling the modules the same thing...
> >> 5. Audio file playback in generic.c needs to open the file and send
> >> the audio on the socket.
> >>
> >> BR,
> >> Jeremy
> >>
> >>
> >> On Wed, Aug 5, 2015 at 5:42 PM, Jeremy Whiting <jpwhiting at kde.org> 
> >> wrote:
> >>> Ok, the audio in the server is in it's own thread now, and mostly all
> >>> code is in server/audio.c to keep it separate from the other file
> >>> descriptor handling for clients. I'm still getting pauses for some
> >>> reason, but it is threaded now at least and works when run with -d
> >>> also. I'll try to figure out where the pauses are coming from.
> >>>
> >>> BR,
> >>> Jeremy
> >>>
> >>> On Fri, Jul 31, 2015 at 6:47 PM, Jeremy Whiting <jpwhiting at kde.org> 
> >>> wrote:
> >>>> I've spent a bit of time wrestling with this code today and have found
> >>>> the following.
> >>>>
> >>>> If I don't initialize pulse by calling _pulse_open but only initialize
> >>>> once I have data to set the format it works mostly, though there are
> >>>> pauses of silence in long phrases from espeak still.
> >>>> If I do initialize pulse by calling _pulse_open in pulse_open and also
> >>>> reinitializing in pulse_play as required for audio rate changes etc.
> >>>> it doesn't play anything somehow (it's getting stuck in pa_simple_free
> >>>> on a mutex somehow).
> >>>>
> >>>> Do I need to run a thread for every audio socket we attach in the
> >>>> server? If so what should the thread's start_routine look like, just
> >>>> while(1) and the callback audio_process_incoming is called when we get
> >>>> traffic on the fd ? Once this is working (and I clean up how we
> >>>> initialize the audio to not hard coded values, but get the config from
> >>>> the config file) I can look at making the audio use the pulse async
> >>>> api, but I want to get the proof of concept working as a first step.
> >>>> My knowledge of pthreads seems to be blocking me at the moment though.
> >>>>
> >>>> thanks,
> >>>> Jeremy
> >>>>
> >>>>
> >>>>
> >>>> On Thu, Jul 30, 2015 at 7:42 PM, Jeremy Whiting <jpwhiting at kde.org> 
> >>>> wrote:
> >>>>> Oops, I didn't see this until just now. At any rate I got that issue
> >>>>> solved, now only playback failing (I verified I get samples in the
> >>>>> server and I think it's initializing the AudioId properly since it's
> >>>>> not NULL here. It seems to think it's playing from all the return
> >>>>> values, but I hear no audio yet. I also wasn't sure what to do about
> >>>>> sending the audio parameters just yet, so hard coded some based on my
> >>>>> config here for now.
> >>>>>
> >>>>> BR,
> >>>>> Jeremy
> >>>>>
> >>>>> On Thu, Jul 30, 2015 at 6:40 PM, Luke Yelavich
> >>>>> <luke.yelavich at canonical.com> wrote:
> >>>>>> On Fri, Jul 31, 2015 at 10:40:04AM AEST, Luke Yelavich wrote:
> >>>>>>> On Fri, Jul 31, 2015 at 07:27:27AM AEST, Jeremy Whiting wrote:
> >>>>>>> > Hey all,
> >>>>>>> >
> >>>>>>> > I'm implementing moving audio from the modules to the server (and
> >>>>>>> > modules will send audio data to the server on a unix socket). I've 
> >>>>>>> > got
> >>>>>>> > the socket creation, and seem to have the ability to connect to the
> >>>>>>> > socket in the modules but it's hanging here when I try to run 
> >>>>>>> > spd-say
> >>>>>>> > hello. Also I'm getting this in my speech-dispatcher.log as if it's
> >>>>>>> > trying to open a second audio connection from sd_espeak for some
> >>>>>>> > reason when it hangs (and no log output after this):
> >>>>>>> >
> >>>>>>> > [Thu Jul 30 15:03:15 2015 : 829380] speechd:     Adding audio
> >>>>>>> > connection on socket 4
> >>>>>>> > [Thu Jul 30 15:03:29 2015 : 105629] speechd:    Adding module on fd 
> >>>>>>> > 28
> >>>>>>> > [Thu Jul 30 15:03:29 2015 : 105654] speechd:     Adding audio
> >>>>>>> > connection on socket 4
> >>>>>>> >
> >>>>>>> > I'm probably doing something obviously wrong, but can't seem to see
> >>>>>>> > what at the moment though I've been beating my head against it for a
> >>>>>>> > while and debugging. Can you see anything obvious in my changes?
> >>>>>>>
> >>>>>>> Well, I wonder if what you have in speechd_audio_connection_new is 
> >>>>>>> correct. You make reference to module sockets and the server socket 
> >>>>>>> where clients connect, and not the audio socket.
> >>>>>>
> >>>>>> Helps if I attach the diff.
> >>>>>>
> >>>>>> Luke

> From 51316a1237c09b50a1c84a44348a278c5982a056 Mon Sep 17 00:00:00 2001
> From: Jeremy Whiting <jpwhiting at kde.org>
> Date: Wed, 29 Jul 2015 18:28:03 -0600
> Subject: [PATCH] Moving audio from modules to the server.
> 
> Audio socket is created in the server.
> Audio system is initialized in the server.
> Modules connect to audio socket and send audio data (metadata first separated 
> by :, then samples).
> Server receives AudioTrack deserializes the metadata and plays AudioTrack.
> Updated speech-dispatcher.texi to remove section about AUDIO command handling 
> as it's gone.
> ---
>  doc/speech-dispatcher.texi |   5 -
>  include/speechd_defines.h  |  19 +-
>  src/Makefile.am            |   2 +-
>  src/modules/Makefile.am    |  30 +--
>  src/modules/espeak.c       |  34 +--
>  src/modules/festival.c     |   7 +-
>  src/modules/generic.c      |   4 +-
>  src/modules/module_main.c  |  16 +-
>  src/modules/module_utils.c | 184 +++++--------
>  src/modules/module_utils.h |   4 +-
>  src/modules/spd_audio.c    | 321 ----------------------
>  src/modules/spd_audio.h    |  46 ----
>  src/server/Makefile.am     |   8 +-
>  src/server/audio.c         | 647 
> +++++++++++++++++++++++++++++++++++++++++++++
>  src/server/audio.h         |  60 +++++
>  src/server/module.c        |  12 -
>  src/server/msg.h           |   3 +-
>  src/server/output.c        |  23 --
>  src/server/output.h        |   1 -
>  src/server/server.c        |   1 +
>  src/server/set.c           |  14 +
>  src/server/set.h           |   1 +
>  src/server/speechd.c       |  21 +-
>  src/server/speechd.h       |   9 +
>  24 files changed, 877 insertions(+), 595 deletions(-)
>  delete mode 100644 src/modules/spd_audio.c
>  delete mode 100644 src/modules/spd_audio.h
>  create mode 100644 src/server/audio.c
>  create mode 100644 src/server/audio.h
> 
> diff --git a/doc/speech-dispatcher.texi b/doc/speech-dispatcher.texi
> index 88ca972..2d1a0ad 100755
> --- a/doc/speech-dispatcher.texi
> +++ b/doc/speech-dispatcher.texi
> @@ -2752,11 +2752,6 @@ punctuation_some=NULL
>  203 OK SETTINGS RECEIVED
>  @end example
>  
> - at item AUDIO
> -Audio has exactly the same structure as @code{SET}, but is transmitted
> -only once immediatelly after @code{INIT} to transmit the requested audio
> -parameters and tell the output module to open the audio device.
> -
>  @item QUIT
>  Terminates the output module. It should send the response, deallocate
>  all the resources, close all descriptors, terminate all child
> diff --git a/include/speechd_defines.h b/include/speechd_defines.h
> index 3a544f0..d540c29 100644
> --- a/include/speechd_defines.h
> +++ b/include/speechd_defines.h
> @@ -22,14 +22,15 @@
>  #ifndef SPEECHD_DEFINES_H
>  #define SPEECHD_DEFINES_H
>  
> -#define SPD_ALLCLIENTS "ALL"
> -#define SPD_SELF "SELF"
> -#define SPD_VOLUME "VOLUME"
> -#define SPD_PITCH "PITCH"
> -#define SPD_PITCH_RANGE "PITCH_RANGE"
> -#define SPD_RATE "RATE"
> -#define SPD_LANGUAGE "LANGUAGE"
> -#define SPD_OUTPUT_MODULE "OUTPUT_MODULE"
> -#define SPD_SYNTHESIS_VOICE "SYNTHESIS_VOICE"
> +#define NEWLINE                      "\r\n"
> +#define SPD_ALLCLIENTS               "ALL"
> +#define SPD_SELF             "SELF"
> +#define SPD_VOLUME           "VOLUME"
> +#define SPD_PITCH            "PITCH"
> +#define SPD_PITCH_RANGE              "PITCH_RANGE"
> +#define SPD_RATE             "RATE"
> +#define SPD_LANGUAGE         "LANGUAGE"
> +#define SPD_OUTPUT_MODULE    "OUTPUT_MODULE"
> +#define SPD_SYNTHESIS_VOICE  "SYNTHESIS_VOICE"
>  
>  #endif /* not ifndef SPEECHD_DEFINES_H */
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 81d0690..8690889 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -1,4 +1,4 @@
>  ## Process this file with automake to produce Makefile.in
>  
> -SUBDIRS=common server audio modules api clients tests
> +SUBDIRS=common audio server modules api clients tests
>  
> diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
> index 9012a4b..7010e39 100644
> --- a/src/modules/Makefile.am
> +++ b/src/modules/Makefile.am
> @@ -1,84 +1,74 @@
>  ## Process this file with automake to produce Makefile.in
>  
>  inc_local = -I$(top_srcdir)/include
> -audio_SOURCES = spd_audio.c spd_audio.h
>  common_SOURCES = module_main.c module_utils.c module_utils.h
>  common_LDADD = $(SNDFILE_LIBS) $(DOTCONF_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS)
>  
>  AM_CFLAGS = $(ERROR_CFLAGS)
>  AM_CPPFLAGS = $(inc_local) -DDATADIR=\"$(snddatadir)\" -D_GNU_SOURCE \
> -     -DPLUGIN_DIR="\"$(audiodir)\"" \
>       $(DOTCONF_CFLAGS) $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \
>       $(ibmtts_include) $(SNDFILE_CFLAGS)
>  
>  modulebin_PROGRAMS = sd_dummy sd_generic sd_festival sd_cicero
>  
> -sd_dummy_SOURCES = dummy.c $(audio_SOURCES) $(common_SOURCES) \
> +sd_dummy_SOURCES = dummy.c $(common_SOURCES) \
>       module_utils_addvoice.c
>  sd_dummy_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       $(common_LDADD)
>  dist_snddata_DATA = dummy-message.wav
>  
>  sd_festival_SOURCES = festival.c festival_client.c festival_client.h \
> -     $(audio_SOURCES) $(common_SOURCES)
> +     $(common_SOURCES)
>  sd_festival_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       $(common_LDADD) $(EXTRA_SOCKET_LIBS)
>  
> -sd_generic_SOURCES = generic.c $(audio_SOURCES) $(common_SOURCES) \
> +sd_generic_SOURCES = generic.c $(common_SOURCES) \
>       module_utils_addvoice.c
>  sd_generic_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       $(common_LDADD)
>  
> -sd_cicero_SOURCES = cicero.c $(audio_SOURCES) $(common_SOURCES)
> +sd_cicero_SOURCES = cicero.c $(common_SOURCES)
>  sd_cicero_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       $(common_LDADD)
>  
>  if flite_support
>  modulebin_PROGRAMS += sd_flite
> -sd_flite_SOURCES = flite.c $(audio_SOURCES) $(common_SOURCES)
> +sd_flite_SOURCES = flite.c $(common_SOURCES)
>  sd_flite_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       $(flite_kal) $(flite_basic) \
>       $(common_LDADD)
>  endif
>  
>  if ibmtts_support
>  modulebin_PROGRAMS += sd_ibmtts
> -sd_ibmtts_SOURCES = ibmtts.c $(audio_SOURCES) $(common_SOURCES) \
> +sd_ibmtts_SOURCES = ibmtts.c $(common_SOURCES) \
>       module_utils_addvoice.c
>  sd_ibmtts_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       -libmeci \
>       $(common_LDADD)
>  endif
>  
>  if espeak_support
>  modulebin_PROGRAMS += sd_espeak
> -sd_espeak_SOURCES = espeak.c $(audio_SOURCES) $(common_SOURCES)
> +sd_espeak_SOURCES = espeak.c $(common_SOURCES)
>  sd_espeak_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       -lespeak $(EXTRA_ESPEAK_LIBS) \
>       $(common_LDADD)
>  endif
>  
>  if ivona_support
>  modulebin_PROGRAMS += sd_ivona
> -sd_ivona_SOURCES = ivona.c ivona_client.c ivona_client.h $(audio_SOURCES) \
> +sd_ivona_SOURCES = ivona.c ivona_client.c ivona_client.h \
>       $(common_SOURCES)
>  sd_ivona_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) \
>       -ldumbtts \
>       $(common_LDADD)
>  endif
>  
>  if pico_support
>  modulebin_PROGRAMS += sd_pico
> -sd_pico_SOURCES = pico.c $(audio_SOURCES) $(common_SOURCES)
> +sd_pico_SOURCES = pico.c $(common_SOURCES)
>  sd_pico_LDADD = $(top_builddir)/src/common/libcommon.la \
> -     $(audio_dlopen_modules) -lttspico \
> +     -lttspico \
>       $(common_LDADD)
>  endif
> diff --git a/src/modules/espeak.c b/src/modules/espeak.c
> index 48fc743..6fb9ffe 100644
> --- a/src/modules/espeak.c
> +++ b/src/modules/espeak.c
> @@ -43,7 +43,6 @@
>  #endif
>  
>  /* Speech Dispatcher includes. */
> -#include "spd_audio.h"
>  #include <speechd_types.h>
>  #include "module_utils.h"
>  
> @@ -558,22 +557,23 @@ static void *_espeak_stop_or_pause(void *nothing)
>               pthread_cond_broadcast(&playback_queue_condition);
>               pthread_mutex_unlock(&playback_queue_mutex);
>  
> -             if (module_audio_id) {
> -                     DBG("Espeak: Stopping audio.");
> -                     ret = spd_audio_stop(module_audio_id);
> -                     DBG_WARN(ret == 0,
> -                              "spd_audio_stop returned non-zero value.");
> -                     while (is_thread_busy(&espeak_play_suspended_mutex)) {
> -                             ret = spd_audio_stop(module_audio_id);
> -                             DBG_WARN(ret == 0,
> -                                      "spd_audio_stop returned non-zero 
> value.");
> -                             g_usleep(5000);
> -                     }
> -             } else {
> -                     while (is_thread_busy(&espeak_play_suspended_mutex)) {
> -                             g_usleep(5000);
> -                     }
> -             }
> +             /* TODO: Add a way to request the server stop audio playback */
> +//           if (module_audio_id) {
> +//                   DBG("Espeak: Stopping audio.");
> +//                   ret = spd_audio_stop(module_audio_id);
> +//                   DBG_WARN(ret == 0,
> +//                            "spd_audio_stop returned non-zero value.");
> +//                   while (is_thread_busy(&espeak_play_suspended_mutex)) {
> +//                           ret = spd_audio_stop(module_audio_id);
> +//                           DBG_WARN(ret == 0,
> +//                                    "spd_audio_stop returned non-zero 
> value.");
> +//                           g_usleep(5000);
> +//                   }
> +//           } else {
> +//                   while (is_thread_busy(&espeak_play_suspended_mutex)) {
> +//                           g_usleep(5000);
> +//                   }
> +//           }
>  
>               DBG("Espeak: Waiting for synthesis to stop.");
>               ret = espeak_Cancel();
> diff --git a/src/modules/festival.c b/src/modules/festival.c
> index df6d58a..39ab49e 100644
> --- a/src/modules/festival.c
> +++ b/src/modules/festival.c
> @@ -431,9 +431,10 @@ int module_stop(void)
>               if (!festival_stop) {
>                       pthread_mutex_lock(&sound_output_mutex);
>                       festival_stop = 1;
> -                     if (festival_speaking && module_audio_id) {
> -                             spd_audio_stop(module_audio_id);
> -                     }
> +                     // TODO: Add a way for modules to request speech stop 
> maybe ?
> +//                   if (festival_speaking && module_audio_id) {
> +//                           spd_audio_stop(module_audio_id);
> +//                   }
>                       pthread_mutex_unlock(&sound_output_mutex);
>               }
>       }
> diff --git a/src/modules/generic.c b/src/modules/generic.c
> index 172b6ec..0360f0b 100644
> --- a/src/modules/generic.c
> +++ b/src/modules/generic.c
> @@ -388,8 +388,8 @@ void *_generic_speak(void *nothing)
>                                       homedir =
>                                           g_strdup("UNKNOWN_HOME_DIRECTORY");
>  
> -                             play_command =
> -                                 spd_audio_get_playcmd(module_audio_id);
> +//                           play_command =
> +//                               spd_audio_get_playcmd(module_audio_id);
>                               if (play_command == NULL) {
>                                       DBG("This audio backend has no default 
> play command; using \"play\"\n");
>                                       play_command = "play";
> diff --git a/src/modules/module_main.c b/src/modules/module_main.c
> index f53b053..49b73bc 100644
> --- a/src/modules/module_main.c
> +++ b/src/modules/module_main.c
> @@ -31,7 +31,6 @@
>  #include <pthread.h>
>  #include <glib.h>
>  #include <dotconf.h>
> -#include <ltdl.h>
>  
>  #include <spd_utils.h>
>  #include "module_utils.h"
> @@ -77,10 +76,7 @@ int main(int argc, char *argv[])
>       char *configfilename = NULL;
>       char *status_info = NULL;
>  
> -     /* Initialize ltdl's list of preloaded audio backends. */
> -     LTDL_SET_PRELOADED_SYMBOLS();
>       module_num_dc_options = 0;
> -     module_audio_id = 0;
>  
>       if (argc >= 2) {
>               configfilename = g_strdup(argv[1]);
> @@ -149,6 +145,16 @@ int main(int argc, char *argv[])
>               exit(1);
>       }
>  
> +     ret = module_audio_init(&status_info);
> +     
> +     if (ret != 0) {
> +             printf("399-%s\n", status_info);
> +             printf("%s\n", "399 ERR CANT INIT AUDIO");
> +             g_free(status_info);
> +             module_close();
> +             exit(1);
> +     }
> +
>       printf("299-%s\n", status_info);
>       ret = printf("%s\n", "299 OK LOADED SUCCESSFULLY");
>  
> @@ -190,8 +196,6 @@ int main(int argc, char *argv[])
>                   else
>               PROCESS_CMD(SET, do_set)
>                   else
> -             PROCESS_CMD(AUDIO, do_audio)
> -                 else
>               PROCESS_CMD(LOGLEVEL, do_loglevel)
>                   else
>               PROCESS_CMD_W_ARGS(DEBUG, do_debug)
> diff --git a/src/modules/module_utils.c b/src/modules/module_utils.c
> index 298274a..bde2257 100644
> --- a/src/modules/module_utils.c
> +++ b/src/modules/module_utils.c
> @@ -26,17 +26,22 @@
>  #endif
>  
>  #include <sndfile.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
>  
>  #include <fdsetconv.h>
>  #include <spd_utils.h>
>  #include "module_utils.h"
> -
> -static char *module_audio_pars[10];
> +#include <speechd_defines.h>
>  
>  extern char *module_index_mark;
>  
>  pthread_mutex_t module_stdout_mutex = PTHREAD_MUTEX_INITIALIZER;
>  
> +/* Socket for sending audio data to */
> +int audio_socket;
> +
>  char *do_message(SPDMessageType msgtype)
>  {
>       int ret;
> @@ -95,11 +100,6 @@ char *do_message(SPDMessageType msgtype)
>               msg_settings_old.voice_type = -1;
>       }
>  
> -     /* Volume is controlled by the synthesizer. Always play at normal on 
> audio device. */
> -     if (spd_audio_set_volume(module_audio_id, 85) < 0) {
> -             DBG("Can't set volume. audio not initialized?");
> -     }
> -
>       ret = module_speak(msg->str, strlen(msg->str), msgtype);
>  
>       g_string_free(msg, 1);
> @@ -267,91 +267,12 @@ char *do_set(void)
>       return g_strdup("401 ERROR INTERNAL");  /* Can't be reached */
>  }
>  
> -#define SET_AUDIO_STR(name,idx) \
> -     if(!strcmp(cur_item, #name)){ \
> -             g_free(module_audio_pars[idx]); \
> -             if(!strcmp(cur_value, "NULL")) module_audio_pars[idx] = NULL; \
> -             else module_audio_pars[idx] = g_strdup(cur_value); \
> -     }
> -
> -char *do_audio(void)
> -{
> -     char *cur_item = NULL;
> -     char *cur_value = NULL;
> -     char *line = NULL;
> -     int ret;
> -     size_t n;
> -     int err = 0;            /* Error status */
> -     char *status = NULL;
> -     char *msg;
> -
> -     printf("207 OK RECEIVING AUDIO SETTINGS\n");
> -     fflush(stdout);
> -
> -     while (1) {
> -             line = NULL;
> -             n = 0;
> -             ret = spd_getline(&line, &n, stdin);
> -             if (ret == -1) {
> -                     err = 1;
> -                     break;
> -             }
> -             if (!strcmp(line, ".\n")) {
> -                     g_free(line);
> -                     break;
> -             }
> -             if (!err) {
> -                     cur_item = strtok(line, "=");
> -                     if (cur_item == NULL) {
> -                             err = 1;
> -                             continue;
> -                     }
> -                     cur_value = strtok(NULL, "\n");
> -                     if (cur_value == NULL) {
> -                             err = 1;
> -                             continue;
> -                     }
> -
> -                     SET_AUDIO_STR(audio_output_method, 0)
> -                         else
> -                             SET_AUDIO_STR(audio_oss_device, 1)
> -                                 else
> -                             SET_AUDIO_STR(audio_alsa_device, 2)
> -                                 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
> -                             err = 2;        /* Unknown parameter */
> -             }
> -             g_free(line);
> -     }
> -
> -     if (err == 1)
> -             return g_strdup("302 ERROR BAD SYNTAX");
> -     if (err == 2)
> -             return g_strdup("303 ERROR INVALID PARAMETER OR VALUE");
> -
> -     err = module_audio_init(&status);
> -
> -     if (err == 0)
> -             msg = g_strdup_printf("203 OK AUDIO INITIALIZED");
> -     else
> -             msg = g_strdup_printf("300-%s\n300 UNKNOWN ERROR", status);
> -
> -     g_free(status);
> -     return msg;
> -}
> -
>  #define SET_LOGLEVEL_NUM(name, cond) \
>       if(!strcmp(cur_item, #name)){ \
>               number = strtol(cur_value, &tptr, 10); \
>               if(!(cond)){ err = 2; continue; } \
>               if (tptr == cur_value){ err = 2; continue; } \
>               log_level = number; \
> -             spd_audio_set_loglevel(module_audio_id, number); \
>       }
>  
>  char *do_loglevel(void)
> @@ -516,9 +437,6 @@ void do_quit(void)
>       printf("210 OK QUIT\n");
>       fflush(stdout);
>  
> -     spd_audio_close(module_audio_id);
> -     module_audio_id = NULL;
> -
>       module_close();
>       return;
>  }
> @@ -988,50 +906,74 @@ void *module_get_ht_option(GHashTable * hash_table, 
> const char *key)
>       return option;
>  }
>  
> -int module_audio_init(char **status_info)
> +/* Determine address for the unix socket */
> +static char *_get_default_audio_unix_socket_name(void)
>  {
> -     char *error = 0;
> -     gchar **outputs;
> -     int i = 0;
> +     GString *socket_filename;
> +     char *h;
> +     const char *rundir = g_get_user_runtime_dir();
> +     socket_filename = g_string_new("");
> +     g_string_printf(socket_filename, "%s/speech-dispatcher/audio.sock",
> +                     rundir);
> +     // Do not return glib string, but glibc string...
> +     h = strdup(socket_filename->str);
> +     g_string_free(socket_filename, 1);
> +     return h;
> +}
>  
> -     DBG("Openning audio output system");
> -     if (NULL == module_audio_pars[0]) {
> -             *status_info =
> +int module_audio_init(char **status_info)
> +{
> +     /* Open connection to audio socket */
> +     char *str;
> +     char *socket_filename = _get_default_audio_unix_socket_name();
> +     int len;
> +     struct sockaddr_un server;
> +     
> +     if ((audio_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
> +             *status_info = 
>                   g_strdup
> -                 ("Sound output method specified in configuration not 
> supported. "
> -                  "Please choose 'oss', 'alsa', 'nas', 'libao' or 'pulse'.");
> +                 ("Unable to create socket to send audio data");
>               return -1;
>       }
> -
> -     outputs = g_strsplit(module_audio_pars[0], ",", 0);
> -     while (NULL != outputs[i]) {
> -             module_audio_id =
> -                 spd_audio_open(outputs[i], (void **)&module_audio_pars[1],
> -                                &error);
> -             if (module_audio_id) {
> -                     DBG("Using %s audio output method", outputs[i]);
> -                     g_strfreev(outputs);
> -                     *status_info =
> -                         g_strdup("audio initialized successfully.");
> -                     return 0;
> -             }
> -             i++;
> +     
> +     server.sun_family = AF_UNIX;
> +     strcpy(server.sun_path, socket_filename);
> +     len = strlen(server.sun_path) + sizeof(server.sun_family);
> +     if (connect(audio_socket, (struct sockaddr *)&server, len) == -1) {
> +             *status_info =
> +                 g_strdup_printf
> +                 ("Unable to connect to server socket at %s", 
> socket_filename);
> +             return -1;
>       }
>  
> -     *status_info =
> -         g_strdup_printf("Opening sound device failed. Reason: %s. ", error);
> -     g_free(error);          /* g_malloc'ed, in spd_audio_open. */
> -
> -     g_strfreev(outputs);
> -     return -1;
> +     str = g_strdup("ACK"NEWLINE);
> +     if (send(audio_socket, str, strlen(str), 0) == -1) {
> +             g_free (str);
> +             *status_info =
> +                 g_strdup_printf
> +                 ("Unable to send ACK on audio socket %s", socket_filename);
> +             return -1;
> +     }
> +     g_free(str);
>  
> +     return 0;
>  }
>  
>  int module_tts_output(AudioTrack track, AudioFormat format)
>  {
> -
> -     if (spd_audio_play(module_audio_id, track, format) < 0) {
> -             DBG("Can't play track for unknown reason.");
> +     /* Send audiotrack data to the socket */
> +     char *metadata = g_strdup_printf("%d:%d:%d:%d:%d"NEWLINE,
> +                                      format,
> +                                      track.bits,
> +                                      track.num_channels,
> +                                      track.sample_rate,
> +                                      track.num_samples);
> +     if (send(audio_socket, metadata, strlen(metadata), 0) == -1) {
> +             DBG("Can't send audiotrack metadata for some reason.");
> +             return -1;
> +     }
> +     if (send(audio_socket, track.samples, track.num_samples * sizeof(signed 
> short), 0) == -1) {
> +             DBG("Can't send audio samples for some reason.");
>               return -1;
>       }
>       return 0;
> diff --git a/src/modules/module_utils.h b/src/modules/module_utils.h
> index 7483930..895db80 100644
> --- a/src/modules/module_utils.h
> +++ b/src/modules/module_utils.h
> @@ -41,12 +41,10 @@
>  #include <sys/ipc.h>
>  
>  #include <speechd_types.h>
> -#include "spd_audio.h"
> +#include <spd_audio_plugin.h>
>  
>  int log_level;
>  
> -AudioID *module_audio_id;
> -
>  SPDMsgSettings msg_settings;
>  SPDMsgSettings msg_settings_old;
>  
> diff --git a/src/modules/spd_audio.c b/src/modules/spd_audio.c
> deleted file mode 100644
> index 9bf8e37..0000000
> --- a/src/modules/spd_audio.c
> +++ /dev/null
> @@ -1,321 +0,0 @@
> -
> -/*
> - * spd_audio.c -- Spd Audio Output Library
> - *
> - * Copyright (C) 2004, 2006 Brailcom, o.p.s.
> - *
> - * This is free software; you can redistribute it and/or modify it under the
> - * terms of the GNU Lesser General Public License as published by the Free
> - * Software Foundation; either version 2.1, or (at your option) any later
> - * version.
> - *
> - * This software is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public License
> - * along with this package; see the file COPYING.  If not, write to the Free
> - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> - * 02110-1301, USA.
> - *
> - * $Id: spd_audio.c,v 1.21 2008-06-09 10:29:12 hanke Exp $
> - */
> -
> -/*
> - * spd_audio is a simple realtime audio output library with the capability of
> - * playing 8 or 16 bit data, immediate stop and synchronization. This library
> - * currently provides OSS, NAS, ALSA and PulseAudio backend. The available 
> backends are
> - * specified at compile-time using the directives WITH_OSS, WITH_NAS, 
> WITH_ALSA,
> - * WITH_PULSE, WITH_LIBAO but the user program is allowed to switch between 
> them at run-time.
> - */
> -
> -#ifdef HAVE_CONFIG_H
> -#include <config.h>
> -#endif
> -
> -#include "spd_audio.h"
> -
> -#include <stdio.h>
> -#include <string.h>
> -#include <fcntl.h>
> -#include <sys/ioctl.h>
> -#include <sys/time.h>
> -#include <time.h>
> -#include <unistd.h>
> -#include <errno.h>
> -
> -#include <pthread.h>
> -
> -#include <glib.h>
> -#include <ltdl.h>
> -
> -static int spd_audio_log_level;
> -static lt_dlhandle lt_h;
> -
> -/* Dynamically load a library with RTLD_GLOBAL set.
> -
> -   This is needed when a dynamically-loaded library has its own plugins
> -   that call into the parent library.
> -   Most of the credit for this function goes to Gary Vaughan.
> -*/
> -static lt_dlhandle my_dlopenextglobal(const char *filename)
> -{
> -     lt_dlhandle handle = NULL;
> -     lt_dladvise advise;
> -
> -     if (lt_dladvise_init(&advise))
> -             return handle;
> -
> -     if (!lt_dladvise_ext(&advise) && !lt_dladvise_global(&advise))
> -             handle = lt_dlopenadvise(filename, advise);
> -
> -     lt_dladvise_destroy(&advise);
> -     return handle;
> -}
> -
> -/* Open the audio device.
> -
> -   Arguments:
> -   type -- The requested device. Currently AudioOSS or AudioNAS.
> -   pars -- and array of pointers to parameters to pass to
> -           the device backend, terminated by a NULL pointer.
> -           See the source/documentation of each specific backend.
> -   error -- a pointer to the string where error description is
> -           stored in case of failure (returned AudioID == NULL).
> -           Otherwise will contain NULL.
> -
> -   Return value:
> -   Newly allocated AudioID structure that can be passed to
> -   all other spd_audio functions, or NULL in case of failure.
> -
> -*/
> -AudioID *spd_audio_open(char *name, void **pars, char **error)
> -{
> -     AudioID *id;
> -     spd_audio_plugin_t const *p;
> -     spd_audio_plugin_t *(*fn) (void);
> -     gchar *libname;
> -     int ret;
> -
> -     /* now check whether dynamic plugin is available */
> -     ret = lt_dlinit();
> -     if (ret != 0) {
> -             *error = (char *)g_strdup_printf("lt_dlinit() failed");
> -             return (AudioID *) NULL;
> -     }
> -
> -     ret = lt_dlsetsearchpath(PLUGIN_DIR);
> -     if (ret != 0) {
> -             *error = (char *)g_strdup_printf("lt_dlsetsearchpath() failed");
> -             return (AudioID *) NULL;
> -     }
> -
> -     libname = g_strdup_printf(SPD_AUDIO_LIB_PREFIX "%s", name);
> -     lt_h = my_dlopenextglobal(libname);
> -     g_free(libname);
> -     if (NULL == lt_h) {
> -             *error =
> -                 (char *)g_strdup_printf("Cannot open plugin %s. error: %s",
> -                                         name, lt_dlerror());
> -             return (AudioID *) NULL;
> -     }
> -
> -     fn = lt_dlsym(lt_h, SPD_AUDIO_PLUGIN_ENTRY_STR);
> -     if (NULL == fn) {
> -             *error = (char *)g_strdup_printf("Cannot find symbol %s",
> -                                              SPD_AUDIO_PLUGIN_ENTRY_STR);
> -             return (AudioID *) NULL;
> -     }
> -
> -     p = fn();
> -     if (p == NULL || p->name == NULL) {
> -             *error = (char *)g_strdup_printf("plugin %s not found", name);
> -             return (AudioID *) NULL;
> -     }
> -
> -     id = p->open(pars);
> -     if (id == NULL) {
> -             *error =
> -                 (char *)g_strdup_printf("Couldn't open %s plugin", name);
> -             return (AudioID *) NULL;
> -     }
> -
> -     id->function = p;
> -#if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
> -     id->format = SPD_AUDIO_BE;
> -#else
> -     id->format = SPD_AUDIO_LE;
> -#endif
> -
> -     *error = NULL;
> -
> -     return id;
> -}
> -
> -/* Play a track on the audio device (blocking).
> -
> -   Arguments:
> -   id -- the AudioID* of the device returned by spd_audio_open
> -   track -- a track to play (see spd_audio.h)
> -
> -   Return value:
> -   0 if everything is ok, a non-zero value in case of failure.
> -   See the particular backend documentation or source for the
> -   meaning of these non-zero values.
> -
> -   Comment:
> -   spd_audio_play() is a blocking function. It returns exactly
> -   when the given track stopped playing. However, it's possible
> -   to safely interrupt it using spd_audio_stop() described below.
> -   (spd_audio_stop() needs to be called from another thread, obviously.)
> -
> -*/
> -int spd_audio_play(AudioID * id, AudioTrack track, AudioFormat format)
> -{
> -     int ret;
> -
> -     if (id && id->function->play) {
> -             /* Only perform byte swapping if the driver in use has given us 
> audio in
> -                an endian format other than what the running CPU supports. */
> -             if (format != id->format) {
> -                     unsigned char *out_ptr, *out_end, c;
> -                     out_ptr = (unsigned char *)track.samples;
> -                     out_end =
> -                         out_ptr +
> -                         track.num_samples * 2 * track.num_channels;
> -                     while (out_ptr < out_end) {
> -                             c = out_ptr[0];
> -                             out_ptr[0] = out_ptr[1];
> -                             out_ptr[1] = c;
> -                             out_ptr += 2;
> -                     }
> -             }
> -             ret = id->function->play(id, track);
> -     } else {
> -             fprintf(stderr, "Play not supported on this device\n");
> -             return -1;
> -     }
> -
> -     return ret;
> -}
> -
> -/* Stop playing the current track on device id
> -
> -Arguments:
> -   id -- the AudioID* of the device returned by spd_audio_open
> -
> -Return value:
> -   0 if everything is ok, a non-zero value in case of failure.
> -   See the particular backend documentation or source for the
> -   meaning of these non-zero values.
> -
> -Comment:
> -   spd_audio_stop() safely interrupts spd_audio_play() when called
> -   from another thread. It shouldn't cause any clicks or unwanted
> -   effects in the sound output.
> -
> -   It's safe to call spd_audio_stop() even if the device isn't playing
> -   any track. In that case, it does nothing. However, there is a danger
> -   when using spd_audio_stop(). Since you must obviously do it from
> -   another thread than where spd_audio_play is running, you must make
> -   yourself sure that the device is still open and the id you pass it
> -   is valid and will be valid until spd_audio_stop returns. In other words,
> -   you should use some mutex or other synchronization device to be sure
> -   spd_audio_close isn't called before or during spd_audio_stop execution.
> -*/
> -
> -int spd_audio_stop(AudioID * id)
> -{
> -     int ret;
> -     if (id && id->function->stop) {
> -             ret = id->function->stop(id);
> -     } else {
> -             fprintf(stderr, "Stop not supported on this device\n");
> -             return -1;
> -     }
> -     return ret;
> -}
> -
> -/* Close the audio device id
> -
> -Arguments:
> -   id -- the AudioID* of the device returned by spd_audio_open
> -
> -Return value:
> -   0 if everything is ok, a non-zero value in case of failure.
> -
> -Comments:
> -
> -   Please make sure no other spd_audio function with this device id
> -   is running in another threads. See spd_audio_stop() for detailed
> -   description of possible problems.
> -*/
> -int spd_audio_close(AudioID * id)
> -{
> -     int ret = 0;
> -     if (id && id->function->close) {
> -             ret = (id->function->close(id));
> -     }
> -
> -     if (NULL != lt_h) {
> -             lt_dlclose(lt_h);
> -             lt_h = NULL;
> -             lt_dlexit();
> -     }
> -
> -     return ret;
> -}
> -
> -/* Set volume for playing tracks on the device id
> -
> -Arguments:
> -   id -- the AudioID* of the device returned by spd_audio_open
> -   volume -- a value in the range <-100:100> where -100 means the
> -             least volume (probably silence), 0 the default volume
> -          and +100 the highest volume possible to make on that
> -          device for a single flow (i.e. not using mixer).
> -
> -Return value:
> -   0 if everything is ok, a non-zero value in case of failure.
> -   See the particular backend documentation or source for the
> -   meaning of these non-zero values.
> -
> -Comments:
> -
> -   In case of /dev/dsp, it's not possible to set volume for
> -   the particular flow. For that reason, the value 0 means
> -   the volume the track was recorded on and each smaller value
> -   means less volume (since this works by deviding the samples
> -   in the track by a constant).
> -*/
> -int spd_audio_set_volume(AudioID * id, int volume)
> -{
> -     if ((volume > 100) || (volume < -100)) {
> -             fprintf(stderr, "Requested volume out of range");
> -             return -1;
> -     }
> -     if (id == NULL) {
> -             fprintf(stderr, "audio id is NULL in spd_audio_set_volume\n");
> -             return -1;
> -     }
> -     id->volume = volume;
> -     return 0;
> -}
> -
> -void spd_audio_set_loglevel(AudioID * id, int level)
> -{
> -     if (level) {
> -             spd_audio_log_level = level;
> -             if (id != 0 && id->function != 0)
> -                     id->function->set_loglevel(level);
> -     }
> -}
> -
> -char const *spd_audio_get_playcmd(AudioID * id)
> -{
> -     if (id != 0 && id->function != 0) {
> -             return id->function->get_playcmd();
> -     }
> -     return NULL;
> -}
> diff --git a/src/modules/spd_audio.h b/src/modules/spd_audio.h
> deleted file mode 100644
> index f9452e8..0000000
> --- a/src/modules/spd_audio.h
> +++ /dev/null
> @@ -1,46 +0,0 @@
> -
> -/*
> - * spd_audio.h -- The SPD Audio Library Header
> - *
> - * Copyright (C) 2004 Brailcom, o.p.s.
> - *
> - * This is free software; you can redistribute it and/or modify it under the
> - * terms of the GNU Lesser General Public License as published by the Free
> - * Software Foundation; either version 2.1, or (at your option) any later
> - * version.
> - *
> - * This software is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public License
> - * along with this package; see the file COPYING.  If not, write to the Free
> - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> - * 02110-1301, USA.
> - *
> - * $Id: spd_audio.h,v 1.21 2008-10-15 17:28:17 hanke Exp $
> - */
> -
> -#ifndef __SPD_AUDIO_H
> -#define __SPD_AUDIO_H
> -
> -#include <spd_audio_plugin.h>
> -
> -#define SPD_AUDIO_LIB_PREFIX "spd_"
> -
> -AudioID *spd_audio_open(char *name, void **pars, char **error);
> -
> -int spd_audio_play(AudioID * id, AudioTrack track, AudioFormat format);
> -
> -int spd_audio_stop(AudioID * id);
> -
> -int spd_audio_close(AudioID * id);
> -
> -int spd_audio_set_volume(AudioID * id, int volume);
> -
> -void spd_audio_set_loglevel(AudioID * id, int level);
> -
> -char const *spd_audio_get_playcmd(AudioID * id);
> -
> -#endif /* ifndef #__SPD_AUDIO_H */
> diff --git a/src/server/Makefile.am b/src/server/Makefile.am
> index 607cf8e..bad5a61 100644
> --- a/src/server/Makefile.am
> +++ b/src/server/Makefile.am
> @@ -9,12 +9,14 @@ speech_dispatcher_SOURCES = speechd.c speechd.h server.c 
> server.h \
>       parse.c parse.h set.c set.h msg.h alloc.c alloc.h \
>       compare.c compare.h speaking.c speaking.h options.c options.h \
>       output.c output.h sem_functions.c sem_functions.h \
> -     index_marking.c index_marking.h
> +     index_marking.c index_marking.h audio.c audio.h
>  speech_dispatcher_CFLAGS = $(ERROR_CFLAGS)
>  speech_dispatcher_CPPFLAGS = $(inc_local) $(DOTCONF_CFLAGS) $(GLIB_CFLAGS) \
>       $(GMODULE_CFLAGS) $(GTHREAD_CFLAGS) -DSYS_CONF=\"$(spdconfdir)\" \
>       -DSND_DATA=\"$(snddatadir)\" -DMODULEBINDIR=\"$(modulebindir)\" \
> -     -D_GNU_SOURCE -DDEFAULT_AUDIO_METHOD=\"$(default_audio_method)\"
> +     -D_GNU_SOURCE -DDEFAULT_AUDIO_METHOD=\"$(default_audio_method)\" \
> +     -DPLUGIN_DIR=\"$(audiodir)\"
>  speech_dispatcher_LDFLAGS = $(RDYNAMIC)
>  speech_dispatcher_LDADD = $(lib_common) $(DOTCONF_LIBS) $(GLIB_LIBS) \
> -     $(GMODULE_LIBS) $(GTHREAD_LIBS) $(EXTRA_SOCKET_LIBS)
> +     $(GMODULE_LIBS) $(GTHREAD_LIBS) $(EXTRA_SOCKET_LIBS) \
> +     $(audio_dlopen_modules)
> diff --git a/src/server/audio.c b/src/server/audio.c
> new file mode 100644
> index 0000000..08a6567
> --- /dev/null
> +++ b/src/server/audio.c
> @@ -0,0 +1,647 @@
> +
> +/*
> + * spd_audio.c -- Spd Audio Output Library
> + *
> + * Copyright (C) 2004, 2006 Brailcom, o.p.s.
> + *
> + * This is free software; you can redistribute it and/or modify it under the
> + * terms of the GNU Lesser General Public License as published by the Free
> + * Software Foundation; either version 2.1, or (at your option) any later
> + * version.
> + *
> + * This software is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this package; see the file COPYING.  If not, write to the Free
> + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> + * 02110-1301, USA.
> + *
> + * $Id: spd_audio.c,v 1.21 2008-06-09 10:29:12 hanke Exp $
> + */
> +
> +/*
> + * spd_audio is a simple realtime audio output library with the capability of
> + * playing 8 or 16 bit data, immediate stop and synchronization. This library
> + * currently provides OSS, NAS, ALSA and PulseAudio backend. The available 
> backends are
> + * specified at compile-time using the directives WITH_OSS, WITH_NAS, 
> WITH_ALSA,
> + * WITH_PULSE, WITH_LIBAO but the user program is allowed to switch between 
> them at run-time.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include "audio.h"
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <sys/ioctl.h>
> +#include <sys/time.h>
> +#include <time.h>
> +#include <unistd.h>
> +#include <errno.h>
> +
> +#include <pthread.h>
> +
> +#include <glib.h>
> +#include <glib/gstdio.h>
> +#include <ltdl.h>
> +
> +#include "speechd.h"
> +#include "speechd_defines.h"
> +#include "set.h"
> +
> +static int spd_audio_log_level;
> +static lt_dlhandle lt_h;
> +
> +/* Server audio socket file descriptor */
> +int audio_server_socket;
> +
> +AudioID *audio_id;
> +static char *audio_pars[10]; /* Audio module parameters */
> +
> +static pthread_t audio_thread;
> +static sem_t audio_play_semaphore;
> +
> +static gboolean audio_close_requested = FALSE;
> +
> +/* Dynamically load a library with RTLD_GLOBAL set.
> +
> +   This is needed when a dynamically-loaded library has its own plugins
> +   that call into the parent library.
> +   Most of the credit for this function goes to Gary Vaughan.
> +*/
> +static lt_dlhandle my_dlopenextglobal(const char *filename)
> +{
> +     lt_dlhandle handle = NULL;
> +     lt_dladvise advise;
> +
> +     if (lt_dladvise_init(&advise))
> +             return handle;
> +
> +     if (!lt_dladvise_ext(&advise) && !lt_dladvise_global(&advise))
> +             handle = lt_dlopenadvise(filename, advise);
> +
> +     lt_dladvise_destroy(&advise);
> +     return handle;
> +}
> +
> +/* Open the audio device.
> +
> +   Arguments:
> +   type -- The requested device. Currently AudioOSS or AudioNAS.
> +   pars -- and array of pointers to parameters to pass to
> +           the device backend, terminated by a NULL pointer.
> +           See the source/documentation of each specific backend.
> +   error -- a pointer to the string where error description is
> +           stored in case of failure (returned AudioID == NULL).
> +           Otherwise will contain NULL.
> +
> +   Return value:
> +   Newly allocated AudioID structure that can be passed to
> +   all other spd_audio functions, or NULL in case of failure.
> +
> +*/
> +AudioID *spd_audio_open(char *name, void **pars, char **error)
> +{
> +     MSG(5, "spd_audio_open called with name %s", name);
> +     AudioID *id;
> +     spd_audio_plugin_t const *p;
> +     spd_audio_plugin_t *(*fn) (void);
> +     gchar *libname;
> +     int ret;
> +
> +     /* now check whether dynamic plugin is available */
> +     ret = lt_dlinit();
> +     if (ret != 0) {
> +             *error = (char *)g_strdup_printf("lt_dlinit() failed");
> +             return (AudioID *) NULL;
> +     }
> +
> +     ret = lt_dlsetsearchpath(PLUGIN_DIR);
> +     if (ret != 0) {
> +             *error = (char *)g_strdup_printf("lt_dlsetsearchpath() failed");
> +             return (AudioID *) NULL;
> +     }
> +
> +     libname = g_strdup_printf(SPD_AUDIO_LIB_PREFIX "%s", name);
> +     lt_h = my_dlopenextglobal(libname);
> +     g_free(libname);
> +     if (NULL == lt_h) {
> +             *error =
> +                 (char *)g_strdup_printf("Cannot open plugin %s. error: %s",
> +                                         name, lt_dlerror());
> +             return (AudioID *) NULL;
> +     }
> +
> +     fn = lt_dlsym(lt_h, SPD_AUDIO_PLUGIN_ENTRY_STR);
> +     if (NULL == fn) {
> +             *error = (char *)g_strdup_printf("Cannot find symbol %s",
> +                                              SPD_AUDIO_PLUGIN_ENTRY_STR);
> +             return (AudioID *) NULL;
> +     }
> +
> +     MSG(5, "calling init function");
> +     p = fn();
> +     if (p == NULL || p->name == NULL) {
> +             *error = (char *)g_strdup_printf("plugin %s not found", name);
> +             return (AudioID *) NULL;
> +     }
> +
> +     MSG(5, "calling open function");
> +     id = p->open(pars);
> +     if (id == NULL) {
> +             *error =
> +                 (char *)g_strdup_printf("Couldn't open %s plugin", name);
> +             return (AudioID *) NULL;
> +     }
> +
> +     id->function = p;
> +#if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
> +     id->format = SPD_AUDIO_BE;
> +#else
> +     id->format = SPD_AUDIO_LE;
> +#endif
> +
> +     *error = NULL;
> +
> +     return id;
> +}
> +
> +/* Play a track on the audio device (blocking).
> +
> +   Arguments:
> +   id -- the AudioID* of the device returned by spd_audio_open
> +   track -- a track to play (see spd_audio.h)
> +
> +   Return value:
> +   0 if everything is ok, a non-zero value in case of failure.
> +   See the particular backend documentation or source for the
> +   meaning of these non-zero values.
> +
> +   Comment:
> +   spd_audio_play() is a blocking function. It returns exactly
> +   when the given track stopped playing. However, it's possible
> +   to safely interrupt it using spd_audio_stop() described below.
> +   (spd_audio_stop() needs to be called from another thread, obviously.)
> +
> +*/
> +int spd_audio_play(AudioID * id, AudioTrack track, AudioFormat format)
> +{
> +     int ret;
> +
> +     if (id && id->function->play) {
> +             /* Only perform byte swapping if the driver in use has given us 
> audio in
> +                an endian format other than what the running CPU supports. */
> +             if (format != id->format) {
> +                     unsigned char *out_ptr, *out_end, c;
> +                     out_ptr = (unsigned char *)track.samples;
> +                     out_end =
> +                         out_ptr +
> +                         track.num_samples * 2 * track.num_channels;
> +                     while (out_ptr < out_end) {
> +                             c = out_ptr[0];
> +                             out_ptr[0] = out_ptr[1];
> +                             out_ptr[1] = c;
> +                             out_ptr += 2;
> +                     }
> +             }
> +             MSG(5, "playing audio on audio_id %d", id);
> +             ret = id->function->play(id, track);
> +     } else {
> +             fprintf(stderr, "Play not supported on this device\n");
> +             return -1;
> +     }
> +
> +     return ret;
> +}
> +
> +/* Stop playing the current track on device id
> +
> +Arguments:
> +   id -- the AudioID* of the device returned by spd_audio_open
> +
> +Return value:
> +   0 if everything is ok, a non-zero value in case of failure.
> +   See the particular backend documentation or source for the
> +   meaning of these non-zero values.
> +
> +Comment:
> +   spd_audio_stop() safely interrupts spd_audio_play() when called
> +   from another thread. It shouldn't cause any clicks or unwanted
> +   effects in the sound output.
> +
> +   It's safe to call spd_audio_stop() even if the device isn't playing
> +   any track. In that case, it does nothing. However, there is a danger
> +   when using spd_audio_stop(). Since you must obviously do it from
> +   another thread than where spd_audio_play is running, you must make
> +   yourself sure that the device is still open and the id you pass it
> +   is valid and will be valid until spd_audio_stop returns. In other words,
> +   you should use some mutex or other synchronization device to be sure
> +   spd_audio_close isn't called before or during spd_audio_stop execution.
> +*/
> +
> +int spd_audio_stop(AudioID * id)
> +{
> +     int ret;
> +     if (id && id->function->stop) {
> +             ret = id->function->stop(id);
> +     } else {
> +             fprintf(stderr, "Stop not supported on this device\n");
> +             return -1;
> +     }
> +     return ret;
> +}
> +
> +/* Close the audio device id
> +
> +Arguments:
> +   id -- the AudioID* of the device returned by spd_audio_open
> +
> +Return value:
> +   0 if everything is ok, a non-zero value in case of failure.
> +
> +Comments:
> +
> +   Please make sure no other spd_audio function with this device id
> +   is running in another threads. See spd_audio_stop() for detailed
> +   description of possible problems.
> +*/
> +int spd_audio_close(AudioID * id)
> +{
> +     int ret = 0;
> +     if (id && id->function->close) {
> +             ret = (id->function->close(id));
> +     }
> +
> +     if (NULL != lt_h) {
> +             lt_dlclose(lt_h);
> +             lt_h = NULL;
> +             lt_dlexit();
> +     }
> +
> +     return ret;
> +}
> +
> +/* Set volume for playing tracks on the device id
> +
> +Arguments:
> +   id -- the AudioID* of the device returned by spd_audio_open
> +   volume -- a value in the range <-100:100> where -100 means the
> +             least volume (probably silence), 0 the default volume
> +          and +100 the highest volume possible to make on that
> +          device for a single flow (i.e. not using mixer).
> +
> +Return value:
> +   0 if everything is ok, a non-zero value in case of failure.
> +   See the particular backend documentation or source for the
> +   meaning of these non-zero values.
> +
> +Comments:
> +
> +   In case of /dev/dsp, it's not possible to set volume for
> +   the particular flow. For that reason, the value 0 means
> +   the volume the track was recorded on and each smaller value
> +   means less volume (since this works by deviding the samples
> +   in the track by a constant).
> +*/
> +int spd_audio_set_volume(AudioID * id, int volume)
> +{
> +     if ((volume > 100) || (volume < -100)) {
> +             fprintf(stderr, "Requested volume out of range");
> +             return -1;
> +     }
> +     if (id == NULL) {
> +             fprintf(stderr, "audio id is NULL in spd_audio_set_volume\n");
> +             return -1;
> +     }
> +     id->volume = volume;
> +     return 0;
> +}
> +
> +void spd_audio_set_loglevel(AudioID * id, int level)
> +{
> +     if (level) {
> +             spd_audio_log_level = level;
> +             if (id != 0 && id->function != 0)
> +                     id->function->set_loglevel(level);
> +     }
> +}
> +
> +char const *spd_audio_get_playcmd(AudioID * id)
> +{
> +     if (id != 0 && id->function != 0) {
> +             return id->function->get_playcmd();
> +     }
> +     return NULL;
> +}
> +
> +void speechd_audio_socket_init(void)
> +{
> +     /* For now use unix socket for audio. Maybe later we can add inet 
> socket support */
> +        GString *audio_socket_filename;
> +        audio_socket_filename = g_string_new("");
> +        if (SpeechdOptions.runtime_speechd_dir) {
> +                g_string_printf(audio_socket_filename, "%s/audio.sock",
> +                                SpeechdOptions.runtime_speechd_dir);
> +        } else {
> +            FATAL
> +                ("Socket name file not set and user has no runtime 
> directory");
> +        }
> +        g_free(SpeechdOptions.audio_socket_path);
> +        SpeechdOptions.audio_socket_path = 
> g_strdup(audio_socket_filename->str);
> +        g_string_free(audio_socket_filename, 1);
> +
> +     MSG(1, "Creating audio socket at %s", SpeechdOptions.audio_socket_path);
> +
> +     /* Audio data is only using unix sockets for now, possibly adapt to use 
> +      * inet sockets also later? */
> +     if (g_file_test(SpeechdOptions.audio_socket_path, G_FILE_TEST_EXISTS))
> +             if (g_unlink(SpeechdOptions.audio_socket_path) == -1)
> +                     FATAL
> +                         ("Local socket file for audio exists but impossible 
> to delete. Wrong permissions?");
> +     /* Connect and start listening on local unix socket */
> +     audio_server_socket = 
> make_local_socket(SpeechdOptions.audio_socket_path);
> +}
> +
> +/* play the audio data on _fd_ if we got some activity. */
> +int play_audio(int fd)
> +{
> +     size_t bytes = 0;       /* Number of bytes we got */
> +     int buflen = BUF_SIZE;
> +     char *buf = (char *)g_malloc(buflen + 1);
> +     AudioTrack track;
> +     AudioFormat format;
> +     gchar ** metadata;
> +     int bytes_read;
> +
> +     /* Read data from socket */
> +     /* Read exactly one complete line, the `parse' routine relies on it */
> +     {
> +             while (1) {
> +                     int n = read(fd, buf + bytes, 1);
> +                     if (n <= 0) {
> +                             MSG(5, "ERROR: Read 0 bytes from fd");
> +                             g_free(buf);
> +                             return -1;
> +                     }
> +                     /* Note, bytes is a 0-based index into buf. */
> +                     if ((buf[bytes] == '\n')
> +                         && (bytes >= 1) && (buf[bytes - 1] == '\r')) {
> +                             buf[++bytes] = '\0';
> +                             break;
> +                     }
> +                     if (buf[bytes] == '\0')
> +                             buf[bytes] = '?';
> +                     if ((++bytes) == buflen) {
> +                             buflen *= 2;
> +                             buf = g_realloc(buf, buflen + 1);
> +                     }
> +             }
> +     }
> +
> +     /* Parse the data and read the reply */
> +     MSG2(5, "protocol", "%d:DATA:|%s| (%d)", fd, buf, bytes);
> +     if (strcmp(buf, "ACK"NEWLINE) == 0) {
> +             g_free(buf);
> +             return 0;
> +     }
> +     /* parse the AudioTrack information from buf */
> +     metadata = g_strsplit(buf, ":", 5);
> +     if (metadata == NULL || metadata[0] == NULL
> +         || metadata[1] == NULL || metadata[2] == NULL
> +         || metadata[3] == NULL || metadata[4] == NULL) {
> +             MSG(5, "Error: Unable to read Audiotrack metadata!");
> +             return -1;
> +     }
> +     format = strtol(metadata[0], NULL, 10);
> +     track.bits = strtol(metadata[1], NULL, 10);
> +     track.num_channels = strtol(metadata[2], NULL, 10);
> +     track.sample_rate = strtol(metadata[3], NULL, 10);
> +     track.num_samples = strtol(metadata[4], NULL, 10);
> +     
> +     MSG(5, "Track num samples is %d", track.num_samples);
> +     
> +     if (track.num_samples <= 0) {
> +             MSG(5, "Error: num_samples is invalid");
> +             return -1;
> +     }
> +     /* then free buf  */
> +     g_free(buf);
> +     /* Get the rest of the data */
> +     track.samples = g_malloc0_n(track.num_samples, sizeof(signed short));
> +     bytes_read = read(fd, track.samples, track.num_samples * sizeof(signed 
> short));
> +     
> +     if (bytes_read != track.num_samples * sizeof(signed short)) {
> +             MSG(5, "Error: num_samples %d doesn't match bytes read %d", 
> track.num_samples, bytes_read);
> +             return -1;
> +     }
> +     
> +     MSG(5, "Going to play audio on audio with id %d", audio_id);
> +     
> +     /* And play the AudioTrack */
> +     if (spd_audio_play(audio_id, track, format) < 0) {
> +             MSG(5, "Error: unable to play audio");
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +static gboolean audio_socket_process_incoming (gint          fd,
> +                                     GIOCondition  condition,
> +                                     gpointer      data)
> +{
> +     int ret;
> +     ret = speechd_audio_connection_new(fd);
> +     if (ret != 0) {
> +             MSG(2, "Error: Failed to add new module audio!");
> +             if (SPEECHD_DEBUG) {
> +                     FATAL("Failed to add new module audio!");
> +             }
> +     }
> +     
> +     return TRUE;
> +}
> +
> +static gboolean audio_process_incoming (gint           fd,
> +                              GIOCondition   condition,
> +                              gpointer       data)
> +{
> +     MSG(5, "audio_process_incoming called for fd %d", fd);
> +     int nread;
> +
> +     ioctl(fd, FIONREAD, &nread);
> +
> +     if (nread == 0) {
> +             /* module has gone */
> +             MSG(2, "Info: Module has gone.");
> +             return FALSE;
> +     }
> +     
> +     MSG(5, "read %d bytes from fd %d", nread, fd);
> +
> +     /* client sends some commands or data */
> +     if (play_audio(fd) == -1) {
> +             MSG(2, "Error: Failed to serve client on fd %d!", fd);
> +     }
> +
> +     return TRUE;
> +}
> +
> +/* Playback thread. */
> +static void *_speechd_play(void *nothing)
> +{
> +     char *error = 0;
> +     gchar **outputs;
> +     int i = 0;
> +     gboolean found_audio_module = FALSE;
> +
> +     MSG(1, "Playback thread starting.......");
> +
> +     /* TODO: Use real values from config rather than these hard coded test 
> values */
> +     if (GlobalFDSet.audio_oss_device != NULL)
> +             audio_pars[1] = g_strdup(GlobalFDSet.audio_oss_device);
> +     else
> +             audio_pars[1] = NULL;
> +     
> +     if (GlobalFDSet.audio_alsa_device != NULL)
> +             audio_pars[2] = g_strdup(GlobalFDSet.audio_alsa_device);
> +     else
> +             audio_pars[2] = NULL;
> +     
> +
> +     if (GlobalFDSet.audio_nas_server != NULL)
> +             audio_pars[3] = g_strdup(GlobalFDSet.audio_nas_server);
> +     else
> +             audio_pars[3] = NULL;
> +     
> +     if (GlobalFDSet.audio_pulse_server != NULL)
> +             audio_pars[4] = g_strdup(GlobalFDSet.audio_pulse_server);
> +     else
> +             audio_pars[4] = NULL;
> +     
> +     if (GlobalFDSet.audio_pulse_min_length != NULL)
> +             audio_pars[5] = g_strdup_printf("%d", 
> GlobalFDSet.audio_pulse_min_length);
> +     else
> +             audio_pars[5] = NULL;
> +
> +     MSG(1, "Openning audio output system");
> +     if (GlobalFDSet.audio_output_method == NULL) {
> +             MSG(1, "Sound output method specified in configuration not 
> supported. "
> +                  "Please choose 'oss', 'alsa', 'nas', 'libao' or 'pulse'.");
> +             return 0;
> +     }
> +
> +     outputs = g_strsplit(GlobalFDSet.audio_output_method, ",", 0);
> +     while (NULL != outputs[i]) {
> +             audio_id =
> +                 spd_audio_open(outputs[i], (void **)&audio_pars[1],
> +                                &error);
> +             if (audio_id) {
> +                     spd_audio_set_loglevel(audio_id, 
> SpeechdOptions.log_level);
> +                     MSG(5, "Using %s audio output method with log level 
> %d", outputs[i], SpeechdOptions.log_level);
> +
> +                     /* Volume is controlled by the synthesizer. Always play 
> at normal on audio device. */
> +                     if (spd_audio_set_volume(audio_id, 85) < 0) {
> +                             MSG(2, "Can't set volume. audio not 
> initialized?");
> +                     }
> +
> +                     g_strfreev(outputs);
> +                     MSG(5, "audio initialized successfully.");
> +                     found_audio_module = TRUE;
> +                     break;
> +             }
> +             i++;
> +     }
> +
> +     if (!found_audio_module) {
> +         MSG(1, "Opening sound device failed. Reason: %s. ", error);
> +         g_free(error);              /* g_malloc'ed, in spd_audio_open. */
> +     }
> +
> +     /* Connect to the server socket */
> +     g_unix_fd_add(audio_server_socket, G_IO_IN,
> +                   audio_socket_process_incoming, NULL);
> +
> +     /* Block all signals to this thread. */
> +//   set_speaking_thread_parameters();
> +
> +     while (!audio_close_requested) {
> +             /* If semaphore not set, set suspended lock and suspend until 
> it is signaled. */
> +             if (0 != sem_trywait(&audio_play_semaphore)) {
> +                     sem_wait(&audio_play_semaphore);
> +             }
> +             MSG(5, "Playback semaphore on.");
> +             if (audio_close_requested)
> +                     break;
> +     }
> +
> +     MSG(1, "Playback thread ended.......");
> +     return 0;
> +}
> +
> +void speechd_audio_init()
> +{
> +     int ret = 0;
> +
> +     audio_id = 0;
> +     sem_init(&audio_play_semaphore, 0, 0);
> +
> +     ret = pthread_create(&audio_thread, NULL, _speechd_play, NULL);
> +     if (ret != 0)
> +             FATAL("Audio thread failed!\n");
> +}
> +
> +/* activity is on audio_server_socket (request for a new connection) */
> +int speechd_audio_connection_new(int audio_server_socket)
> +{
> +     MSG(5, "Adding audio connection on socket %d", audio_server_socket);
> +     TAudioFDSetElement *new_fd_set;
> +     struct sockaddr_in module_address;
> +     unsigned int module_len = sizeof(module_address);
> +     int module_socket;
> +
> +     module_socket =
> +         accept(audio_server_socket, (struct sockaddr *)&module_address,
> +                &module_len);
> +
> +     if (module_socket == -1) {
> +             MSG(2,
> +                 "Error: Can't handle connection request of a module for 
> audio");
> +             return -1;
> +     }
> +
> +     /* We add the associated client_socket to the descriptor set. */
> +     if (module_socket > SpeechdStatus.max_fd)
> +             SpeechdStatus.max_fd = module_socket;
> +     MSG(4, "Adding module on fd %d", module_socket);
> +
> +     /* Create a record in fd_settings */
> +     new_fd_set = (TAudioFDSetElement *) default_audio_fd_set();
> +     if (new_fd_set == NULL) {
> +             MSG(2,
> +                 "Error: Failed to create a record in fd_settings for the 
> module for audio");
> +             if (SpeechdStatus.max_fd == module_socket)
> +                     SpeechdStatus.max_fd--;
> +             return -1;
> +     }
> +     new_fd_set->fd = module_socket;
> +     new_fd_set->fd_source = g_unix_fd_add(module_socket, G_IO_IN, 
> audio_process_incoming, NULL);
> +
> +     return 0;
> +}
> +
> +void speechd_audio_cleanup(void)
> +{
> +     if (close(audio_server_socket) == -1)
> +             MSG(2, "close() audio server socket failed: %s", 
> strerror(errno));
> +
> +     MSG(2, "Closing audio output...");
> +     spd_audio_close(audio_id);
> +     audio_id = NULL;
> +}
> diff --git a/src/server/audio.h b/src/server/audio.h
> new file mode 100644
> index 0000000..d371c50
> --- /dev/null
> +++ b/src/server/audio.h
> @@ -0,0 +1,60 @@
> +
> +/*
> + * spd_audio.h -- The SPD Audio Library Header
> + *
> + * Copyright (C) 2004 Brailcom, o.p.s.
> + *
> + * This is free software; you can redistribute it and/or modify it under the
> + * terms of the GNU Lesser General Public License as published by the Free
> + * Software Foundation; either version 2.1, or (at your option) any later
> + * version.
> + *
> + * This software is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this package; see the file COPYING.  If not, write to the Free
> + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> + * 02110-1301, USA.
> + *
> + * $Id: spd_audio.h,v 1.21 2008-10-15 17:28:17 hanke Exp $
> + */
> +
> +#ifndef __SPD_AUDIO_H
> +#define __SPD_AUDIO_H
> +
> +#include <spd_audio_plugin.h>
> +
> +#define SPD_AUDIO_LIB_PREFIX "spd_"
> +
> +AudioID *spd_audio_open(char *name, void **pars, char **error);
> +
> +int spd_audio_play(AudioID * id, AudioTrack track, AudioFormat format);
> +
> +int spd_audio_stop(AudioID * id);
> +
> +int spd_audio_close(AudioID * id);
> +
> +int spd_audio_set_volume(AudioID * id, int volume);
> +
> +void spd_audio_set_loglevel(AudioID * id, int level);
> +
> +char const *spd_audio_get_playcmd(AudioID * id);
> +
> +/* Speech dispatcher server functions */
> +
> +/* speechd_play_audio() reads audio data and plays it */
> +int speechd_play_audio(int fd);
> +
> +int speechd_audio_connection_new(int audio_socket);
> +/* Initialize the audio socket */
> +void speechd_audio_socket_init(void);
> +/* Initialize the audio backend based on user's settings in a new thread */
> +void speechd_audio_init(void);
> +
> +/* Clean up audio socket and module */
> +void speechd_audio_cleanup(void);
> +
> +#endif /* ifndef #__SPD_AUDIO_H */
> diff --git a/src/server/module.c b/src/server/module.c
> index 3932e6d..b27727d 100644
> --- a/src/server/module.c
> +++ b/src/server/module.c
> @@ -313,18 +313,6 @@ OutputModule *load_output_module(char *mod_name, char 
> *mod_prog,
>               output_module_debug(module);
>       }
>  
> -     /* Initialize audio settings */
> -     ret = output_send_audio_settings(module);
> -     if (ret != 0) {
> -             MSG(1,
> -                 "ERROR: Can't initialize audio in output module, see reason 
> above.");
> -             module->working = 0;
> -             kill(module->pid, 9);
> -             waitpid(module->pid, NULL, WNOHANG);
> -             destroy_module(module);
> -             return NULL;
> -     }
> -
>       /* Send log level configuration setting */
>       ret = output_send_loglevel_setting(module);
>       if (ret != 0) {
> diff --git a/src/server/msg.h b/src/server/msg.h
> index 67c07a9..a8f5048 100644
> --- a/src/server/msg.h
> +++ b/src/server/msg.h
> @@ -24,7 +24,8 @@
>  #ifndef MSG_H
>  #define MSG_H
>  
> -#define NEWLINE                                                      "\r\n"
> +#include <speechd_defines.h>
> +
>  #define OK_LANGUAGE_SET                                      "201 OK 
> LANGUAGE SET" NEWLINE
>  #define OK_PRIORITY_SET                                      "202 OK 
> PRIORITY SET" NEWLINE
>  #define OK_RATE_SET                                          "203 OK RATE 
> SET" NEWLINE
> diff --git a/src/server/output.c b/src/server/output.c
> index 0d3e40b..cfa02bc 100644
> --- a/src/server/output.c
> +++ b/src/server/output.c
> @@ -482,29 +482,6 @@ int output_send_settings(TSpeechDMessage * msg, 
> OutputModule * output)
>               g_string_append_printf(set_str, #name"=NULL\n"); \
>       }
>  
> -int output_send_audio_settings(OutputModule * output)
> -{
> -     GString *set_str;
> -     int err;
> -
> -     MSG(4, "Module set parameters.");
> -     set_str = g_string_new("");
> -     ADD_SET_STR(audio_output_method);
> -     ADD_SET_STR(audio_oss_device);
> -     ADD_SET_STR(audio_alsa_device);
> -     ADD_SET_STR(audio_nas_server);
> -     ADD_SET_STR(audio_pulse_server);
> -     ADD_SET_INT(audio_pulse_min_length);
> -
> -     SEND_CMD_N("AUDIO");
> -     SEND_DATA_N(set_str->str);
> -     SEND_CMD_N(".");
> -
> -     g_string_free(set_str, 1);
> -
> -     return 0;
> -}
> -
>  int output_send_loglevel_setting(OutputModule * output)
>  {
>       GString *set_str;
> diff --git a/src/server/output.h b/src/server/output.h
> index 10bbe80..d48602b 100644
> --- a/src/server/output.h
> +++ b/src/server/output.h
> @@ -41,7 +41,6 @@ GString *output_read_reply(OutputModule * output);
>  char *output_read_reply2(OutputModule * output);
>  int output_send_data(char *cmd, OutputModule * output, int wfr);
>  int output_send_settings(TSpeechDMessage * msg, OutputModule * output);
> -int output_send_audio_settings(OutputModule * output);
>  int output_send_loglevel_setting(OutputModule * output);
>  int output_module_is_speaking(OutputModule * output, char **index_mark);
>  int waitpid_with_timeout(pid_t pid, int *status_ptr, int options,
> diff --git a/src/server/server.c b/src/server/server.c
> index 6bdc78e..cf72880 100644
> --- a/src/server/server.c
> +++ b/src/server/server.c
> @@ -31,6 +31,7 @@
>  #include "speaking.h"
>  #include "sem_functions.h"
>  #include "history.h"
> +#include "speechd_defines.h"
>  
>  int last_message_id = 0;
>  
> diff --git a/src/server/set.c b/src/server/set.c
> index d0c2305..23e2a9c 100644
> --- a/src/server/set.c
> +++ b/src/server/set.c
> @@ -537,6 +537,20 @@ TFDSetElement *default_fd_set(void)
>       return (new);
>  }
>  
> +TAudioFDSetElement *default_audio_fd_set(void)
> +{
> +     TAudioFDSetElement *new;
> +
> +     new = (TAudioFDSetElement *) g_malloc(sizeof(TAudioFDSetElement));
> +
> +     /* Fill with the global settings values */
> +     /* We can't use global_fdset copy as this
> +        returns static structure and we need dynamic */
> +     new->output_module = g_strdup(GlobalFDSet.output_module);
> +
> +     return (new);
> +}
> +
>  int get_client_uid_by_fd(int fd)
>  {
>       int *uid;
> diff --git a/src/server/set.h b/src/server/set.h
> index 08866ab..2b7f488 100644
> --- a/src/server/set.h
> +++ b/src/server/set.h
> @@ -94,6 +94,7 @@ int set_debug_all(int debug);
>  int set_debug_destination_all(char *debug_destination);
>  
>  TFDSetElement *default_fd_set(void);
> +TAudioFDSetElement *default_audio_fd_set(void);
>  
>  char *set_param_str(char *parameter, char *value);
>  
> diff --git a/src/server/speechd.c b/src/server/speechd.c
> index d790c3f..21ca5c1 100644
> --- a/src/server/speechd.c
> +++ b/src/server/speechd.c
> @@ -31,8 +31,10 @@
>  #include <sys/stat.h>
>  #include <sys/socket.h>
>  #include <sys/un.h>
> +#include <ltdl.h>
>  
>  #include "speechd.h"
> +#include "audio.h"
>  
>  /* Declare dotconf functions and data structures*/
>  #include "configuration.h"
> @@ -76,6 +78,10 @@ static gboolean client_process_incoming (gint          fd,
>                                 GIOCondition  condition,
>                                 gpointer      data);
>  
> +static gboolean audio_process_incoming (gint           fd,
> +                               GIOCondition  condition,
> +                               gpointer      data);
> +
>  void check_client_count(void);
>  
>  #ifdef __SUNPRO_C
> @@ -867,6 +873,7 @@ int make_local_socket(const char *filename)
>               FATAL("listen() failed for local socket");
>       }
>  
> +     MSG(5, "Successfully opened local socket at %s", filename);
>       return sock;
>  }
>  
> @@ -911,6 +918,7 @@ int make_inet_socket(const int port)
>                   ("listen() failed for inet socket, another Speech 
> Dispatcher running?");
>       }
>  
> +     MSG(5, "Successfully opened inet socket on port %d", port);
>       return server_socket;
>  }
>  
> @@ -981,6 +989,7 @@ int main(int argc, char *argv[])
>       char *spawn_communication_method = NULL;
>       int spawn_port = 0;
>       char *spawn_socket_path = NULL;
> +     char *status_info;
>  
>       /* Strip all permisions for 'others' from the files created */
>       umask(007);
> @@ -991,6 +1000,9 @@ int main(int argc, char *argv[])
>       custom_logfile = NULL;
>       custom_log_kind = NULL;
>  
> +     /* Initialize ltdl's list of preloaded audio backends. */
> +     LTDL_SET_PRELOADED_SYMBOLS();
> +
>       /* initialize i18n support */
>       i18n_init();
>  
> @@ -1116,8 +1128,11 @@ int main(int argc, char *argv[])
>               exit(1);
>       }
>  
> +     /* We need this first since modules will connect to it */
> +     speechd_audio_socket_init();
> +     
>       speechd_init();
> -
> +     
>       /* Handle socket_path 'default' */
>       // TODO: This is a hack, we should do that at appropriate places...
>       if (!strcmp(SpeechdOptions.socket_path, "default")) {
> @@ -1237,6 +1252,8 @@ int main(int argc, char *argv[])
>       g_unix_signal_add(SIGUSR1, speechd_reload_dead_modules, NULL);
>       (void)signal(SIGPIPE, SIG_IGN);
>  
> +     speechd_audio_init();
> +     
>       MSG(4, "Creating new thread for speak()");
>       ret = pthread_create(&speak_thread, NULL, speak, NULL);
>       if (ret != 0)
> @@ -1280,6 +1297,8 @@ int main(int argc, char *argv[])
>       if (close(server_socket) == -1)
>               MSG(2, "close() failed: %s", strerror(errno));
>  
> +     speechd_audio_cleanup();
> +     
>       MSG(4, "Removing pid file");
>       destroy_pid_file();
>  
> diff --git a/src/server/speechd.h b/src/server/speechd.h
> index e5e620b..0e80d6f 100644
> --- a/src/server/speechd.h
> +++ b/src/server/speechd.h
> @@ -111,6 +111,12 @@ typedef struct {
>  } TFDSetElement;
>  
>  typedef struct {
> +     int fd;                 /* File descriptor the module is on. */
> +     guint fd_source;        /* Used to store the GSource ID for watching fd 
> activity in the main loop */
> +     char *output_module;    /* Output module name. (e.g. "festival", 
> "flite", "apollo", ...) */
> +} TAudioFDSetElement;
> +
> +typedef struct {
>       char *pattern;
>       TFDSetElement val;
>  } TFDSetClientSpecific;
> @@ -153,6 +159,7 @@ struct {
>       char *communication_method;
>       int communication_method_set;
>       char *socket_path;
> +     char *audio_socket_path;
>       int socket_path_set;
>       int port, port_set;
>       int localhost_access_only, localhost_access_only_set;
> @@ -256,6 +263,8 @@ int isanum(const char *str);
>   absolute (starting with slash) or relative. */
>  char *spd_get_path(char *filename, char *startdir);
>  
> +int make_local_socket(const char *filename);
> +
>  /* Functions used in speechd.c only */
>  int speechd_connection_new(int server_socket);
>  int speechd_connection_destroy(int fd);
> -- 
> 2.5.0
> 

> _______________________________________________
> Speechd mailing list
> Speechd at lists.freebsoft.org
> http://lists.freebsoft.org/mailman/listinfo/speechd




reply via email to

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