speechd-discuss
[Top][All Lists]
Advanced

[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: Thu, 11 Feb 2016 20:45:55 -0700

Hi Andrei,

On Thu, Feb 11, 2016 at 1:51 PM, Andrei Kholodnyi
<andrei.kholodnyi at gmail.com> wrote:
> Hi Jeremy,
>
> I'm glad to see that we have common understanding on this topic.
> server shall handle client connections, client shall handle data.
>
> Currently it is not like this, and I think we need to put efforts fixing it.
> I really like your idea to get audio back from the modules, but it shall go
> directly to the client.

Yeah, sending the audio data back to each client makes sense.
Especially as most libspeechd users likely have some sound output
mechanism of their own. Recently a client evaluated speech-dispatcher
and decided to write their own library that does most/some of what it
does but gives them the audio back rather than playing it itself.
There were other reasons they decided to write their own rather than
use speech-dispatcher (proprietary speech synthesizer, etc.) but
that's one of the reasons.

> Also I'm not sure we need to mix metadata and audio in one stream.

Yeah, I don't like it mixing them either, but wasn't sure how to
separate them. I guess we could have two sockets, one for metadata and
the other for the raw data or something. Do you have something in
mind?
>
> BTW, have you realized you answer me directly :)

I didn't realize that, no, my mistake. CC'ing the list this time,
thanks for pointing it out.

thanks,
Jeremy
>
> Thanks,
> Andrei
>
> 2016-02-11 20:48 GMT+01:00 Jeremy Whiting <jpwhiting at kde.org>:
>>
>> Andrei,
>>
>> That would make sense (having one audio output per client), but that's
>> not how it currently works. Currently every output module has it's own
>> audio output thread. Since I have espeak, flite, pico, and festival
>> here, each of sd_espeak, sd_flite, sd_pico and sd_festival has a
>> connection to the audio system (pulse in my case). Having the audio go
>> through the server simplifies it down to one connection to audio, so
>> there's only one volume control for all of speech-dispatcher rather
>> than 4 (when I have 4 they all say their name is the same too, so
>> changing the volume of speech-dispatcher becomes a guessing game).
>>
>> Once speech-dispatcher creates output modules as needed (when
>> requested by each client) that will help also, but this change doesn't
>> depend on that happening.
>>
>> BR,
>> Jeremy
>>
>> On Thu, Feb 11, 2016 at 12:33 PM, Andrei Kholodnyi
>> <andrei.kholodnyi at gmail.com> wrote:
>> > sorry, selected your private email address while replying. I have resent
>> > my
>> > post to the speechd list
>> >
>> > 2016-02-11 20:29 GMT+01:00 Andrei Kholodnyi
>> > <andrei.kholodnyi at gmail.com>:
>> >>
>> >> Hi Jeremy,
>> >>
>> >> I'm not sure I understand the ratio behind of putting the audio
>> >> processing
>> >> in the server part.
>> >> You have an incoming text stream associated with each client, the
>> >> outcoming audio stream shall be also associated with the client as
>> >> well, not
>> >> with the server.
>> >>
>> >> Andrei
>> >>
>> >> 2016-02-11 1:38 GMT+01:00 Jeremy Whiting <jpwhiting at kde.org>:
>> >>>
>> >>> 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
>> >>>
>> >>> _______________________________________________
>> >>> Speechd mailing list
>> >>> Speechd at lists.freebsoft.org
>> >>> http://lists.freebsoft.org/mailman/listinfo/speechd
>> >>>
>> >>
>> >>
>> >>
>> >> --
>> >> Believe is not enough, you must know
>> >
>> >
>> >
>> >
>> > --
>> > Believe is not enough, you must know
>
>
>
>
> --
> Believe is not enough, you must know



reply via email to

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