]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
switch_ivr/xml: Change the structure of the phrases/language system. Previously it...
authorMarc Olivier Chouinard <mochouinard@moctel.com>
Wed, 20 Apr 2011 17:09:03 +0000 (13:09 -0400)
committerMarc Olivier Chouinard <mochouinard@moctel.com>
Wed, 20 Apr 2011 17:09:03 +0000 (13:09 -0400)
You can have sub macros <macros name="voicemail"><macro ...> and allow you to call it login@voicemail.
Change the sound-path to sound-prefix to make it constistant with the rest of freeswitch.
Also allow to set a sound-prefix to a macros, so you can override it for a specific file set.
You can set say-modules="en" or whatever in the <language section to define that say module to use.

13 files changed:
conf/freeswitch.xml
conf/lang/de/de.xml
conf/lang/en/en.xml
conf/lang/fr/fr.xml
conf/lang/he/he.xml
conf/lang/ru/ru.xml
src/include/switch_xml.h
src/mod/applications/mod_protovm/protovm.conf.xml
src/mod/applications/mod_protovm/sounds.xml
src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c
src/switch_ivr.c
src/switch_ivr_play_say.c
src/switch_xml.c

index 65f6e1812d0627b26c8f0cedc028765b5e0edec3..42eede31ee09dfc47d4e89f48ac64b379f5876f8 100644 (file)
     <X-PRE-PROCESS cmd="include" data="directory/*.xml"/>
   </section>
 
-  <!-- phrases section (under development still) -->
-  <section name="phrases" description="Speech Phrase Management">
-    <macros>
-      <X-PRE-PROCESS cmd="include" data="lang/de/*.xml"/>
-      <X-PRE-PROCESS cmd="include" data="lang/en/*.xml"/>
-      <X-PRE-PROCESS cmd="include" data="lang/fr/*.xml"/>
-      <X-PRE-PROCESS cmd="include" data="lang/ru/*.xml"/>
-      <X-PRE-PROCESS cmd="include" data="lang/he/*.xml"/>
-    </macros>
+  <!-- languages section (under development still) -->
+  <section name="languages" description="Language Management">
+    <X-PRE-PROCESS cmd="include" data="lang/de/*.xml"/>
+    <X-PRE-PROCESS cmd="include" data="lang/en/*.xml"/>
+    <X-PRE-PROCESS cmd="include" data="lang/fr/*.xml"/>
+    <X-PRE-PROCESS cmd="include" data="lang/ru/*.xml"/>
+    <X-PRE-PROCESS cmd="include" data="lang/he/*.xml"/>
   </section>
 </document>
index 5239489f75720207cec1d373abf6aa0e1a4af3b1..1b44c9a1ddade3a894dc1bd2e06972f777c06975 100644 (file)
@@ -1,7 +1,11 @@
 <include>
-  <language name="de" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
-    <X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
-    <!--voicemail_de_tts is purely implemented with tts, we need a files based implementation too -->
-    <X-PRE-PROCESS cmd="include" data="vm/tts.xml"/>
+  <language name="de" sound-prefix="/snds" tts-engine="cepstral" tts-voice="david">
+    <phrases>
+      <macros>
+        <X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
+        <!--voicemail_de_tts is purely implemented with tts, we need a files based implementation too -->
+        <X-PRE-PROCESS cmd="include" data="vm/tts.xml"/>
+      </macros>
+    </phrases>
   </language>
 </include>
index 6bd5a7d5fbde5ac4dabe3a2ab07b5a93e66eab38..1e23dc5d7ba3de6aaecfdd052c8867b768308ee4 100644 (file)
@@ -1,8 +1,12 @@
 <include>
-  <language name="en" sound-path="$${sounds_dir}/en/us/callie" tts-engine="cepstral" tts-voice="callie">
-    <X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
-    <!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
-    <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>  <!-- vm/tts.xml if you want to use tts and have cepstral -->
-    <X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>  <!-- dir/tts.xml if you want to use tts and have cepstral -->
+  <language name="en" say-module="en" sound-prefix="$${sounds_dir}/en/us/callie" tts-engine="cepstral" tts-voice="callie">
+    <phrases>
+      <macros>
+        <X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
+        <!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
+        <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>  <!-- vm/tts.xml if you want to use tts and have cepstral -->
+        <X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>  <!-- dir/tts.xml if you want to use tts and have cepstral -->
+      </macros>
+    </phrases>
   </language>
 </include>
index 12bec06f20cebdf844ad2657136673a1698e8a7f..eaf00f247efdb41d4331ce8236cf1154a043f7ed 100644 (file)
@@ -1,8 +1,12 @@
 <include>
-  <language name="fr" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
-    <X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
-    <!--voicemail_fr_tts is purely implemented with tts, we need a files based implementation too -->
-       <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
-       <X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>  <!-- dir/tts.xml if you want to use tts and have cepstral -->
+  <language name="fr" say-module="fr" sound-prefix="$${sounds_dir}/fr/ca/june" tts-engine="cepstral" tts-voice="david">
+    <phrases>
+      <macros>
+        <X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
+        <!--voicemail_fr_tts is purely implemented with tts, we need a files based implementation too -->
+        <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
+        <X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>  <!-- dir/tts.xml if you want to use tts and have cepstral -->
+      </macros>
+    </phrases>
   </language>
 </include>
index 006195bf9a03e411e02009e72b62d150205438e9..fe7c5d8a01076464ac96e0eaeebe2589a734c900 100644 (file)
@@ -1,7 +1,11 @@
 <include>
-  <language name="he" sound-path="$${sounds_dir}/he/daniel" tts-engine="cepstral" tts-voice="daniel">
-    <X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
-    <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
-    <X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>
+  <language name="he" sound-prefix="$${sounds_dir}/he/daniel" tts-engine="cepstral" tts-voice="daniel">
+    <phrases>
+      <macros>
+        <X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
+        <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
+        <X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>
+      </macros>
+    </phrases>
   </language>
 </include>
index 25d63b611012964106a09cf666eb6f6589cbea68..686e84086000ec2f03db9f7e3db1211f1ea975c0 100644 (file)
@@ -1,9 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--тестовые файлы Вы звуковые файлы можно взять тут svn co http://svn.freeswitch.ru/bbv/mod_say_ru/ru/  -->
 <include>
-  <language name="ru" sound-path="$${sounds_dir}/ru/RU/elena" tts-engine="cepstral" tts-voice="elena">
-    <X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
-    <!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
-    <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>  <!-- vm/tts.xml if you want to use tts and have cepstral -->
+  <language name="ru" sound-prefix="$${sounds_dir}/ru/RU/elena" tts-engine="cepstral" tts-voice="elena">
+    <phrases>
+      <macros>
+        <X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
+        <!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
+        <X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>  <!-- vm/tts.xml if you want to use tts and have cepstral -->
+      </macros>
+    </phrases>
   </language>
 </include>
index f1164cee2e9634221067c1101ba264b664c2d96a..2d3f99487815028257df544a56b1099dd80aa986 100644 (file)
@@ -417,6 +417,8 @@ SWITCH_DECLARE(switch_xml_section_t) switch_xml_parse_section_string(_In_opt_z_
 
 SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond);
 
+SWITCH_DECLARE(switch_status_t) switch_xml_locate_language(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language);
+
 SWITCH_END_EXTERN_C
 ///\}
 #endif // _SWITCH_XML_H
index 3c42ce1faab339c3de7f7ffe66dddc6dfc3118b6..e25b8760c864b3785985acf2d069992f2a275b90 100644 (file)
@@ -17,7 +17,7 @@
                <menus>
                        <menu name="std_authenticate">
                        <phrases>
-                               <phrase name="fail_auth" value="protovm_fail_auth" />
+                               <phrase name="fail_auth" value="fail_auth@protovm" />
                        </phrases>
                        <keys>
                        </keys>
@@ -25,7 +25,7 @@
 
                        <menu name="std_authenticate_ask_user">
                        <phrases>
-                               <phrase name="instructions" value="protovm_enter_id" />
+                               <phrase name="instructions" value="enter_id@protovm" />
                        </phrases>
                        <keys>
                                <key dtmf="#" action="ivrengine:terminate_entry" variable="VM-Key-Terminator" /> <!-- TODO Make the ivrengine: parsed and the key configurable -->
@@ -34,7 +34,7 @@
 
                        <menu name="std_authenticate_ask_password">
                        <phrases>
-                               <phrase name="instructions" value="protovm_enter_pass" />
+                               <phrase name="instructions" value="enter_pass@protovm" />
                        </phrases>
                        <keys>
                                <key dtmf="#" action="ivrengine:terminate_entry" variable="VM-Key-Terminator" /> <!-- TODO Make the ivrengine: parsed and the key configurable -->
 
                        <menu name="std_navigator">
                        <phrases>
-                               <phrase name="msg_count" value="protovm_message_count" />
-                               <phrase name="say_date" value="protovm_say_date_event" />
-                               <phrase name="say_msg_number" value="protovm_say_message_number" />
-                               <phrase name="menu_options" value="protovm_listen_file_check" />
-                               <phrase name="ack" value="protovm_ack" />
-                               <phrase name="play_message" value="protovm_play_message" />
+                               <phrase name="msg_count" value="message_count@protovm" />
+                               <phrase name="say_date" value="say_date_event@protovm" />
+                               <phrase name="say_msg_number" value="say_message_number@protovm" />
+                               <phrase name="menu_options" value="listen_file_check@protovm" />
+                               <phrase name="ack" value="ack@protovm" />
+                               <phrase name="play_message" value="play_message@protovm" />
                        </phrases>
                        <keys>
                                <key dtmf="1" action="skip_intro" variable="VM-Key-Main-Listen-File" />
@@ -62,7 +62,7 @@
 
                        <menu name="std_preference">
                        <phrases>
-                               <phrase name="menu_options" value="protovm_config_menu" />
+                               <phrase name="menu_options" value="config_menu@protovm" />
                        </phrases>
                        <keys>
                                <key dtmf="1" action="menu:std_record_greeting_with_slot" variable="VM-Key-Record-Greeting" />
@@ -75,9 +75,9 @@
 
                        <menu name="std_record_greeting">
                        <phrases>
-                               <phrase name="instructions" value="voicemail_record_greeting" />
-                               <phrase name="play_recording" value="protovm_play_recording" />
-                               <phrase name="menu_options" value="protovm_record_file_check" />
+                               <phrase name="instructions" value="record_greeting@protovm" />
+                               <phrase name="play_recording" value="play_recording@protovm" />
+                               <phrase name="menu_options" value="record_file_check@protovm" />
                        </phrases>
                        <keys>
                                <key dtmf="1" action="listen" variable="VM-Key-Listen-File" />
@@ -90,9 +90,9 @@
 
                        <menu name="std_record_name">
                        <phrases>
-                               <phrase name="instructions" value="protovm_record_name" />
-                               <phrase name="play_recording" value="protovm_play_recording" />
-                               <phrase name="menu_options" value="protovm_record_file_check" />
+                               <phrase name="instructions" value="record_name@protovm" />
+                               <phrase name="play_recording" value="play_recording@protovm" />
+                               <phrase name="menu_options" value="record_file_check@protovm" />
                        </phrases>
                        <keys>
                                <key dtmf="1" action="listen" variable="VM-Key-Listen-File" />
 
                        <menu name="std_select_greeting_slot">
                        <phrases>
-                               <phrase name="instructions" value="protovm_choose_greeting" />
-                               <phrase name="invalid_slot" value="protovm_choose_greeting_fail" />
-                               <phrase name="selected_slot" value="protovm_greeting_selected" />
+                               <phrase name="instructions" value="choose_greeting@protovm" />
+                               <phrase name="invalid_slot" value="choose_greeting_fail@protovm" />
+                               <phrase name="selected_slot" value="greeting_selected@protovm" />
                        </phrases>
                        <keys>
                        </keys>
 
                        <menu name="std_record_greeting_with_slot">
                        <phrases>
-                               <phrase name="instructions" value="protovm_choose_greeting" />
+                               <phrase name="instructions" value="choose_greeting@protovm" />
                        </phrases>
                        <keys>
                        </keys>
 
                        <menu name="std_set_password">
                        <phrases>
-                               <phrase name="instructions" value="protovm_enter_pass" />
+                               <phrase name="instructions" value="enter_pass@protovm" />
                        </phrases>
                        <keys>
                        </keys>
index 2fe42a40d2424045a4a0371c0c83abe25d413e6b..1760e7cc0764f7b66b5ff40a34c1058e8c4da305 100644 (file)
 <include><!--This line will be ignored it's here to validate the xml and is optional -->
-  <macro name="protovm_press_key">
-    <input pattern="^(.*):(.*)$">
-      <match>
-       <action function="play-file" data="$2"/>
-       <action function="play-file" data="voicemail/vm-press.wav"/>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_plurial_msg">
-    <input pattern="^[01]:(.*):(.*)$" break_on_match="true">
-      <match>
-       <action function="play-file" data="$1"/>
-      </match>
-    </input>
-    <input pattern="^.*:(.*):(.*)$" break_on_match="true">
-      <match>
-       <action function="play-file" data="$2"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_enter_id">
-    <input pattern="(.+)">
-      <match>
-       <action function="play-file" data="voicemail/vm-enter_id.wav"/>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-      </match>
-      <nomatch>
-       <action function="play-file" data="voicemail/vm-enter_id.wav"/>
-       <action function="say" data="${VM-Key-Terminator}" method="pronounced" type="name_spelled"/>
-      </nomatch>
-  </input>
-  </macro>
-  
-
-  <macro name="protovm_enter_pass">
-    <input pattern="(.+)">
-      <match>
-       <action function="play-file" data="voicemail/vm-enter_pass.wav"/>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-      </match>
-      <nomatch>
-       <action function="play-file" data="voicemail/vm-enter_pass.wav"/>
-       <action function="say" data="${VM-Key-Terminator}" method="pronounced" type="name_spelled"/>
-      </nomatch>
-
-    </input>
-  </macro>
-
-  <macro name="protovm_fail_auth">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-fail_auth.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_hello">
-    <input>
-      <match>
-       <!--<action function="play-file" data="voicemail/vm-hello.wav"/> -->
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_goodbye">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-goodbye.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_abort">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-abort.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_message_count">
-    <input field="${VM-Total-New-Urgent-Messages}" pattern="^(0)$">
-      <nomatch>
-       <action function="play-file" data="voicemail/vm-you_have.wav"/>
-       <action function="say" data="${VM-Total-New-Urgent-Messages}" method="pronounced" type="items"/>
-       <action function="play-file" data="voicemail/vm-urgent-new.wav"/>
-       <action function="phrase" phrase="voicemail_plurial_msg" data="${VM-Total-New-Urgent-Messages}:voicemail/vm-message.wav:voicemail/vm-messages.wav"/>
-      </nomatch>
-    </input>
-    <input field="${VM-Total-New-Messages}" pattern="^(\d+)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-you_have.wav"/>
-       <action function="say" data="${VM-Total-New-Messages}" method="pronounced" type="items"/>
-       <action function="play-file" data="voicemail/vm-new.wav"/>
-       <action function="phrase" phrase="voicemail_plurial_msg" data="${VM-Total-New-Messages}:voicemail/vm-message.wav:voicemail/vm-messages.wav"/>
-      </match>
-    </input>
-    <input field="${VM-Total-Saved-Messages}" pattern="^(0)$">
-      <nomatch>
-       <action function="play-file" data="currency/and.wav"/>
-       <action function="say" data="${VM-Total-Saved-Messages}" method="pronounced" type="items"/>
-       <action function="play-file" data="voicemail/vm-saved.wav"/>
-       <action function="phrase" phrase="voicemail_plurial_msg" data="${VM-Total-Saved-Messages}:voicemail/vm-message.wav:voicemail/vm-messages.wav"/>
-      </nomatch>
-    </input>
-  </macro>
-
-  <macro name="protovm_menu">
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Play-New-Messages}:voicemail/vm-listen_new.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Play-Saved-Messages}:voicemail/vm-listen_saved.wav"/>     
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Config-Menu}:voicemail/vm-advanced.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Terminator}:voicemail/vm-to_exit.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_config_menu">
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Record-Greeting}:voicemail/vm-to_record_greeting.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Choose-Greeting}:voicemail/vm-choose_greeting.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Record-Name}:voicemail/vm-record_name2.wav"/>     
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Change-Password}:voicemail/vm-change_password.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Menu}:voicemail/vm-main_menu.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_record_name">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-record_name1.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_record_file_check">
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Listen-File}:voicemail/vm-listen_to_recording.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Save-File}:voicemail/vm-save_recording.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Record-File}:voicemail/vm-rerecord.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_record_urgent_check">
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Urgent}:voicemail/vm-mark-urgent.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Terminator}:voicemail/vm-continue.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_forward_prepend">
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Prepend}:voicemail/vm-forward_add_intro.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Forward}:voicemail/vm-send_message_now.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_forward_message_enter_extension">
-    <input pattern="^([0-9#*])$">
-      <match>
-       <action function="play-file" data="voicemail/vm-forward_enter_ext.wav"/>
-       <action function="play-file" data="voicemail/vm-followed_by.wav"/>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_invalid_extension">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-that_was_an_invalid_ext.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_listen_file_check">
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Next-Msg}:voicemail/vm-for_next_msg.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Listen-File}:voicemail/vm-listen_to_recording.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Save-File}:voicemail/vm-save_recording.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Delete-File}:voicemail/vm-delete_recording.wav"/>
-     </match>
-    </input>
-    <input field="${VM-Message-Email}" pattern="^$">
-      <nomatch>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Email}:voicemail/vm-forward_to_email.wav"/>
-      </nomatch>
-    </input>
-    <input>
-      <match>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Callback}:voicemail/vm-return_call.wav"/>
-       <action function="phrase" phrase="voicemail_press_key" data="${VM-Key-Main-Forward}:voicemail/vm-to_forward.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_choose_greeting">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-choose_greeting_choose.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_choose_greeting_fail">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-choose_greeting_fail.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_record_greeting">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-record_greeting.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_record_message">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-record_message.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_greeting_selected">
-    <input pattern="^(\d+)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-greeting.wav"/>
-       <action function="say" data="$1" method="pronounced" type="items"/>
-       <action function="play-file" data="voicemail/vm-selected.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_play_greeting">
-    <input pattern="^(.*)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-person.wav"/>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-       <action function="play-file" data="voicemail/vm-not_available.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_say_number">
-    <input pattern="^(\d+)$">
-      <match>
-       <action function="say" data="$1" method="pronounced" type="items"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_say_message_number">
-    <input>
-      <match>
-       <action function="play-file" data="voicemail/vm-${VM-Message-Type}.wav"/> 
-       <action function="play-file" data="voicemail/vm-message_number.wav"/>
-       <action function="say" data="${VM-Message-Number}" method="pronounced" type="items"/> 
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_say_phone_number">
-    <input pattern="^(.*)$">
-      <match>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_say_name">
-    <input pattern="^(.*)$">
-      <match>
-       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
-      </match>
-    </input>
-  </macro>
-  <!-- Note: Update this to marked-urgent,emailed and saved once new sound files are recorded -->
-  <macro name="protovm_ack"> 
-    <input pattern="^(too-small)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-too-small.wav"/>
-      </match>
-    </input>
-    <input pattern="^(undeleted)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-message.wav"/>
-       <action function="play-file" data="voicemail/vm-$1.wav"/>
-      </match>
-    </input>
-    <input pattern="^(deleted)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-message.wav"/>
-       <action function="play-file" data="voicemail/vm-$1.wav"/>
-      </match>
-    </input>
-    <input pattern="^(saved)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-message.wav"/>
-       <action function="play-file" data="voicemail/vm-$1.wav"/>
-      </match>
-    </input>
-    <input pattern="^(emailed)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-message.wav"/>
-       <action function="play-file" data="voicemail/vm-$1.wav"/>
-      </match>
-    </input>
-    <input pattern="^(marked-urgent)$">
-      <match>
-       <action function="play-file" data="voicemail/vm-message.wav"/>
-       <action function="play-file" data="voicemail/vm-$1.wav"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_say_date">
-    <input pattern="^(.*)$">
-      <match>
-       <action function="say" data="$1" method="pronounced" type="short_date_time"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_say_date_event">
-    <input>
-      <match>
-        <action function="say" data="${VM-Message-Received-Epoch}" method="pronounced" type="short_date_time"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_play_message">
-    <input>
-      <match>
-        <action function="play-file" data="${VM-Message-File-Path}"/>
-      </match>
-    </input>
-  </macro>
-
-  <macro name="protovm_play_recording">
-    <input>
-      <match>
-        <action function="play-file" data="${VM-Record-File-Path}"/>
-      </match>
-    </input>
-  </macro>
+  <macros name="protovm" sound-prefix="$${sounds_dir}/fr/ca/june"> 
+    <macro name="press_key">
+      <input pattern="^(.*):(.*)$">
+        <match>
+       <action function="play-file" data="$2"/>
+       <action function="play-file" data="voicemail/vm-press.wav"/>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+        </match>
+      </input>
+    </macro>
   
-  <macro name="protovm_disk_quota_exceeded">
-    <input>
-       <match>
-           <action function="play-file" data="voicemail/vm-mailbox_full.wav"/>
-       </match>
-    </input>
-  </macro>
-
+    <macro name="plurial_msg">
+      <input pattern="^[01]:(.*):(.*)$" break_on_match="true">
+        <match>
+       <action function="play-file" data="$1"/>
+        </match>
+      </input>
+      <input pattern="^.*:(.*):(.*)$" break_on_match="true">
+        <match>
+       <action function="play-file" data="$2"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="enter_id">
+      <input pattern="(.+)">
+        <match>
+       <action function="play-file" data="voicemail/vm-enter_id.wav"/>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+        </match>
+        <nomatch>
+       <action function="play-file" data="voicemail/vm-enter_id.wav"/>
+       <action function="say" data="${VM-Key-Terminator}" method="pronounced" type="name_spelled"/>
+        </nomatch>
+    </input>
+    </macro>
+    
+  
+    <macro name="enter_pass">
+      <input pattern="(.+)">
+        <match>
+       <action function="play-file" data="voicemail/vm-enter_pass.wav"/>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+        </match>
+        <nomatch>
+       <action function="play-file" data="voicemail/vm-enter_pass.wav"/>
+       <action function="say" data="${VM-Key-Terminator}" method="pronounced" type="name_spelled"/>
+        </nomatch>
+  
+      </input>
+    </macro>
+  
+    <macro name="fail_auth">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-fail_auth.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="hello">
+      <input>
+        <match>
+       <!--<action function="play-file" data="voicemail/vm-hello.wav"/> -->
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="goodbye">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-goodbye.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="abort">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-abort.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="message_count">
+      <input field="${VM-Total-New-Urgent-Messages}" pattern="^(0)$">
+        <nomatch>
+       <action function="play-file" data="voicemail/vm-you_have.wav"/>
+       <action function="say" data="${VM-Total-New-Urgent-Messages}" method="pronounced" type="items"/>
+       <action function="play-file" data="voicemail/vm-urgent-new.wav"/>
+       <action function="phrase" phrase="plurial_msg@protovm" data="${VM-Total-New-Urgent-Messages}:voicemail/vm-message.wav:voicemail/vm-messages.wav"/>
+        </nomatch>
+      </input>
+      <input field="${VM-Total-New-Messages}" pattern="^(\d+)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-you_have.wav"/>
+       <action function="say" data="${VM-Total-New-Messages}" method="pronounced" type="items"/>
+       <action function="play-file" data="voicemail/vm-new.wav"/>
+       <action function="phrase" phrase="plurial_msg@protovm" data="${VM-Total-New-Messages}:voicemail/vm-message.wav:voicemail/vm-messages.wav"/>
+        </match>
+      </input>
+      <input field="${VM-Total-Saved-Messages}" pattern="^(0)$">
+        <nomatch>
+       <action function="play-file" data="currency/and.wav"/>
+       <action function="say" data="${VM-Total-Saved-Messages}" method="pronounced" type="items"/>
+       <action function="play-file" data="voicemail/vm-saved.wav"/>
+       <action function="phrase" phrase="plurial_msg@protovm" data="${VM-Total-Saved-Messages}:voicemail/vm-message.wav:voicemail/vm-messages.wav"/>
+        </nomatch>
+      </input>
+    </macro>
+  
+    <macro name="menu">
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Play-New-Messages}:voicemail/vm-listen_new.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Play-Saved-Messages}:voicemail/vm-listen_saved.wav"/>       
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Config-Menu}:voicemail/vm-advanced.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Terminator}:voicemail/vm-to_exit.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="config_menu">
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Record-Greeting}:voicemail/vm-to_record_greeting.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Choose-Greeting}:voicemail/vm-choose_greeting.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Record-Name}:voicemail/vm-record_name2.wav"/>       
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Change-Password}:voicemail/vm-change_password.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Menu}:voicemail/vm-main_menu.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="record_name">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-record_name1.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="record_file_check">
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Listen-File}:voicemail/vm-listen_to_recording.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Save-File}:voicemail/vm-save_recording.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Record-File}:voicemail/vm-rerecord.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="record_urgent_check">
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Urgent}:voicemail/vm-mark-urgent.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Terminator}:voicemail/vm-continue.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="forward_prepend">
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Prepend}:voicemail/vm-forward_add_intro.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Forward}:voicemail/vm-send_message_now.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="forward_message_enter_extension">
+      <input pattern="^([0-9#*])$">
+        <match>
+       <action function="play-file" data="voicemail/vm-forward_enter_ext.wav"/>
+       <action function="play-file" data="voicemail/vm-followed_by.wav"/>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="invalid_extension">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-that_was_an_invalid_ext.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="listen_file_check">
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Next-Msg}:voicemail/vm-for_next_msg.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Listen-File}:voicemail/vm-listen_to_recording.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Save-File}:voicemail/vm-save_recording.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Delete-File}:voicemail/vm-delete_recording.wav"/>
+       </match>
+      </input>
+      <input field="${VM-Message-Email}" pattern="^$">
+        <nomatch>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Email}:voicemail/vm-forward_to_email.wav"/>
+        </nomatch>
+      </input>
+      <input>
+        <match>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Callback}:voicemail/vm-return_call.wav"/>
+       <action function="phrase" phrase="press_key@protovm" data="${VM-Key-Main-Forward}:voicemail/vm-to_forward.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="choose_greeting">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-choose_greeting_choose.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="choose_greeting_fail">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-choose_greeting_fail.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="record_greeting">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-record_greeting.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="record_message">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-record_message.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="greeting_selected">
+      <input pattern="^(\d+)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-greeting.wav"/>
+       <action function="say" data="$1" method="pronounced" type="items"/>
+       <action function="play-file" data="voicemail/vm-selected.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="play_greeting">
+      <input pattern="^(.*)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-person.wav"/>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+       <action function="play-file" data="voicemail/vm-not_available.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="say_number">
+      <input pattern="^(\d+)$">
+        <match>
+       <action function="say" data="$1" method="pronounced" type="items"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="say_message_number">
+      <input>
+        <match>
+       <action function="play-file" data="voicemail/vm-${VM-Message-Type}.wav"/> 
+       <action function="play-file" data="voicemail/vm-message_number.wav"/>
+       <action function="say" data="${VM-Message-Number}" method="pronounced" type="items"/> 
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="say_phone_number">
+      <input pattern="^(.*)$">
+        <match>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="say_name">
+      <input pattern="^(.*)$">
+        <match>
+       <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+        </match>
+      </input>
+    </macro>
+    <!-- Note: Update this to marked-urgent,emailed and saved once new sound files are recorded -->
+    <macro name="ack"> 
+      <input pattern="^(too-small)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-too-small.wav"/>
+        </match>
+      </input>
+      <input pattern="^(undeleted)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-message.wav"/>
+       <action function="play-file" data="voicemail/vm-$1.wav"/>
+        </match>
+      </input>
+      <input pattern="^(deleted)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-message.wav"/>
+       <action function="play-file" data="voicemail/vm-$1.wav"/>
+        </match>
+      </input>
+      <input pattern="^(saved)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-message.wav"/>
+       <action function="play-file" data="voicemail/vm-$1.wav"/>
+        </match>
+      </input>
+      <input pattern="^(emailed)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-message.wav"/>
+       <action function="play-file" data="voicemail/vm-$1.wav"/>
+        </match>
+      </input>
+      <input pattern="^(marked-urgent)$">
+        <match>
+       <action function="play-file" data="voicemail/vm-message.wav"/>
+       <action function="play-file" data="voicemail/vm-$1.wav"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="say_date">
+      <input pattern="^(.*)$">
+        <match>
+       <action function="say" data="$1" method="pronounced" type="short_date_time"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="say_date_event">
+      <input>
+        <match>
+          <action function="say" data="${VM-Message-Received-Epoch}" method="pronounced" type="short_date_time"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="play_message">
+      <input>
+        <match>
+          <action function="play-file" data="${VM-Message-File-Path}"/>
+        </match>
+      </input>
+    </macro>
+  
+    <macro name="play_recording">
+      <input>
+        <match>
+          <action function="play-file" data="${VM-Record-File-Path}"/>
+        </match>
+      </input>
+    </macro>
+    
+    <macro name="disk_quota_exceeded">
+      <input>
+       <match>
+           <action function="play-file" data="voicemail/vm-mailbox_full.wav"/>
+       </match>
+      </input>
+    </macro>
+  </macros>
 </include><!--This line will be ignored it's here to validate the xml and is optional -->
index e58377ef5a7b3b0532ebe46766d916216552a645..1ac0d38889b9a90a2ce2ff344e581839d435a6e1 100644 (file)
@@ -50,7 +50,8 @@ typedef enum {
        XML_LDAP_CONFIG = 0,
        XML_LDAP_DIRECTORY,
        XML_LDAP_DIALPLAN,
-       XML_LDAP_PHRASE
+       XML_LDAP_PHRASE,
+       XML_LDAP_LANGUAGE
 } xml_ldap_query_type_t;
 
 SWITCH_MODULE_LOAD_FUNCTION(mod_xml_ldap_load);
@@ -247,6 +248,8 @@ static switch_xml_t xml_ldap_search(const char *section, const char *tag_name, c
                query_type = XML_LDAP_DIALPLAN;
        } else if (!strcmp(section, "phrases")) {
                query_type = XML_LDAP_PHRASE;
+       } else if (!strcmp(section, "languages")) {
+               query_type = XML_LDAP_LANGUAGE;
        } else {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid section\n");
                return NULL;
@@ -269,6 +272,7 @@ static switch_xml_t xml_ldap_search(const char *section, const char *tag_name, c
 
                                case XML_LDAP_DIALPLAN:
                                case XML_LDAP_PHRASE:
+                               case XML_LDAP_LANGUAGE:
                                        break;
                                }
                        }
@@ -326,6 +330,7 @@ static switch_xml_t xml_ldap_search(const char *section, const char *tag_name, c
                                break;
 
                        case XML_LDAP_PHRASE:
+                       case XML_LDAP_LANGUAGE:
                                break;
                        }
                } else {
index 07c341a580a6da093113bf65a73751e314d59e95..825f2d30cdda8716dd7dc4e46cdc40897c29f54c 100644 (file)
@@ -29,6 +29,7 @@
  * Matt Klein <mklein@nmedia.net>
  * Michael Jerris <mike@jerris.com>
  * Ken Rice <krice at suspicious dot org>
+ * Marc Olivier Chouinard <mochouinard@moctel.com>
  *
  * switch_ivr.c -- IVR Library
  *
@@ -2327,9 +2328,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
        switch_say_interface_t *si;
        switch_channel_t *channel;
        switch_status_t status = SWITCH_STATUS_FALSE;
-       const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *lname = NULL, *sound_path = NULL;
+       const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *sound_path = NULL;
        switch_event_t *hint_data;
-       switch_xml_t cfg, xml = NULL, language, macros;
+       switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL;
        char *p;
 
        switch_assert(session);
@@ -2341,6 +2342,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
        }
 
        if (module_name) {
+               char *p;
                p = switch_core_session_strdup(session, module_name);
                module_name = p;
                
@@ -2371,58 +2373,35 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
        switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang);
        switch_channel_event_set_data(channel, hint_data);
 
-       if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of phrases failed.\n");
+       if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, &macros, chan_lang) != SWITCH_STATUS_SUCCESS) {
                goto done;
        }
 
-       if (!(macros = switch_xml_child(cfg, "macros"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros tag.\n");
-               goto done;
+       if ((p = (char *) switch_xml_attr(language, "say-module"))) {
+               module_name = switch_core_session_strdup(session, p);
+       } else if ((p = (char *) switch_xml_attr(language, "module"))) {
+               module_name = switch_core_session_strdup(session, p);
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n");
+       } else {
+               module_name = chan_lang;
        }
 
-       if (!(language = switch_xml_child(macros, "language"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language tag.\n");
-               goto done;
+       if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) {
+               if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
+                       sound_path = (char *) switch_xml_attr(language, "sound_path");
+               }
        }
 
-       while (language) {
-               if ((lname = (char *) switch_xml_attr(language, "name")) && !strcasecmp(lname, chan_lang)) {
-                       const char *tmp;
-
-                       if ((tmp = switch_xml_attr(language, "module"))) {
-                               module_name = tmp;
+       if (channel) {
+               const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced");
+               if (!switch_true(p)) {
+                       save_path = switch_channel_get_variable(channel, "sound_prefix");
+                       if (sound_path) {
+                               switch_channel_set_variable(channel, "sound_prefix", sound_path);
                        }
-                       break;
                }
-               language = language->next;
-       }
-
-       if (!language) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language %s.\n", chan_lang);
-               goto done;
        }
 
-       if (!module_name) {
-               module_name = chan_lang;
-       }
-
-       if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
-               sound_path = (char *) switch_xml_attr(language, "sound_path");
-       }
-
-       save_path = switch_channel_get_variable(channel, "sound_prefix");
-
-       if (sound_path) {
-               switch_channel_set_variable(channel, "sound_prefix", sound_path);
-               p = switch_core_session_strdup(session, sound_path);
-               sound_path = p;
-       }
-
-       if (xml) {
-               switch_xml_free(xml);
-       }
-       
        if ((si = switch_loadable_module_get_say_interface(module_name))) {
                /* should go back and proto all the say mods to const.... */
                switch_say_args_t say_args = {0};
@@ -2446,7 +2425,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
        if (save_path) {
                switch_channel_set_variable(channel, "sound_prefix", save_path);
        }
-       
+
+       if (xml) {
+               switch_xml_free(xml);
+       }
+
        return status;
 }
 
@@ -2463,9 +2446,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *ses
        switch_say_interface_t *si;
        switch_channel_t *channel = NULL;
        switch_status_t status = SWITCH_STATUS_FALSE;
-       const char *save_path = NULL, *chan_lang = NULL, *lname = NULL, *sound_path = NULL;
+       const char *save_path = NULL, *chan_lang = NULL, *sound_path = NULL;
        switch_event_t *hint_data;
-       switch_xml_t cfg, xml = NULL, language, macros;
+       switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL;
 
        if (session) {
                channel = switch_core_session_get_channel(session);
@@ -2498,52 +2481,31 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *ses
                switch_channel_event_set_data(channel, hint_data);
        }
 
-       if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of phrases failed.\n");
-               goto done;
-       }
-
-       if (!(macros = switch_xml_child(cfg, "macros"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros tag.\n");
+       if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, &macros, chan_lang) != SWITCH_STATUS_SUCCESS) {
                goto done;
        }
 
-       if (!(language = switch_xml_child(macros, "language"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language tag.\n");
-               goto done;
-       }
-
-       while (language) {
-               if ((lname = (char *) switch_xml_attr(language, "name")) && !strcasecmp(lname, chan_lang)) {
-                       const char *tmp;
-
-                       if ((tmp = switch_xml_attr(language, "module"))) {
-                               module_name = tmp;
-                       }
-                       break;
-               }
-               language = language->next;
-       }
-
-       if (!language) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language %s.\n", chan_lang);
-               goto done;
-       }
-
-       if (!module_name) {
+       if ((module_name = switch_xml_attr(language, "say-module"))) {
+       } else if ((module_name = switch_xml_attr(language, "module"))) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n");
+       } else {
                module_name = chan_lang;
        }
 
-       if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
-               sound_path = (char *) switch_xml_attr(language, "sound_path");
+       if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) {
+               if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
+                       sound_path = (char *) switch_xml_attr(language, "sound_path");
+               }
        }
 
        if (channel) {
-               save_path = switch_channel_get_variable(channel, "sound_prefix");
-       }
-
-       if (sound_path && channel) {
-               switch_channel_set_variable(channel, "sound_prefix", sound_path);
+               const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced");  
+               if (!switch_true(p)) {
+                       save_path = switch_channel_get_variable(channel, "sound_prefix");
+                       if (sound_path) {
+                               switch_channel_set_variable(channel, "sound_prefix", sound_path);
+                       }
+               }
        }
 
        if ((si = switch_loadable_module_get_say_interface(module_name))) {
index 6c769ecfd8b07383cec225dbc3ffe3a7838da18b..76cea5a6666a7df628f2b080f7c22e39c0819c9e 100644 (file)
@@ -28,6 +28,7 @@
  * Neal Horman <neal at wanlink dot com>
  * Matt Klein <mklein@nmedia.net>
  * Michael Jerris <mike@jerris.com>
+ * Marc Olivier Chouinard <mochouinard@moctel.com>
  *
  * switch_ivr_play_say.c -- IVR Library (functions to play or say audio)
  *
@@ -39,8 +40,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
                                                                                                                switch_input_args_t *args)
 {
        switch_event_t *hint_data;
-       switch_xml_t cfg, xml = NULL, language, macros, macro, input, action;
-       char *lname = NULL, *mname = NULL;
+       switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL, macro, input, action;
        switch_status_t status = SWITCH_STATUS_GENERR;
        const char *old_sound_prefix = NULL, *sound_path = NULL, *tts_engine = NULL, *tts_voice = NULL;
        const char *module_name = NULL, *chan_lang = NULL;
@@ -49,6 +49,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
        int matches = 0;
        const char *pause_val;
        int pause = 100;
+       const char *group_macro_name = NULL;
+       const char *local_macro_name = macro_name;
+       switch_bool_t sound_prefix_enforced = switch_true(switch_channel_get_variable(channel, "sound_prefix_enforced"));
+       switch_bool_t local_sound_prefix_enforced = SWITCH_FALSE;
 
        if (!macro_name) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No phrase macro specified.\n");
@@ -65,8 +69,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
                chan_lang = lang;
        }
 
-       module_name = chan_lang;
-
        switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
        switch_assert(hint_data);
 
@@ -82,40 +84,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
        }
        switch_channel_event_set_data(channel, hint_data);
 
-       if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of phrases failed.\n");
+       if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, &macros, chan_lang) != SWITCH_STATUS_SUCCESS) {
                goto done;
        }
 
-       if (!(macros = switch_xml_child(cfg, "macros"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros tag.\n");
-               goto done;
-       }
-
-       if (!(language = switch_xml_child(macros, "language"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language tag.\n");
-               goto done;
+       if ((module_name = switch_xml_attr(language, "say-module"))) {
+       } else if ((module_name = switch_xml_attr(language, "module"))) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute. Use say-module instead\n");
+       } else {
+               module_name = chan_lang;
        }
 
-       while (language) {
-               if ((lname = (char *) switch_xml_attr(language, "name")) && !strcasecmp(lname, chan_lang)) {
-                       const char *tmp;
-
-                       if ((tmp = switch_xml_attr(language, "module"))) {
-                               module_name = tmp;
-                       }
-                       break;
+       if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) {
+               if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
+                       sound_path = (char *) switch_xml_attr(language, "sound_path");
                }
-               language = language->next;
-       }
-
-       if (!language) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language %s.\n", chan_lang);
-               goto done;
-       }
-
-       if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
-               sound_path = (char *) switch_xml_attr(language, "sound_path");
        }
 
        if (!(tts_engine = (char *) switch_xml_attr(language, "tts-engine"))) {
@@ -126,31 +109,48 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
                tts_voice = (char *) switch_xml_attr(language, "tts_voice");
        }
 
-       if (sound_path) {
+       /* If we use the new structure, check for a group name */
+       if (language != macros) {
                char *p;
-               old_sound_prefix = switch_str_nil(switch_channel_get_variable(channel, "sound_prefix"));
-               p = switch_core_session_strdup(session, old_sound_prefix);
-               old_sound_prefix = p;
-               switch_channel_set_variable(channel, "sound_prefix", sound_path);
-       }
+               char *macro_name_dup = switch_core_session_strdup(session, macro_name);
+               const char *group_sound_path;
+               const char *sound_prefix_enforced_str;
 
-       if (!(macro = switch_xml_child(language, "macro"))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find any macro tags.\n");
-               goto done;
-       }
+               if ((p = strchr(macro_name_dup, '@'))) {
+                       *p++ = '\0';
+                       local_macro_name = macro_name_dup;
+                       group_macro_name = p;
 
-       while (macro) {
-               if ((mname = (char *) switch_xml_attr(macro, "name")) && !strcasecmp(mname, macro_name)) {
-                       break;
+                       if (!(macros = switch_xml_find_child(phrases, "macros", "name", group_macro_name))) {
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros group %s.\n", group_macro_name);
+                               goto done;
+                       }
                }
-               macro = macro->next;
+               /* Support override of certain language attribute */
+               if ((group_sound_path = (char *) switch_xml_attr(macros, "sound-prefix")) || (group_sound_path = (char *) switch_xml_attr(macros, "sound-path")) || (group_sound_path = (char *) switch_xml_attr(macros, "sound_path"))) {
+                       sound_path = group_sound_path;
+               }
+
+               if (sound_prefix_enforced == SWITCH_FALSE && (sound_prefix_enforced_str = switch_xml_attr(macros, "sound-prefix-enforced"))
+                               && (local_sound_prefix_enforced = switch_true(sound_prefix_enforced_str)) == SWITCH_TRUE) {
+                       switch_channel_set_variable(channel, "sound_prefix_enforced", sound_prefix_enforced_str);
+               }
+
        }
 
-       if (!macro) {
+       if (!(macro = switch_xml_find_child(macros, "macro", "name", local_macro_name))) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macro %s.\n", macro_name);
                goto done;
        }
 
+       if (sound_path && sound_prefix_enforced == SWITCH_FALSE) {
+               char *p;
+               old_sound_prefix = switch_str_nil(switch_channel_get_variable(channel, "sound_prefix"));
+               p = switch_core_session_strdup(session, old_sound_prefix);
+               old_sound_prefix = p;
+               switch_channel_set_variable(channel, "sound_prefix", sound_path);
+       }
+
        if ((pause_val = switch_xml_attr(macro, "pause"))) {
                int tmp = atoi(pause_val);
                if (tmp >= 0) {
@@ -342,6 +342,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
        if (old_sound_prefix) {
                switch_channel_set_variable(channel, "sound_prefix", old_sound_prefix);
        }
+       if (local_sound_prefix_enforced == SWITCH_TRUE) {
+               switch_channel_set_variable(channel, "sound_prefix_enforced", NULL);
+       }
+
        if (xml) {
                switch_xml_free(xml);
        }
index 00f6ddd48e7365050f64a116e7db679fba29b0ad..0ad8768cad3fc3df6018d15514bcd5e4baeec8b3 100644 (file)
@@ -25,7 +25,7 @@
  * 
  * Anthony Minessale II <anthm@freeswitch.org>
  * Simon Capper <skyjunky@sbcglobal.net>
- *
+ * Marc Olivier Chouinard <mochouinard@moctel.com>
  *
  * switch_xml.c -- XML PARSER
  *
@@ -2785,6 +2785,62 @@ SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond) {
        return time_match;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_xml_locate_language(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language) {
+       switch_status_t status = SWITCH_STATUS_FALSE;
+
+       if (switch_xml_locate("languages", NULL, NULL, NULL, root, node, params, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
+               switch_xml_t sub_macros;
+
+               if (switch_xml_locate("phrases", NULL, NULL, NULL, root, node, params, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of languages and phrases failed.\n");
+                       goto done;
+               }
+               if (!(sub_macros = switch_xml_child(*node, "macros"))) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find macros tag.\n");
+                       switch_xml_free(*root);
+                       *root = NULL;
+                       *node = NULL;
+                       goto done;
+               }
+               if (!(*language = switch_xml_find_child(sub_macros, "language", "name", str_language))) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find language %s.\n", str_language);
+                       switch_xml_free(*root);
+                       *root = NULL;
+                       *node = NULL;
+                       goto done;
+               }
+               *macros = *language;
+       } else {
+               if (!(*language = switch_xml_find_child(*node, "language", "name", str_language))) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find language %s.\n", str_language);
+                       switch_xml_free(*root);
+                       *root = NULL;
+                       goto done;
+               }
+               if (!(*phrases = switch_xml_child(*language, "phrases"))) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find phrases tag.\n");
+                       switch_xml_free(*root);
+                       *root = NULL;
+                       *node = NULL;
+                       *language = NULL;
+                       goto done;
+               }
+
+               if (!(*macros = switch_xml_child(*phrases, "macros"))) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find macros tag.\n");
+                       switch_xml_free(*root);
+                       *root = NULL;
+                       *node = NULL;
+                       *language = NULL;
+                       *phrases = NULL;
+                       goto done;
+               }
+       }
+       status = SWITCH_STATUS_SUCCESS;
+
+done:
+       return status;
+}
 
 #ifdef WIN32
 /*