From 9059fb91cc3a891013534a5556cb127d90767461 Mon Sep 17 00:00:00 2001 From: Peter Olsson Date: Sun, 2 Feb 2014 12:33:37 +0100 Subject: [PATCH] FS-5045 --- build/modules.conf.in | 1 + .../autoload_configs/modules.conf.xml | 1 + conf/rayo/autoload_configs/modules.conf.xml | 1 + conf/rayo/freeswitch.xml | 1 + conf/rayo/lang/sv/sv.xml | 7 + conf/rayo/lang/sv/vm/sounds.xml | 504 +++++++++++++ .../vanilla/autoload_configs/modules.conf.xml | 1 + conf/vanilla/freeswitch.xml | 1 + conf/vanilla/lang/sv/sv.xml | 7 + conf/vanilla/lang/sv/vm/sounds.xml | 504 +++++++++++++ debian/control-modules | 4 + freeswitch-sounds-sv-se-jakob.spec | 377 ++++++++++ freeswitch.spec | 14 +- src/include/switch_types.h | 3 +- src/mod/say/mod_say_sv/Makefile | 2 + .../say/mod_say_sv/mod_say_sv.2010.vcxproj | 135 ++++ .../say/mod_say_sv/mod_say_sv.2012.vcxproj | 135 ++++ src/mod/say/mod_say_sv/mod_say_sv.c | 699 ++++++++++++++++++ 18 files changed, 2395 insertions(+), 2 deletions(-) create mode 100644 conf/rayo/lang/sv/sv.xml create mode 100644 conf/rayo/lang/sv/vm/sounds.xml create mode 100644 conf/vanilla/lang/sv/sv.xml create mode 100644 conf/vanilla/lang/sv/vm/sounds.xml create mode 100644 freeswitch-sounds-sv-se-jakob.spec create mode 100644 src/mod/say/mod_say_sv/Makefile create mode 100644 src/mod/say/mod_say_sv/mod_say_sv.2010.vcxproj create mode 100644 src/mod/say/mod_say_sv/mod_say_sv.2012.vcxproj create mode 100644 src/mod/say/mod_say_sv/mod_say_sv.c diff --git a/build/modules.conf.in b/build/modules.conf.in index 727ec9191a..9b38e070ed 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -140,6 +140,7 @@ say/mod_say_en #say/mod_say_ru #say/mod_say_th #say/mod_say_zh +#say/mod_say_sv #timers/mod_posix_timer #timers/mod_timerfd xml_int/mod_xml_cdr diff --git a/conf/insideout/autoload_configs/modules.conf.xml b/conf/insideout/autoload_configs/modules.conf.xml index b15595c466..6cdb4ddaae 100644 --- a/conf/insideout/autoload_configs/modules.conf.xml +++ b/conf/insideout/autoload_configs/modules.conf.xml @@ -96,5 +96,6 @@ + diff --git a/conf/rayo/autoload_configs/modules.conf.xml b/conf/rayo/autoload_configs/modules.conf.xml index e0d81b34fa..85191aceeb 100644 --- a/conf/rayo/autoload_configs/modules.conf.xml +++ b/conf/rayo/autoload_configs/modules.conf.xml @@ -66,6 +66,7 @@ + diff --git a/conf/rayo/freeswitch.xml b/conf/rayo/freeswitch.xml index 49bd41fec2..f38983ebcb 100644 --- a/conf/rayo/freeswitch.xml +++ b/conf/rayo/freeswitch.xml @@ -63,6 +63,7 @@ + diff --git a/conf/rayo/lang/sv/sv.xml b/conf/rayo/lang/sv/sv.xml new file mode 100644 index 0000000000..f77e0221f6 --- /dev/null +++ b/conf/rayo/lang/sv/sv.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/conf/rayo/lang/sv/vm/sounds.xml b/conf/rayo/lang/sv/vm/sounds.xml new file mode 100644 index 0000000000..aaee3c0b6b --- /dev/null +++ b/conf/rayo/lang/sv/vm/sounds.xml @@ -0,0 +1,504 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/vanilla/autoload_configs/modules.conf.xml b/conf/vanilla/autoload_configs/modules.conf.xml index eb4a8f4bd7..67396b17ee 100644 --- a/conf/vanilla/autoload_configs/modules.conf.xml +++ b/conf/vanilla/autoload_configs/modules.conf.xml @@ -127,6 +127,7 @@ + diff --git a/conf/vanilla/freeswitch.xml b/conf/vanilla/freeswitch.xml index b067d986c4..51b93f8a70 100644 --- a/conf/vanilla/freeswitch.xml +++ b/conf/vanilla/freeswitch.xml @@ -67,5 +67,6 @@ + diff --git a/conf/vanilla/lang/sv/sv.xml b/conf/vanilla/lang/sv/sv.xml new file mode 100644 index 0000000000..f77e0221f6 --- /dev/null +++ b/conf/vanilla/lang/sv/sv.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/conf/vanilla/lang/sv/vm/sounds.xml b/conf/vanilla/lang/sv/vm/sounds.xml new file mode 100644 index 0000000000..aaee3c0b6b --- /dev/null +++ b/conf/vanilla/lang/sv/vm/sounds.xml @@ -0,0 +1,504 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/debian/control-modules b/debian/control-modules index 9fa832b117..b681d3f681 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -665,6 +665,10 @@ Module: say/mod_say_zh Description: mod_say_zh Adds mod_say_zh. +Module: say/mod_say_sv +Description: mod_say_sv + Adds mod_say_sv. + ## mod/sdk Module: sdk/autotools diff --git a/freeswitch-sounds-sv-se-jakob.spec b/freeswitch-sounds-sv-se-jakob.spec new file mode 100644 index 0000000000..06f91becb7 --- /dev/null +++ b/freeswitch-sounds-sv-se-jakob.spec @@ -0,0 +1,377 @@ +############################################################################## +# Copyright and license +############################################################################## +# +# Spec file for package freeswitch-sounds-sv-se-jakob (version 1.0.18-1) +# +# Copyright (c) 2009 Patrick Laimbock +# Some fixes and additions (c) 2011 Michal Bielicki +# Copied and modified for mod_say_sv (c) 2013 Jakob Sundberg +# This file and all modifications and additions to the pristine +# package are under the same license as the package itself. +# + +############################################################################## +# Determine distribution +############################################################################## + +# %define is_rhel5 %(test -f /etc/redhat-release && egrep -q 'release 5' /etc/redhat-release && echo 1 || echo 0) + +############################################################################## +# Set variables +############################################################################## + +%define version %{VERSION_NUMBER} +%define release %{BUILD_NUMBER} + +%define fsname freeswitch +# you could add a version number to be more strict + +%define PREFIX %{_prefix} +%define EXECPREFIX %{_exec_prefix} +%define BINDIR %{_bindir} +%define SBINDIR %{_sbindir} +%define LIBEXECDIR %{_libexecdir}/%{fsname} +%define SYSCONFDIR %{_sysconfdir}/%{fsname} +%define SHARESTATEDIR %{_sharedstatedir}/%{fsname} +%define LOCALSTATEDIR %{_localstatedir}/lib/%{fsname} +%define LIBDIR %{_libdir} +%define INCLUDEDIR %{_includedir} +%define _datarootdir %{_prefix}/share +%define DATAROOTDIR %{_datarootdir} +%define DATADIR %{_datadir} +%define INFODIR %{_infodir} +%define LOCALEDIR %{_datarootdir}/locale +%define MANDIR %{_mandir} +%define DOCDIR %{_defaultdocdir}/%{fsname} +%define HTMLDIR %{_defaultdocdir}/%{fsname}/html +%define DVIDIR %{_defaultdocdir}/%{fsname}/dvi +%define PDFDIR %{_defaultdocdir}/%{fsname}/pdf +%define PSDIR %{_defaultdocdir}/%{fsname}/ps +%define LOGFILEDIR /var/log/%{fsname} +%define MODINSTDIR %{_libdir}/%{fsname}/mod +%define RUNDIR %{_localstatedir}/run/%{fsname} +%define DBDIR %{LOCALSTATEDIR}/db +%define HTDOCSDIR %{_datarootdir}/%{fsname}/htdocs +%define SOUNDSDIR %{_datarootdir}/%{fsname}/sounds +%define GRAMMARDIR %{_datarootdir}/%{fsname}/grammar +%define SCRIPTDIR %{_datarootdir}/%{fsname}/scripts +%define RECORDINGSDIR %{LOCALSTATEDIR}/recordings +%define PKGCONFIGDIR %{_datarootdir}/%{fsname}/pkgconfig +%define HOMEDIR %{LOCALSTATEDIR} + + +############################################################################## +# General +############################################################################## + +Summary: FreeSWITCH sv-se Jakob prompts +Name: freeswitch-sounds-sv-se-jakob +Version: %{version} +Release: %{release}%{?dist} +License: MPL +Group: Applications/Communications +Packager: Patrick Laimbock +URL: http://www.freeswitch.org +Source0:http://files.freeswitch.org/%{name}-48000-%{version}.tar.bz2 +BuildArch: noarch +BuildRequires: sox +Requires: freeswitch +Requires: freeswitch-sounds-sv-se-jakob-48000 +Requires: sox +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +%description +FreeSWITCH 48kHz sv-se jakob prompts plus, during the installation, +it will also install locally generated 8KHz, 16KHz and 32KHz prompts + +%package -n freeswitch-sounds-sv-se-jakob-8000 +Summary: FreeSWITCH 8kHz sv-se jakob prompts +Group: Applications/Communications +BuildArch: noarch +Requires: %{fsname} + +%description -n freeswitch-sounds-sv-se-jakob-8000 +FreeSWITCH 8kHz sv-se jakob prompts + +%package -n freeswitch-sounds-sv-se-jakob-16000 +Summary: FreeSWITCH 16kHz sv-se jakob prompts +Group: Applications/Communications +BuildArch: noarch +Requires: %{fsname} + +%description -n freeswitch-sounds-sv-se-jakob-16000 +FreeSWITCH 16kHz sv-se jakob prompts + +%package -n freeswitch-sounds-sv-se-jakob-32000 +Summary: FreeSWITCH 32kHz sv-se jakob prompts +Group: Applications/Communications +BuildArch: noarch +Requires: %{fsname} + +%description -n freeswitch-sounds-sv-se-jakob-32000 +FreeSWITCH 32kHz sv-se jakob prompts + +%package -n freeswitch-sounds-sv-se-jakob-48000 +Summary: FreeSWITCH 48kHz sv-se jakob prompts +Group: Applications/Communications +BuildArch: noarch +Requires: %{fsname} + +%description -n freeswitch-sounds-sv-se-jakob-48000 +FreeSWITCH 48kHz sv-se jakob prompts + +%package -n freeswitch-sounds-sv-se-jakob-all +Summary: FreeSWITCH sv-se jakob prompts +Group: Applications/Communications +BuildArch: noarch +Requires: %{fsname} +Requires: freeswitch-sounds-sv-se-jakob-8000 = %{version} +Requires: freeswitch-sounds-sv-se-jakob-16000 = %{version} +Requires: freeswitch-sounds-sv-se-jakob-32000 = %{version} +Requires: freeswitch-sounds-sv-se-jakob-48000 = %{version} + +%description -n freeswitch-sounds-sv-se-jakob-all +FreeSWITCH jakob prompts package that pulls in the 8KHz, 16KHz, +32KHz and 48KHz RPMs + +############################################################################## +# Prep +############################################################################## + +%prep +%setup -b0 -q -n en +mkdir -p ./usr/jakob +# create buildsounds-jakob.sh script in working dir +echo '#!/bin/bash + +sounds_location=$1 +for rate in 32000 16000 8000 +do + for i in ascii base256 conference currency digits directory ivr misc phonetic-ascii time voicemail zrtp + do + mkdir -p $sounds_location/$i/$rate + for f in `find $sounds_location/$i/48000 -name \*.wav` + do + echo "generating" $sounds_location/$i/$rate/`basename $f` + sox $f -r $rate $sounds_location/$i/$rate/`basename $f` + done + done +done' > ./sv/jakob/buildsounds-jakob.sh +%{__chmod} 0750 ./sv/jakob/buildsounds-jakob.sh + +############################################################################## +# Build +############################################################################## + +%build +# nothing to do here + +############################################################################## +# Install +############################################################################## + +%install +[ "%{buildroot}" != '/' ] && rm -rf %{buildroot} + +# create the sounds directories +%{__install} -d -m 0750 %{buildroot}%{SOUNDSDIR}/sv/se/jakob + +pushd sv/jakob +# first install the 48KHz sounds +%{__cp} -prv ./* %{buildroot}%{SOUNDSDIR}/sv/se/jakob +# now resample the 48KHz ones to 8KHz, 16KHz and 32KHz +./buildsounds-jakob.sh %{buildroot}%{SOUNDSDIR}/sv/se/jakob +popd + +############################################################################## +# Clean +############################################################################## + +%clean +[ "%{buildroot}" != '/' ] && rm -rf %{buildroot} + +############################################################################## +# Post +############################################################################## + +%post +# generate the 8KHz, 16KHz and 32KHz prompts from the 48KHz ones +cd %{SOUNDSDIR}/sv/se/jakob +./buildsounds-jakob.sh %{SOUNDSDIR}/sv/se/jakob + +############################################################################## +# Postun +############################################################################## + +%postun +# you could check if there are sound files in 8000/ or +# 16000/ or 32000/ and remove them *only* if the files +# do not belong to an rpm + +############################################################################## +# Files +############################################################################## + +%files +%defattr(-,root,root) +%attr(0750,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/buildsounds-jakob.sh + +%files -n freeswitch-sounds-sv-se-jakob-8000 +%defattr(-,root,root,-) +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ascii/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/base256/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/conference/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/currency/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/digits/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/directory/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ivr/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/misc/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/time/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/voicemail/8000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/zrtp/8000 +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ascii/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/base256/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/conference/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/currency/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/digits/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/directory/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ivr/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/misc/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/time/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/voicemail/8000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/zrtp/8000/*.wav + +%files -n freeswitch-sounds-sv-se-jakob-16000 +%defattr(-,root,root,-) +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ascii/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/base256/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/conference/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/currency/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/digits/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/directory/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ivr/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/misc/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/time/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/voicemail/16000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/zrtp/16000 +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ascii/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/base256/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/conference/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/currency/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/digits/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/directory/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ivr/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/misc/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/time/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/voicemail/16000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/zrtp/16000/*.wav + +%files -n freeswitch-sounds-sv-se-jakob-32000 +%defattr(-,root,root,-) +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ascii/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/base256/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/conference/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/currency/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/digits/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/directory/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ivr/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/misc/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/time/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/voicemail/32000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/zrtp/32000 +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ascii/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/base256/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/conference/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/currency/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/digits/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/directory/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ivr/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/misc/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/time/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/voicemail/32000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/zrtp/32000/*.wav + +%files -n freeswitch-sounds-sv-se-jakob-48000 +%defattr(-,root,root,-) +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ascii/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/base256/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/conference/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/currency/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/digits/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/directory/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/ivr/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/misc/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/time/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/voicemail/48000 +%attr(0750,freeswitch,daemon) %dir %{SOUNDSDIR}/sv/se/jakob/zrtp/48000 +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ascii/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/base256/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/conference/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/currency/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/digits/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/directory/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/ivr/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/misc/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/phonetic-ascii/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/time/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/voicemail/48000/*.wav +%attr(0640,freeswitch,daemon) %{SOUNDSDIR}/sv/se/jakob/zrtp/48000/*.wav + +%files -n freeswitch-sounds-sv-se-jakob-all + +############################################################################## +# Changelog +############################################################################## + +%changelog +* Sun Mar 05 2012 Ken Rice - 1.0.18-1 +- update to FHS Layout for FreeSWITCH +- bump up version +* Sun May 22 2011 Michal Bielicki - 1.0.16-1 +- bump up version +* Tue Jan 18 2011 Michal Bielicki - 1.0.14-1 +- bump up version +- include script into freeswitch core +- include specfile into freeswitch core +- runtime does not require sox, only building + +* Thu Dec 17 2009 Patrick Laimbock - 1.0.12-8 +- update perms and user/group to sync with the old situation + +* Wed Dec 16 2009 Patrick Laimbock - 1.0.12-7 +- make main package require freeswitch-sounds-sv-se-jakob-48000 and +- generate the 8KHz, 16KHz and 32KHz sounds from there +- add license to spec file + +* Wed Dec 16 2009 Patrick Laimbock - 1.0.12-5 +- put 48KHz in a separate package and let the main package Require 48KHz +- and then use the script to generate the 8KHz, 16KHz and 32KHz sounds + +* Wed Dec 16 2009 Patrick Laimbock - 1.0.12-4 +- add freeswitch-sounds-sv-se-jakob-all package that pulls in the 8KHz, +- 16KHz, 32KHz and 48KHz RPM packages + +* Tue Dec 15 2009 Patrick Laimbock - 1.0.12-3 +- override subpackage name with -n so it no longer builds an empty main RPM +- rework spec file +- add sox as a requirement +- run buildsounds-jakob.sh in post to generate 8KHz, 16KHz and 32KHz prompts + +* Tue Dec 15 2009 Patrick Laimbock - 1.0.12-2 +- can't override Name in subpackage so put all versions in RPM subpackages +- with an empty main RPM package + +* Tue Dec 15 2009 Patrick Laimbock - 1.0.12-1 +- create spec file with the following requirement: +- source only contains the 48KHz sound prompts +- during build the 48KHz sound prompts are resampled to 8KHz, 16KHz and 32KHz +- the 8KHz, 16KHz, 32KHz and 48KHz sound prompts are packaged separately + diff --git a/freeswitch.spec b/freeswitch.spec index 6c7e08ad2b..2ec731a208 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -1443,7 +1443,7 @@ LOGGERS_MODULES="loggers/mod_console loggers/mod_logfile loggers/mod_syslog" # Phrase engine language modules # ###################################################################################################################### -SAY_MODULES="say/mod_say_de say/mod_say_en say/mod_say_fr say/mod_say_he say/mod_say_ru" +SAY_MODULES="say/mod_say_de say/mod_say_en say/mod_say_fr say/mod_say_he say/mod_say_ru say/mod_say_sv" ###################################################################################################################### # @@ -2408,6 +2408,16 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/pt/dir/*.xml %{MODINSTDIR}/mod_say_en.so* +%files lang-sv +%defattr(-, freeswitch, daemon) +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/sv +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/sv/demo +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/sv/vm +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/sv/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/sv/demo/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/sv/vm/*.xml +%{MODINSTDIR}/mod_say_sv.so* + ###################################################################################################################### # # Timer Modules @@ -2444,6 +2454,8 @@ fi # ###################################################################################################################### %changelog +* Sun Feb 02 2014 - jakob@mress.se +- add support for building Swedish say language module * Mon Jan 13 2014 - peter@olssononline.se - Add mod_v8 * Mon Dec 09 2013 - crienzo@grasshopper.com diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 331bcb523f..e9b6fca591 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -432,7 +432,8 @@ typedef enum { typedef enum { SSG_MASCULINE, SSG_FEMININE, - SSG_NEUTER + SSG_NEUTER, + SSG_UTRUM } switch_say_gender_t; typedef enum { diff --git a/src/mod/say/mod_say_sv/Makefile b/src/mod/say/mod_say_sv/Makefile new file mode 100644 index 0000000000..2c35e6e98f --- /dev/null +++ b/src/mod/say/mod_say_sv/Makefile @@ -0,0 +1,2 @@ +BASE=../../../.. +include $(BASE)/build/modmake.rules diff --git a/src/mod/say/mod_say_sv/mod_say_sv.2010.vcxproj b/src/mod/say/mod_say_sv/mod_say_sv.2010.vcxproj new file mode 100644 index 0000000000..b61c9d229b --- /dev/null +++ b/src/mod/say/mod_say_sv/mod_say_sv.2010.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + mod_say_sv + {988CACF7-3FCB-4992-BE69-77872AE67DC8} + mod_say_sv + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + {f6c55d93-b927-4483-bb69-15aef3dd2dff} + false + + + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} + false + + + + + + diff --git a/src/mod/say/mod_say_sv/mod_say_sv.2012.vcxproj b/src/mod/say/mod_say_sv/mod_say_sv.2012.vcxproj new file mode 100644 index 0000000000..d6d91bb20c --- /dev/null +++ b/src/mod/say/mod_say_sv/mod_say_sv.2012.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + mod_say_sv + {988CACF7-3FCB-4992-BE69-77872AE67DC8} + mod_say_sv + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + {f6c55d93-b927-4483-bb69-15aef3dd2dff} + false + + + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} + false + + + + + + diff --git a/src/mod/say/mod_say_sv/mod_say_sv.c b/src/mod/say/mod_say_sv/mod_say_sv.c new file mode 100644 index 0000000000..6607ba26f6 --- /dev/null +++ b/src/mod/say/mod_say_sv/mod_say_sv.c @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2007-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Michael B. Murdock + * Daniel Swarbrick + * Christian Benke + * Jakob Sundberg (2013) + * + * mod_say_sv.c -- Say for Swedish + * + */ + +#include +#include +#include + +SWITCH_MODULE_LOAD_FUNCTION(mod_say_sv_load); +SWITCH_MODULE_DEFINITION(mod_say_sv, mod_say_sv_load, NULL, NULL); + +#define say_num(_sh, num, meth) { \ + char tmp[80]; \ + switch_status_t tstatus; \ + switch_say_method_t smeth = say_args->method; \ + switch_say_type_t stype = say_args->type; \ + say_args->type = SST_ITEMS; say_args->method = meth; \ + switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \ + if ((tstatus = \ + sv_say_general_count(_sh, tmp, say_args)) \ + != SWITCH_STATUS_SUCCESS) { \ + return tstatus; \ + } \ + say_args->method = smeth; say_args->type = stype; \ + } \ + +static switch_status_t play_group(switch_say_method_t method, switch_say_gender_t gender, int a, int b, int c, char *what, switch_say_file_handle_t *sh) +{ + /*swedish makes the distiction between utrum for "one" (en) and neutrum for "one" (ett), e.g. voicemail-message is neutrum but recording is utrum. + This only applies to the likes of 1, 101, 1001 etc. + files referenced below: + SSM_COUNTED=r-%d + SSM_UTRUM=u-1 + SSM_NEUTRUM=n-1 + */ + if (a) { + if (method == SSM_COUNTED) { + if ( a > 1 && b == 0 && c == 0) { /* [2-9]xx */ + switch_say_file(sh, "digits/%d", a); + } + switch_say_file(sh, "digits/r-100"); + } else { + if (a == 1) { /* 1xx */ + switch_say_file(sh, "digits/n-1"); + } else { /* [2-9]xx */ + switch_say_file(sh, "digits/%d", a); + } + switch_say_file(sh, "digits/hundra"); + } + } + + if (b) { + if (b > 1) { /* 20 < 99 */ + if (c == 0) { + if (method == SSM_COUNTED) { + switch_say_file(sh, "digits/r-%d0", b); + } else { + switch_say_file(sh, "digits/%d0", b); + } + } else { + if (c == 1) { + if (method == SSM_COUNTED) { + switch_say_file(sh, "digits/r-1", b); + } else { + if (gender == SSG_UTRUM) { + switch_say_file(sh, "digits/u-1"); + } else { + switch_say_file(sh, "digits/n-1"); + } + } + } else { + if (method == SSM_COUNTED) { + switch_say_file(sh, "digits/r-%d0", b); + } else { + switch_say_file(sh, "digits/%d0", b); + } + } + } + } else { /* 10 < 20 */ + if (method == SSM_COUNTED) { + switch_say_file(sh, "digits/r-%d%d", b, c); + } else { + switch_say_file(sh, "digits/%d%d", b, c); + } + } + c = 0; + } + + if (c) { /* 0 < 9 */ + if (c == 1) { + if (what) { + switch_say_file(sh, "digits/n-1"); + } else { + if (method == SSM_COUNTED) { + switch_say_file(sh, "digits/r-1"); + } else { + if (gender == SSG_UTRUM) { + switch_say_file(sh, "digits/u-1"); + } else { + switch_say_file(sh, "digits/n-1"); + } + } + } + } else { + if (what) { + switch_say_file(sh, "digits/%d", c); + } else { + if (method == SSM_COUNTED) { + switch_say_file(sh, "digits/r-%d", c); + } else { + switch_say_file(sh, "digits/%d", c); + } + } + } + } + + if (what && (a || b || c)) { + switch_say_file(sh, what); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t sv_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args) +{ + int in; + int x = 0; + int places[9] = { 0 }; + char sbuf[128] = ""; + switch_status_t status; + + if (say_args->method == SSM_ITERATED) { + if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) { + char *p; + for (p = tosay; p && *p; p++) { + switch_say_file(sh, "digits/%c", *p); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + return SWITCH_STATUS_GENERR; + } + return SWITCH_STATUS_SUCCESS; + } + + if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + return SWITCH_STATUS_GENERR; + } + + in = atoi(tosay); + + if (in != 0) { /*fills the places-array with tosay(resp. in) from tail to front e.g. 84371 would be places[|1|7|3|4|8|0|0|0|], up to 1 billion minus 1*/ + for (x = 8; x >= 0; x--) { + int num = (int) pow(10, x); + if ((places[(uint32_t) x] = in / num)) { + in -= places[(uint32_t) x] * num; + } + } + + switch (say_args->method) { + case SSM_PRONOUNCED_YEAR: + { + int num = atoi(tosay); + int a = num / 100; + int b = num % 100; + + if (!b || !(a % 10)) { + say_num(sh, num, SSM_PRONOUNCED); + return SWITCH_STATUS_SUCCESS; + } + + say_num(sh, a, SSM_PRONOUNCED); + say_num(sh, b, SSM_PRONOUNCED); + + return SWITCH_STATUS_SUCCESS; + } + break; + case SSM_COUNTED: + case SSM_PRONOUNCED: + if (places[6] == 1 && ( !places[8] || !places[7])) { + if ((status = play_group(SSM_PRONOUNCED, say_args->gender, places[8], places[7], places[6], "digits/miljon", sh)) != SWITCH_STATUS_SUCCESS) { + return status; + } + } else { + if ((status = play_group(SSM_PRONOUNCED, say_args->gender, places[8], places[7], places[6], "digits/miljoner", sh)) != SWITCH_STATUS_SUCCESS) { + return status; + } + } + if ((status = play_group(SSM_PRONOUNCED, say_args->gender, places[5], places[4], places[3], "digits/tusen", sh)) != SWITCH_STATUS_SUCCESS) { + return status; + } + if ((status = play_group(say_args->method, say_args->gender, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) { + return status; + } + break; + default: + break; + } + } else { + switch_say_file(sh, "digits/0"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t sv_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args) +{ + int32_t t; + switch_time_t target = 0, target_now = 0; + switch_time_exp_t tm, tm_now; + uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0; + const char *tz = NULL; + + tz = switch_say_file_handle_get_variable(sh, "timezone"); + + if (say_args->type == SST_TIME_MEASUREMENT) { + int64_t hours = 0; + int64_t minutes = 0; + int64_t seconds = 0; + int64_t r = 0; + + if (strchr(tosay, ':')) { + char *tme = strdup(tosay); + char *p; + + if ((p = strrchr(tme, ':'))) { + *p++ = '\0'; + seconds = atoi(p); + if ((p = strchr(tme, ':'))) { + *p++ = '\0'; + minutes = atoi(p); + if (tme) { + hours = atoi(tme); + } + } else { + minutes = atoi(tme); + } + } + free(tme); + } else { + if ((seconds = atol(tosay)) <= 0) { + seconds = (int64_t) switch_epoch_time_now(NULL); + } + + if (seconds >= 60) { + minutes = seconds / 60; + r = seconds % 60; + seconds = r; + } + + if (minutes >= 60) { + hours = minutes / 60; + r = minutes % 60; + minutes = r; + } + } + + if (hours) { + say_num(sh, hours, SSM_PRONOUNCED); + if (hours == 1) { + switch_say_file(sh, "time/timme"); + } else { + switch_say_file(sh, "time/timmar"); + } + } else { /* midnight */ + if (minutes == 0) { + switch_say_file(sh, "time/midnatt"); + } else { + switch_say_file(sh, "digits/0"); + switch_say_file(sh, "time/timmar"); + } + } + + if (minutes) { + say_num(sh, minutes, SSM_PRONOUNCED); + if (minutes == 1) { + switch_say_file(sh, "time/minut"); + } else { + switch_say_file(sh, "time/minuter"); + } + } else { + switch_say_file(sh, "digits/0"); + switch_say_file(sh, "time/minuter"); + } + + if (seconds) { + say_num(sh, seconds, SSM_PRONOUNCED); + if (seconds == 1) { + switch_say_file(sh, "time/sekund"); + } else { + switch_say_file(sh, "time/sekunder"); + } + } else { + switch_say_file(sh, "digits/0"); + switch_say_file(sh, "time/sekunder"); + } + + return SWITCH_STATUS_SUCCESS; + } + + if ((t = atol(tosay)) > 0) { + target = switch_time_make(t, 0); + target_now = switch_micro_time_now(); + } else { + target = switch_micro_time_now(); + target_now = switch_micro_time_now(); + } + + if (tz) { + int check = atoi(tz); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz); + if (check) { + switch_time_exp_tz(&tm, target, check); + switch_time_exp_tz(&tm_now, target_now, check); + } else { + switch_time_exp_tz_name(tz, &tm, target); + switch_time_exp_tz_name(tz, &tm_now, target_now); + } + } else { + switch_time_exp_lt(&tm, target); + switch_time_exp_lt(&tm_now, target_now); + } + + switch (say_args->type) { + case SST_CURRENT_DATE_TIME: + say_date = say_time = 1; + break; + case SST_CURRENT_DATE: + say_date = 1; + break; + case SST_CURRENT_TIME: + say_time = 1; + break; + case SST_SHORT_DATE_TIME: + say_time = 1; + if (tm.tm_year != tm_now.tm_year) { + say_date = 1; + break; + } + if (tm.tm_yday == tm_now.tm_yday) { + say_today = 1; + break; + } + if (tm.tm_yday == tm_now.tm_yday - 1) { + say_yesterday = 1; + break; + } + if (tm.tm_yday >= tm_now.tm_yday - 5) { + say_dow = 1; + break; + } + if (tm.tm_mon != tm_now.tm_mon) { + say_month = say_day = say_dow = 1; + break; + } + + say_month = say_day = say_dow = 1; + + break; + default: + break; + } + + if (say_today) { + switch_say_file(sh, "time/idag"); + } + if (say_yesterday) { + switch_say_file(sh, "time/igar"); + } + if (say_dow) { + switch_say_file(sh, "time/day-%d", tm.tm_wday); + } + + if (say_date) { + say_year = say_month = say_day = say_dow = 1; + say_today = say_yesterday = 0; + } + + if (say_month) { + switch_say_file(sh, "time/mon-%d", tm.tm_mon); + } + if (say_day) { + say_num(sh, tm.tm_mday, SSM_COUNTED); + } + if (say_year) { + say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED_YEAR); + } + + if (say_time) { /* sweden use only 24h time format */ + if (tm.tm_hour > 9) { + say_num(sh, tm.tm_hour, SSM_PRONOUNCED); + } else if (tm.tm_hour) { + switch_say_file(sh, "digits/0"); + say_num(sh, tm.tm_hour, SSM_PRONOUNCED); + } + if (tm.tm_min > 9) { + say_num(sh, tm.tm_min, SSM_PRONOUNCED); + } else if (tm.tm_min) { + switch_say_file(sh, "digits/0"); + say_num(sh, tm.tm_min, SSM_PRONOUNCED); + } + } + + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t sv_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args) +{ + char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */ + char *dollars = NULL; + char *cents = NULL; + + if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + return SWITCH_STATUS_GENERR; + } + + dollars = sbuf; + + if ((cents = strchr(sbuf, '.'))) { + *cents++ = '\0'; + if (strlen(cents) > 2) { + cents[2] = '\0'; + } + } + + /* If positive sign - skip over" */ + if (sbuf[0] == '+') { + dollars++; + } + + /* If negative say "negative" */ + if (sbuf[0] == '-') { + switch_say_file(sh, "currency/negativ"); + dollars++; + } + + /* Say dollar amount */ + sv_say_general_count(sh, dollars, say_args); + if (atoi(dollars) == 1) { + switch_say_file(sh, "currency/krona"); + } else { + switch_say_file(sh, "currency/kronor"); + } + + /* Say "and" */ + switch_say_file(sh, "currency/och"); + + /* Say cents */ + if (cents) { + sv_say_general_count(sh, cents, say_args); + if (atoi(cents) == 1) { + switch_say_file(sh, "currency/ore"); + } else { + switch_say_file(sh, "currency/oren"); + } + } else { + switch_say_file(sh, "digits/0"); + switch_say_file(sh, "currency/ore"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t say_ip(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args) +{ + char *a, *b, *c, *d; + switch_status_t status = SWITCH_STATUS_FALSE; + + if (!(a = strdup(tosay))) { + abort(); + } + + if (!(b = strchr(a, '.'))) { + goto end; + } + + *b++ = '\0'; + + if (!(c = strchr(b, '.'))) { + goto end; + } + + *c++ = '\0'; + + if (!(d = strchr(c, '.'))) { + goto end; + } + + *d++ = '\0'; + + say_num(sh, atoi(a), say_args->method); + switch_say_file(sh, "digits/punkt"); + say_num(sh, atoi(b), say_args->method); + switch_say_file(sh, "digits/punkt"); + say_num(sh, atoi(c), say_args->method); + switch_say_file(sh, "digits/punkt"); + say_num(sh, atoi(d), say_args->method); + + end: + + free(a); + + return status; +} + +static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args) +{ + char *p; + + for (p = tosay; p && *p; p++) { + int a = tolower((int) *p); + if (a >= '0' && a <= '9') { + switch_say_file(sh, "digits/%c", a); + } else { + if (say_args->type == SST_NAME_SPELLED) { + switch_say_file(sh, "ascii/%d", a); + } else if (say_args->type == SST_NAME_PHONETIC) { + switch_say_file(sh, "phonetic-ascii/%d", a); + } + } + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args) +{ + switch_new_say_callback_t say_cb = NULL; + + switch (say_args->type) { + case SST_NUMBER: + case SST_ITEMS: + case SST_PERSONS: + case SST_MESSAGES: + say_cb = sv_say_general_count; + break; + case SST_TIME_MEASUREMENT: + case SST_CURRENT_DATE: + case SST_CURRENT_TIME: + case SST_CURRENT_DATE_TIME: + case SST_SHORT_DATE_TIME: + say_cb = sv_say_time; + break; + case SST_IP_ADDRESS: + say_cb = say_ip; + break; + case SST_NAME_SPELLED: + case SST_NAME_PHONETIC: + say_cb = say_spell; + break; + case SST_CURRENCY: + say_cb = sv_say_money; + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type); + break; + } + + return say_cb; +} + +static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr) +{ + switch_say_file_handle_t *sh; + switch_status_t status = SWITCH_STATUS_FALSE; + switch_event_t *var_event = NULL; + + if (session) { + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_channel_get_variables(channel, &var_event); + } + + switch_say_file_handle_create(&sh, say_args->ext, &var_event); + + status = say_cb(sh, tosay, say_args); + + if ((*rstr = switch_say_file_handle_detach_path(sh))) { + status = SWITCH_STATUS_SUCCESS; + } + + switch_say_file_handle_destroy(&sh); + + return status; +} + +static switch_status_t sv_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args) +{ + + switch_new_say_callback_t say_cb = NULL; + char *string = NULL; + + switch_status_t status = SWITCH_STATUS_FALSE; + + say_cb = choose_callback(say_args); + + if (say_cb) { + status = run_callback(say_cb, tosay, say_args, session, &string); + if (session && string) { + status = switch_ivr_play_file(session, NULL, string, args); + } + + switch_safe_free(string); + } + + return status; +} + +static switch_status_t sv_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr) +{ + + switch_new_say_callback_t say_cb = NULL; + char *string = NULL; + + switch_status_t status = SWITCH_STATUS_FALSE; + + say_cb = choose_callback(say_args); + + if (say_cb) { + status = run_callback(say_cb, tosay, say_args, session, &string); + if (string) { + status = SWITCH_STATUS_SUCCESS; + *rstr = string; + } + } + + return status; +} + +SWITCH_MODULE_LOAD_FUNCTION(mod_say_sv_load) +{ + switch_say_interface_t *say_interface; + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE); + say_interface->interface_name = "sv"; + say_interface->say_function = sv_say; + say_interface->say_string_function = sv_say_string; + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */