diff --git a/conf/freeswitch.xml b/conf/freeswitch.xml index 65f6e1812d..42eede31ee 100644 --- a/conf/freeswitch.xml +++ b/conf/freeswitch.xml @@ -52,14 +52,12 @@ <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> diff --git a/conf/lang/de/de.xml b/conf/lang/de/de.xml index 5239489f75..1b44c9a1dd 100644 --- a/conf/lang/de/de.xml +++ b/conf/lang/de/de.xml @@ -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> diff --git a/conf/lang/en/en.xml b/conf/lang/en/en.xml index 6bd5a7d5fb..1e23dc5d7b 100644 --- a/conf/lang/en/en.xml +++ b/conf/lang/en/en.xml @@ -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> diff --git a/conf/lang/fr/fr.xml b/conf/lang/fr/fr.xml index 12bec06f20..eaf00f247e 100644 --- a/conf/lang/fr/fr.xml +++ b/conf/lang/fr/fr.xml @@ -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> diff --git a/conf/lang/he/he.xml b/conf/lang/he/he.xml index 006195bf9a..fe7c5d8a01 100644 --- a/conf/lang/he/he.xml +++ b/conf/lang/he/he.xml @@ -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> diff --git a/conf/lang/ru/ru.xml b/conf/lang/ru/ru.xml index 25d63b6110..686e840860 100644 --- a/conf/lang/ru/ru.xml +++ b/conf/lang/ru/ru.xml @@ -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> diff --git a/src/include/switch_xml.h b/src/include/switch_xml.h index f1164cee2e..2d3f994878 100644 --- a/src/include/switch_xml.h +++ b/src/include/switch_xml.h @@ -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 diff --git a/src/mod/applications/mod_protovm/protovm.conf.xml b/src/mod/applications/mod_protovm/protovm.conf.xml index 3c42ce1faa..e25b8760c8 100644 --- a/src/mod/applications/mod_protovm/protovm.conf.xml +++ b/src/mod/applications/mod_protovm/protovm.conf.xml @@ -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 --> @@ -43,12 +43,12 @@ <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" /> @@ -106,9 +106,9 @@ <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> @@ -116,7 +116,7 @@ <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> @@ -124,7 +124,7 @@ <menu name="std_set_password"> <phrases> - <phrase name="instructions" value="protovm_enter_pass" /> + <phrase name="instructions" value="enter_pass@protovm" /> </phrases> <keys> </keys> diff --git a/src/mod/applications/mod_protovm/sounds.xml b/src/mod/applications/mod_protovm/sounds.xml index 2fe42a40d2..1760e7cc07 100644 --- a/src/mod/applications/mod_protovm/sounds.xml +++ b/src/mod/applications/mod_protovm/sounds.xml @@ -1,375 +1,376 @@ <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> + <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_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> + <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="protovm_disk_quota_exceeded"> - <input> - <match> - <action function="play-file" data="voicemail/vm-mailbox_full.wav"/> - </match> + <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> + + + <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 --> diff --git a/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c b/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c index e58377ef5a..1ac0d38889 100644 --- a/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c +++ b/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c @@ -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 { diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 07c341a580..825f2d30cd 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -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, ¯os, 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; - } - - 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 ((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 (!(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"); + } } - 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 (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); + } + } } - 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"); + if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, ¯os, 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; - } - - 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))) { diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index 6c769ecfd8..76cea5a666 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -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, ¯os, 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 ((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; } - 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; + 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,7 +109,41 @@ 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; + char *macro_name_dup = switch_core_session_strdup(session, macro_name); + const char *group_sound_path; + const char *sound_prefix_enforced_str; + + if ((p = strchr(macro_name_dup, '@'))) { + *p++ = '\0'; + local_macro_name = macro_name_dup; + group_macro_name = p; + + 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; + } + } + /* 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 = 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); @@ -134,23 +151,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio switch_channel_set_variable(channel, "sound_prefix", sound_path); } - 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; - } - - while (macro) { - if ((mname = (char *) switch_xml_attr(macro, "name")) && !strcasecmp(mname, macro_name)) { - break; - } - macro = macro->next; - } - - if (!macro) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macro %s.\n", macro_name); - goto done; - } - 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); } diff --git a/src/switch_xml.c b/src/switch_xml.c index 00f6ddd48e..0ad8768cad 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -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 /*