[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
WIP audio in server
From: |
Jeremy Whiting |
Subject: |
WIP audio in server |
Date: |
Wed, 10 Feb 2016 17:38:43 -0700 |
Ok, here's an updated patch that includes fixes in flite and pico
output modules. It seems to work pretty well here, though I haven't
tested all the output modules yet.
On Mon, Aug 17, 2015 at 1:36 PM, Jeremy Whiting <jpwhiting at kde.org> wrote:
> Trevor,
>
> On Mon, Aug 17, 2015 at 1:30 PM, Trevor Saunders <tbsaunde at tbsaunde.org>
> wrote:
>> On Thu, Aug 13, 2015 at 05:28:00PM -0600, Jeremy Whiting wrote:
>>> Trevor,
>>>
>>> On Thu, Aug 13, 2015 at 4:43 PM, Trevor Saunders <tbsaunde at tbsaunde.org>
>>> wrote:
>>> > 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?
>>>
>>> I hadn't thought of that. I thought a unix socket would be easier
>>> since in the near (maybe) future we will have the server spawn an
>>> output module for each client when it is requested. I'm not sure if
>>> using a pipe would make that easier or harder though.
>>
>> If you deal with audio in the main server process I don't think it would
>> be any harder. The one thing I don't see how to handle is changing
>> audio method while modules are running, but I'm not sure if that is or
>> should be supported.
>>
>>> >> 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.
>>>
>>> Actually both are sending audio through module_tts_output which with
>>> this patch sends it through the socket to the server to play.
>>
>> oh heh maybe I should have read the patch and stuff before talking.
>>
>>> >
>>> > 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.
>>>
>>> I haven't considered that. I'd rather not reinvent pulseaudio for our
>>> own purposes if we can avoid it though.
>>
>> I'm not sure I'd call it reinventing Pulse, but it may be the case
>> outputting audio is not complex enough to be worth it.
>
> No worries. With the latest patch I sent all the audio is handled in
> one thread. It's not very complex at all.
>
> BR,
> Jeremy
>
>>
>> Trev
>>
>>>
>>> BR,
>>> Jeremy
>>>
>>> >
>>> > 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
>>> >
>>> >
>>> > _______________________________________________
>>> > Speechd mailing list
>>> > Speechd at lists.freebsoft.org
>>> > http://lists.freebsoft.org/mailman/listinfo/speechd
>>>
>>> _______________________________________________
>>> Speechd mailing list
>>> Speechd at lists.freebsoft.org
>>> http://lists.freebsoft.org/mailman/listinfo/speechd
>>
>> _______________________________________________
>> Speechd mailing list
>> Speechd at lists.freebsoft.org
>> http://lists.freebsoft.org/mailman/listinfo/speechd
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Moving-audio-from-modules-to-the-server.patch
Type: text/x-patch
Size: 59869 bytes
Desc: not available
URL:
<http://lists.freebsoft.org/pipermail/speechd/attachments/20160210/21a79904/attachment-0001.bin>
- WIP audio in server,
Jeremy Whiting <=
- WIP audio in server, Andrei Kholodnyi, 2016/02/11
- Message not available
- Message not available
- Message not available
- Message not available
- WIP audio in server, Jeremy Whiting, 2016/02/11
- WIP audio in server, Luke Yelavich, 2016/02/12
- WIP audio in server, Jeremy Whiting, 2016/02/12
- WIP audio in server, Tim Cross, 2016/02/13
- WIP audio in server, Chris Brannon, 2016/02/13
- WIP audio in server, Tim Cross, 2016/02/13
- WIP audio in server, Andrei Kholodnyi, 2016/02/14
- WIP audio in server, Jeremy Whiting, 2016/02/25