You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(17) |
Dec
(42) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(24) |
Feb
(31) |
Mar
(30) |
Apr
(26) |
May
(44) |
Jun
(40) |
Jul
(17) |
Aug
(10) |
Sep
(15) |
Oct
(4) |
Nov
(7) |
Dec
(1) |
2005 |
Jan
(3) |
Feb
(32) |
Mar
(15) |
Apr
(19) |
May
(51) |
Jun
(31) |
Jul
(18) |
Aug
(3) |
Sep
(3) |
Oct
(11) |
Nov
(17) |
Dec
(21) |
2006 |
Jan
(13) |
Feb
(17) |
Mar
(13) |
Apr
(38) |
May
(10) |
Jun
(6) |
Jul
(9) |
Aug
(16) |
Sep
(12) |
Oct
(17) |
Nov
(7) |
Dec
(18) |
2007 |
Jan
(6) |
Feb
(23) |
Mar
(9) |
Apr
(9) |
May
(7) |
Jun
(12) |
Jul
(16) |
Aug
(36) |
Sep
(17) |
Oct
(13) |
Nov
(11) |
Dec
(10) |
2008 |
Jan
(4) |
Feb
(7) |
Mar
(36) |
Apr
(20) |
May
(9) |
Jun
(4) |
Jul
(19) |
Aug
(14) |
Sep
(7) |
Oct
(3) |
Nov
(12) |
Dec
|
2009 |
Jan
(12) |
Feb
|
Mar
(1) |
Apr
(2) |
May
|
Jun
(61) |
Jul
(27) |
Aug
(20) |
Sep
(17) |
Oct
(29) |
Nov
(4) |
Dec
(4) |
2010 |
Jan
(2) |
Feb
(1) |
Mar
(27) |
Apr
(43) |
May
(62) |
Jun
(61) |
Jul
(50) |
Aug
(50) |
Sep
(20) |
Oct
(9) |
Nov
|
Dec
(1) |
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(3) |
Jun
(5) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2013 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2016 |
Jan
(1) |
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2017 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
(5) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: bright <br...@mi...> - 2017-05-22 12:53:34
|
专业出口到欧美亚马逊仓库,移动电源快递到欧美亚马逊仓库,移动电源空运到欧美亚马逊仓库,移动电源海运到欧美亚马逊仓库专业物流,清关货代. 何为FBA: FBA(英文全名为:Fulfillment by Amazon,是亚马逊提供的代发货业务) 亚马逊目前主要是三块主营业务: 1,Media(即自己的vendors产品的销售提成)、 2,FBA(出租网店+卖流量+分仓租赁+代包装代发货+代收款)、 3,Amazon web services(包括s3\db\aq等产品,可以理解为IDC+CDN加速+个性化建站) 我司可为国内外客户提供良好的:国际快递 、国内外空运、国际海运一条龙、海外仓储.进出口、深港运输 、报关 、报检等各种物流配套服务。多年来公司全体同仁一直致力于发展规律成为国际 的物流企业。 我们可承接:独轮车、平衡车、扭扭车、汽车应急启动电源、充电宝、电子镇流器 逆变器 变压器 电源、电池、纯电池、移动电源、行车记录仪、光盘、自拍杆、吊灯、灯罩、灯饰、台灯、LED灯具、装饰材料、装饰品、建筑材料、工艺品、家具、沙发、餐具、茶几、桌椅、电器、五金、电子产品、数码产品、太阳能板、精密包装盒、平板电脑、手机、带电产品 液体、 粉末、化妆品、食品、机器、蓄电池、电机、马达、压缩机、衣服、鞋子、包包、鼠标、键盘、数据线、U盘、汽车配件、移动电源、手机配件、照相机、DVD 路由器、纯电池、笔记本电池、建材、门窗玻璃、胶水等等;并且我司承诺:从客户委托本公司运输货物开始,我们将对整个运输过程进行24小时监督负责,以确定您的货物以比较短的时间,以低的成本安全运抵目的地。 物流方案我们来帮您设计,运输的难题我们可以帮您解决,提供到欧洲各国的货物、有专线,有特价、有特服。让我们来帮您节省宝贵的金钱和时间。直到把货物完好无损的送到你们客户手中。 我们做物流,我们做的是诚信!您出货或者不出货,服务 在这里,不离不弃;您满意或者不满意,态度 在这里,不折不扣;选择华悦空运让您真正实现低风险,高 安全。货物在中转途中出现的丢货情况华悦公司严格按航空公司IATA的协会航空法履行丢货赔偿事宜。 做亚马逊的所有客户,都明确的知道,亚马逊只是作为一个收货仓库,它并没有真实的收件人去配合清关 交税等等,所以这一块 对选择货代有要求了,选择一个没有清关能力的货代 可能会导致客户的货在目的地扣关,如果不及时解决清关 退回的费用是出口的好几倍,对客户来说 是不少的损失,华悦物流 专注欧美亚马逊双清包税到门服务,凭借着欧美清关良好的代理关系,借助欧美清关公司的实力,大肆的开发着这方面的客户,我们的服务承诺是,清关遇到问题 所属是我司的问题 按照货值进行赔偿,如果是客户低申报 逃税导致的是客户的问题,我司欧美合作清关公司一但收到海关清关通知 会及时的配合海关进行清关,放行后由快递派送到亚马逊仓库。 深圳市民海国际物流有限公司 联系人: 梁亮/Bright 联系电话:18320766890 在线QQ: 327044034 E_MAIL: Br...@mi... 地址:深圳市宝安区福永镇兴华路北创业城A栋305 |
From: bright <b32...@ye...> - 2017-05-15 08:18:40
|
亚马逊FBA头程/海外仓储运输一条龙 · 我们提供亚马逊FBA海空运头程一条龙服务;欧美有自己的大型仓库,可做仓储清关派送(墨西哥能提供RFC)。 · 我们致力于为您的全球出口业务提供便捷式的物流方案; · 我司区别于大多数同行优势之处在于可以给客户提供一条龙门对门的国际物流服务;空运/快递/海运 · 我们即可以帮出口商将货物运送到目的地客户的指定地址,并负责清关,代缴关税。同样地帮国外进商将从中国各城市采购的货物从供应商地址提货,报关,并顺利帮客户清关,代缴关税,与客户约定送货时间,将货物准时送达;目前已帮助大多数客户发到:美国FBA /加拿大FBA/墨西哥、英国FBA/德国FBA/法国FBA/西班牙FBA: 日本FBA;空运到门/快递到门/海运到门任您选择! ·我们只需您一个电话或一封邮件,剩下的交给我们来办,让您有更多的时间和精力发展自己的业务。 1, 一条龙整柜、散货海运到各国FBA仓(美国、英国、德国、加拿大FBA),无需在目的地有公司 2, 一站式空运快递到各国FBA(美国、德国、法国、英国、班牙、意大利、日本、加拿大、墨西哥FBA),无需在目的地有公司 3, 与亚马逊指定卡车公司合作,运费更优惠 4, 提供国外短期仓储。 5, 提供贴唛,分货,托盘服务 6, 提供国外退货到香港运输服务 7, 提供各大港口海运到FBA服务 我们与国外专业的代理及送货公司直接合作,可提供欧州,加拿大,美国亚马逊FBA仓库的货运清关及派送服务。发往AMAZON仓库的货物要求高,AMAZON对于需运往其仓库的运输做了十几条规定。我司和国外代理已将AMAZON仓库规定牢记并付诸于行动,已成功为不少做AMAZON的客户提供货运到门服务 亚马逊FBA头程配送运输 概况 我司利用自身的网络和物流优势,帮助使用亚马逊全球开店项目FBA服务的卖家,将货物从中国运输转运到美国各亚马逊仓库的服务。 深圳市民海国际物流有限公司 联系人: 梁亮/Bright 联系电话:18320766890 在线QQ: 327044034 E_MAIL: Br...@mi... 地址:深圳市宝安区福永镇兴华路北创业城A栋305 |
From: Bright <br...@mi...> - 2017-05-15 07:40:55
|
亚马逊FBA头程/海外仓储运输一条龙 · 我们提供亚马逊FBA海空运头程一条龙服务;欧美有自己的大型仓库,可做仓储清关派送(墨西哥能提供RFC)。 · 我们致力于为您的全球出口业务提供便捷式的物流方案; · 我司区别于大多数同行优势之处在于可以给客户提供一条龙门对门的国际物流服务;空运/快递/海运 · 我们即可以帮出口商将货物运送到目的地客户的指定地址,并负责清关,代缴关税。同样地帮国外进商将从中国各城市采购的货物从供应商地址提货,报关,并顺利帮客户清关,代缴关税,与客户约定送货时间,将货物准时送达;目前已帮助大多数客户发到:美国FBA /加拿大FBA/墨西哥、英国FBA/德国FBA/法国FBA/西班牙FBA: 日本FBA;空运到门/快递到门/海运到门任您选择! ·我们只需您一个电话或一封邮件,剩下的交给我们来办,让您有更多的时间和精力发展自己的业务。 1, 一条龙整柜、散货海运到各国FBA仓(美国、英国、德国、加拿大FBA),无需在目的地有公司 2, 一站式空运快递到各国FBA(美国、德国、法国、英国、班牙、意大利、日本、加拿大、墨西哥FBA),无需在目的地有公司 3, 与亚马逊指定卡车公司合作,运费更优惠 4, 提供国外短期仓储。 5, 提供贴唛,分货,托盘服务 6, 提供国外退货到香港运输服务 7, 提供各大港口海运到FBA服务 我们与国外专业的代理及送货公司直接合作,可提供欧州,加拿大,美国亚马逊FBA仓库的货运清关及派送服务。发往AMAZON仓库的货物要求高,AMAZON对于需运往其仓库的运输做了十几条规定。我司和国外代理已将AMAZON仓库规定牢记并付诸于行动,已成功为不少做AMAZON的客户提供货运到门服务 亚马逊FBA头程配送运输 概况 我司利用自身的网络和物流优势,帮助使用亚马逊全球开店项目FBA服务的卖家,将货物从中国运输转运到美国各亚马逊仓库的服务。 深圳市民海国际物流有限公司 联系人: 梁亮/Bright 联系电话:18320766890 在线QQ: 327044034 E_MAIL: Br...@mi... 地址:深圳市宝安区福永镇兴华路北创业城A栋305 |
From: Bright <br...@mi...> - 2017-05-08 13:00:10
|
专业的亚马逊物流仓储派送货代,专注:英国亚马逊,德国亚马逊,法国亚马逊,意大利亚马逊,加拿大亚马逊,美国亚马逊 清关 派送服务,可做预付关税的一条龙服务,深圳市民海国际物流有限公司.货物经自由贸易区的香港周转.所有出口的货物.可以不用报关不用商检.价格超低!!香港空运包板庄家,年底大货随时订舱,我司在欧洲,中东,非洲,中南美有自己的代理。可以做DDU,DDP 条款,清关+派送+预付关税,真正的一条龙服务。 找一个好的货代合作是小事,也是大事,找我,我能为你很好的解决出口的事儿! 12年的空运、快递操作经验,24小时为您门对门面对面服务,途中破损或丢失100%全赔,50人操作团队24小时为您跟踪,可以从香港飞,内地飞。物流方案我们来帮您设计,运输的难题我们可以帮您解决,提供到欧洲各国的货物、有专线,有特价、有特服。让我们来帮您节省宝贵的金钱和时间。直到把货物完好无损的送到你们指定仓库。 我们做物流,我们做的是诚信!您出货或者不出货,服务就在这里,不离不弃;您满意或者不满意,态度就在这里,不折不扣;选择民海国际让您真正实现0风险,100%安全。货物在中转途中出现的丢货情况民海国际严格按航空公司IATA的协会航空法履行丢货赔偿事宜。 FBA亚马逊头程运输就找深圳市民海国际物流有限公司! 深圳市民海国际物流有限公司 联系人: 梁亮/Bright 联系电话:18320766890 在线QQ: 327044034 E_MAIL: Br...@mi... 地址:深圳市宝安区福永镇兴华路北创业城A栋305 |
From: David P. <nye...@ci...> - 2016-11-04 06:37:20
|
Greetings openvxi http://vertocommunications.com/duck.php?glad=1810au8raxfnzz David |
From: Campobasso <al...@oz...> - 2016-07-07 20:40:23
|
Hello, I think I have a very good news for you, you're gonna be surprised! Read it here please <http://ntawekube.firstjudicialclaims.net/aejcrzp> Good wishes, Campobasso |
From: Antje B. <kl...@at...> - 2016-05-27 12:36:41
|
Hello, Isn't it the information you were looking for? Read about it here <http://spirengecru.kupugani.com/aesyuw> Yours truly, Antje Blumer |
From: David P. <nye...@ri...> - 2016-03-05 12:40:50
|
hi openvxi http://agentjayz.com/vast.php?bear=u1np301pva8su nye...@ya... David Peng |
From: nymnails <nym...@lo...> - 2016-01-23 10:36:31
|
hi openvxi http://user1122701.atservers.net/cake.php?spent=sn11csg8xk3g4r nym...@ya... |
From: prince D. <pri...@ya...> - 2013-10-16 09:03:49
|
Hi, i am currently working on OpenVXI interpretor and I am trying to make it work for multiple calls. But I am struck one one scenario .As OpenVXI is implemented as a synchronous code.For eg. when we run VXIclient with a sample VXML Document consisting of just a "prompt" and "filled" for an input. After playing the prompt it waits for the input and proceeds further only if we supply any input. I am trying to develop an application so that it can work Asynchronously i.e Event based. It should play the message and then return to wait for any other event and when input is supplied it processes the input and processes the answer and takes further action. i tried to segregate the prompt code from input receive code, but was unsuccessful as the code is interwoven in two nested while loops. and any change done hampers the normal working of code. So please suggest any way out for this.So that I can make it asynchronous Thanks in advance Prince |
From: David P. <nye...@ya...> - 2013-02-03 23:59:42
|
Good day! http://jambajuicerecipes.net/tcokn.html David Peng |
From: Anshuman S. R. <ar...@3c...> - 2012-09-17 07:51:00
|
Hi Lauters, I think this will give some pointers -> http://www.w3.org/TR/2003/PR-speech-grammar-20031218/#S2.5.1. Look at the example (in XML format) in this section. From that example, it seems to me that the way to make it work is : <rule id="action" scope="public"> turn <one-of> <item>on</item> <item>off</item> </one-of> </rule> Hope that helps, Anshuman On 9/13/2012 7:09 PM, Lauters Mehdi wrote: > Hi all, > I dond understand everything on the openVXI (3.4, linux/ubuntu) behaviour. > I'm trying to implement a simple vxml grammar to be able to say > > "turn (ON | OFF) the (RED | BLUE) light" but i've got a problem. > > I didn't find how to do it correctly: for example, this simple rule > doesn'work: > > <rule id="action" scope="public"> > <item>turn</item> > <one-of> > <item>on</item> > <item>off</item> > </one-of> > </rule> > > because it fiil the field only if i said "turn" OR "on" OR "off" > But i would like to get the field filled only with "turn on" or "turn off" > > in the same way, the following rule is true if I said "one" OR "two" > instead of "one two". > > <rule id="test" scope="public"> > <item>one</item> > <item>two</item> > </rule> > > Is there a openVXI bug or a vxml error (I checked on specifications, > it seems to be right) > > > This is a the complete grammar file: > > <?xml version="1.0"?> > <!DOCTYPE vxml PUBLIC "-//BeVocal Inc//VoiceXML 1.0//EN" > "http://cafe.bevocal.com/libraries/dtd/vxml1-0-bevocal.dtd"> > <vxml version = "2.1" > > <grammar version="1.0" root="task" > > > > > <rule id="task"> > <ruleref uri="#action" /> > <ruleref uri="#thing" /> > </rule> > > <rule id="action" scope="public"> > <item>turn</item> > <one-of> > <item>on<tag> state = HIGH </tag></item> > <item>off<tag> state = LOW </tag></item> > </one-of> > </rule> > > > <rule id="thing"> > <item>the </item> > <ruleref uri="#color" /> > <item>light</item> > </rule> > > > <rule id="color"> > <one-of> > <item> blue <tag> pin = 12 </tag></item> > <item> red <tag> pin = 13 </tag></item> > <item> green <tag> pin = 11 </tag></item> > <item> yellow <tag> pin = 10 </tag></item> > </one-of> > </rule> > </grammar> > </vxml> > > > Thanks for your advices. > > Regards > > Mehdi > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > > > _______________________________________________ > Openvxi-discuss mailing list > Ope...@li... > https://lists.sourceforge.net/lists/listinfo/openvxi-discuss > > > No virus found in this message. > Checked by AVG - www.avg.com <http://www.avg.com> > Version: 2012.0.2221 / Virus Database: 2437/5266 - Release Date: 09/13/12 > |
From: Lauters M. <meh...@gm...> - 2012-09-13 13:40:26
|
Hi all, I dond understand everything on the openVXI (3.4, linux/ubuntu) behaviour. I'm trying to implement a simple vxml grammar to be able to say "turn (ON | OFF) the (RED | BLUE) light" but i've got a problem. I didn't find how to do it correctly: for example, this simple rule doesn'work: <rule id="action" scope="public"> <item>turn</item> <one-of> <item>on</item> <item>off</item> </one-of> </rule> because it fiil the field only if i said "turn" OR "on" OR "off" But i would like to get the field filled only with "turn on" or "turn off" in the same way, the following rule is true if I said "one" OR "two" instead of "one two". <rule id="test" scope="public"> <item>one</item> <item>two</item> </rule> Is there a openVXI bug or a vxml error (I checked on specifications, it seems to be right) This is a the complete grammar file: <?xml version="1.0"?> <!DOCTYPE vxml PUBLIC "-//BeVocal Inc//VoiceXML 1.0//EN" " http://cafe.bevocal.com/libraries/dtd/vxml1-0-bevocal.dtd"> <vxml version = "2.1" > <grammar version="1.0" root="task" > <rule id="task"> <ruleref uri="#action" /> <ruleref uri="#thing" /> </rule> <rule id="action" scope="public"> <item>turn</item> <one-of> <item>on<tag> state = HIGH </tag></item> <item>off<tag> state = LOW </tag></item> </one-of> </rule> <rule id="thing"> <item>the </item> <ruleref uri="#color" /> <item>light</item> </rule> <rule id="color"> <one-of> <item> blue <tag> pin = 12 </tag></item> <item> red <tag> pin = 13 </tag></item> <item> green <tag> pin = 11 </tag></item> <item> yellow <tag> pin = 10 </tag></item> </one-of> </rule> </grammar> </vxml> Thanks for your advices. Regards Mehdi |
From: Anshuman S. R. <ar...@3c...> - 2012-06-20 07:31:37
|
/****************License************************************************ * Vocalocity OpenVXI * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or * registered trademarks of Vocalocity, Inc. * OpenVXI is a trademark of Scansoft, Inc. and used under license * by Vocalocity. ***********************************************************************/ #include <cstdio> #include <string> #include <cstring> #define VXIstrcmp wcscmp #include <VXIvalue.h> #include <documentparser.hpp> #include <xmlchconverter.hpp> #include <dom/domnodelist.hpp> #include <dom/domnode.hpp> #include <dom/domelement.hpp> #include <pj/log.h> #include <pj/types.h> #include <pjsua-lib/pjsua.h> //#define VXIPROMPT_EXPORTS #include "VXIpromptAPI.h" #include "vxiclientutils.h" #include <VXIclientConfig.h> #include <vxiinet.h> #include <sipPhone.h> #include <sstream> #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 static void samples_to_host(pj_int16_t *samples, unsigned count) { unsigned i; for (i=0; i<count; ++i) { samples[i] = pj_swap16(samples[i]); } } #else # define samples_to_host(samples,count) #endif //keep signature same as wave player #define SIGNATURE PJMEDIA_PORT_SIGNATURE('F', 'P', 'l', 'y') #define ESCAPE_TABLE_SIZE 26 /* Query string for OpenMary TTS */ #define TEXT_PREFIX L"/process?INPUT_TYPE=TEXT&OUTPUT_TYPE=AUDIO&INPUT_TEXT=" #define VOLUME_PREFIX L"&OUTPUT_TEXT=&effect_Volume_selected=on&effect_Volume_parameters=amount%3A" #define VOICE_PREFIX L".0%3B&effect_Volume_default=Default&effect_Volume_help=Help&effect_TractScaler_selected=" \ L"&effect_TractScaler_parameters=amount%3A1.5%3B&effect_TractScaler_default=Default" \ L"&effect_TractScaler_help=Help&effect_F0Scale_selected=&effect_F0Scale_parameters=" \ L"f0Scale%3A2.0%3B&effect_F0Scale_default=Default&effect_F0Scale_help=Help" \ L"&effect_F0Add_selected=&effect_F0Add_parameters=f0Add%3A50.0%3B&effect_F0Add_default=Default" \ L"&effect_F0Add_help=Help&effect_Rate_selected=&effect_Rate_parameters=durScale%3A1.5%3B" \ L"&effect_Rate_default=Default&effect_Rate_help=Help&effect_Robot_selected=" \ L"&effect_Robot_parameters=amount%3A100.0%3B&effect_Robot_default=Default" \ L"&effect_Robot_help=Help&effect_Whisper_selected=&effect_Whisper_parameters=amount%3A100.0%3B" \ L"&effect_Whisper_default=Default&effect_Whisper_help=Help&effect_Stadium_selected=" \ L"&effect_Stadium_parameters=amount%3A100.0&effect_Stadium_default=Default" \ L"&effect_Stadium_help=Help&effect_Chorus_selected=&effect_Chorus_parameters=" \ L"delay1%3A466%3Bamp1%3A0.54%3Bdelay2%3A600%3Bamp2%3A-0.10%3Bdelay3%3A250%3Bamp3%3A0.30" \ L"&effect_Chorus_default=Default&effect_Chorus_help=Help&effect_FIRFilter_selected=" \ L"&effect_FIRFilter_parameters=type%3A3%3Bfc1%3A500.0%3Bfc2%3A2000.0&effect_FIRFilter_default" \ L"=Default&effect_FIRFilter_help=Help&effect_JetPilot_selected=&effect_JetPilot_parameters=" \ L"&effect_JetPilot_default=Default&effect_JetPilot_help=Help&HELP_TEXT=&exampleTexts=" \ L"&VOICE_SELECTIONS=" #define LOCALE_PREFIX L"&AUDIO_OUT=WAVE_FILE&LOCALE=" #define VOICE_PREFIX2 L"&VOICE=" #define AUDIO_TAG L"&AUDIO=WAVE_FILE" // Global for the base diagnostic tag ID // static VXIunsigned gblDiagLogBase = 0; // Globals for TTS server static vxistring gblTTSserver = L""; static vxistring gblTTSVoice = L"dfki-prudence-hsmm en_GB female hmm"; static vxistring gblTTSVoiceType = L"dfki-prudence-hsmm"; static vxistring gblTTSspchLang = L"en_GB"; //default static vxistring gblTTSspchVol = L"1"; // Constants for diagnostic logging tags // static const VXIunsigned DIAG_TAG_PROMPTING = 1; static const VXIunsigned DIAG_TAG_PREFETCHING = 2; // VXIprompt implementation of the VXIprompt interface // extern "C" { struct voice_details { bool valid; vxistring pvalue; vxistring name; vxistring lang; vxistring gender; VXIint32 age; VXIint32 variant; }; struct prompt_details { // This must be the first member declared in the struct! PJ_DECL_LIST_MEMBER(struct prompt_details); vxistring src; vxistring mark; vxistring pvalue; VXIContent *vxicontent; pj_bool_t is_filler; pj_time_val play_start_time; VXIlong min_play_msec; pj_bool_t bargein_allowed; VXIint fetch_timeout; VXIint max_age; VXIint max_stale; struct voice_details voice; }; struct prompt_sess_list { // This must be the first member declared in the struct! PJ_DECL_LIST_MEMBER(struct prompt_sess_list); struct VXIpromptImpl* impl; }; struct VXIpromptImpl { // Base interface, must be first VXIpromptInterfaceEx intf; // Log interface for this resource VXIlogInterface *log; // Internet fetch interface for this resource VXIinetInterface *inet; // call on which prompts will be played pjsua_call_id call_id; //lock for synchronizing various operations pj_mutex_t* obj_lock; //list of files which have been queued struct prompt_details queued_files; // list of streams to be played struct prompt_details play_files; //entry pointing to the currently playing file struct prompt_details *current_pfile; // player for the currently playig file pjsua_player_id player_id; // lock indicating if play is in progress pj_sem_t* play_lock; // result of the play operation VXIpromptResult play_result; //timer for stopping filler pj_timer_entry stop_filler_timer; //memory pool for this prompt resource pj_pool_t* pool; // flag which indicates if the resource has been stopped pj_bool_t stop; // flag which indicates if play next event is pending pj_bool_t event_pending; // request to play next file struct prompt_sess_list next_file_req; }; struct file_reader_port { pjmedia_port base; unsigned options; pjmedia_wave_fmt_tag fmt_tag; pj_uint16_t bytes_per_sample; pj_bool_t eof; pj_size_t bufsize; char *buf; char *readpos; char *eofpos; pj_off_t fsize; unsigned start_data; unsigned data_len; unsigned data_left; pj_off_t fpos; pj_oshandle_t fd; pj_status_t (*cb)(pjmedia_port*, void*); VXIMap *props; VXIpromptImpl *impl; }; } // thread for destroying unused players static pj_thread_t *play_next_thread; static pj_mutex_t *plist_mutex; static struct prompt_sess_list sessions; static pj_sem_t *player_sem; static pj_pool_t *gbl_prompt_pool; static pj_status_t vxi_strmplayer_port_create( VXIpromptImpl *impl, VXIinetStream *strm, VXIMap* props, pjmedia_port **p_port ); static VXIpromptResult PlayFileEntry(VXIpromptImpl *impl,struct prompt_details *prompt); static pj_status_t onPlayFileComplete( pjmedia_port *port, void *usr_data ); static VXIpromptResult PlayLocalFile(VXIpromptImpl *impl,char *filename); static VXIpromptResult PlayFileFromStream(VXIpromptImpl *impl,char *filename,VXIinetStream *stream, VXIMap *strmprops); static VXIpromptResult PlayBuffer(VXIpromptImpl *impl, VXIbyte *content, VXIulong contentlen); static VXIinetResult read_stream(file_reader_port* fport, VXIbyte* buf, VXIulong size_to_read, VXIulong* size_read); static VXIinetResult skip_stream(file_reader_port* fport, VXIulong size_to_read ); static pj_status_t strm_get_frame(pjmedia_port *this_port, pjmedia_frame *frame); static pj_status_t strm_on_destroy(pjmedia_port *this_port); static pj_status_t fill_port_buffer(struct file_reader_port *fport); static VXIpromptResult StopFiller(VXIpromptImpl *impl); static VXIpromptResult VXIpromptGetFilePlayTime (VXIpromptInterfaceEx *prompt, VXIlong* remainingTime); static VXIchar escape_char_table[ESCAPE_TABLE_SIZE][2] = { L" ", L"<", L">", L"+", L"#", L"$", L"%", L"&", L"@", L"`", L":", L"[", L"]", L"{", L"}", L"\"", L"+", L"/", L";", L"=", L"?", L"\\", L"^", L"|", L"'", L",", }; static VXIchar escape_char_value[ESCAPE_TABLE_SIZE][4] = { L"%20", L"%3C", L"%3E", L"%2B", L"%23", L"%24", L"%25", L"%26", L"%40", L"%60", L"%3A", L"%5B", L"%5D", L"%7B", L"%7D", L"%22", L"%2B", L"%2F", L"%3B", L"%3D", L"%3F", L"%5C", L"%5E", L"%7C", L"%27", L"%2C", }; static pj_status_t strm_get_frame(pjmedia_port *this_port, pjmedia_frame *frame) { struct file_reader_port *fport = (struct file_reader_port*)this_port; unsigned frame_size; pj_status_t status; pj_assert(fport->base.info.signature == SIGNATURE); pj_assert(frame->size <= fport->bufsize); /* EOF is set and readpos already passed the eofpos */ if (fport->eof && fport->readpos >= fport->eofpos) { pj_status_t status = PJ_SUCCESS; /*PJ_LOG(5,(THIS_FILE, "File port %.*s EOF", (int)fport->base.info.name.slen, fport->base.info.name.ptr));*/ /* Call callback, if any */ if (fport->cb) status = (*fport->cb)(this_port, fport->base.port_data.pdata); /* If callback returns non PJ_SUCCESS or 'no loop' is specified, * return immediately (and don't try to access player port since * it might have been destroyed by the callback). */ if ((status != PJ_SUCCESS) || (fport->options & PJMEDIA_FILE_NO_LOOP)) { frame->type = PJMEDIA_FRAME_TYPE_NONE; frame->size = 0; return PJ_EEOF; } /*PJ_LOG(5,(THIS_FILE, "File port %.*s rewinding..", (int)fport->base.info.name.slen, fport->base.info.name.ptr));*/ fport->eof = PJ_FALSE; } //pj_assert(frame->size == fport->base.info.bytes_per_frame); if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_PCM) { frame_size = frame->size; //frame->size = frame_size; } else { /* Must be ULAW or ALAW */ pj_assert(fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW || fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ALAW); frame_size = frame->size >> 1; frame->size = frame_size << 1; } /* Copy frame from buffer. */ frame->type = PJMEDIA_FRAME_TYPE_AUDIO; frame->timestamp.u64 = 0; if ((fport->readpos + frame_size) <= (fport->buf + fport->bufsize)) { /* Read contiguous buffer. */ pj_memcpy(frame->buf, fport->readpos, frame_size); /* Fill up the buffer if all has been read. */ fport->readpos += frame_size; if (fport->readpos == fport->buf + fport->bufsize) { fport->readpos = fport->buf; status = fill_port_buffer(fport); if (status != PJ_SUCCESS) { frame->type = PJMEDIA_FRAME_TYPE_NONE; frame->size = 0; fport->readpos = fport->buf + fport->bufsize; return status; } } } else { unsigned endread; /* Split read. * First stage: read until end of buffer. */ endread = (fport->buf+fport->bufsize) - fport->readpos; pj_memcpy(frame->buf, fport->readpos, endread); /* End Of Buffer and EOF and NO LOOP */ if (fport->eof && (fport->options & PJMEDIA_FILE_NO_LOOP)) { fport->readpos += endread; if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_PCM) { pj_bzero((char*)frame->buf + endread, frame_size - endread); } else if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW) { int val = pjmedia_linear2ulaw(0); pj_memset((char*)frame->buf + endread, val, frame_size - endread); } else if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ALAW) { int val = pjmedia_linear2alaw(0); pj_memset((char*)frame->buf + endread, val, frame_size - endread); } return PJ_SUCCESS; } /* Second stage: fill up buffer, and read from the start of buffer. */ status = fill_port_buffer(fport); if (status != PJ_SUCCESS) { frame->type = PJMEDIA_FRAME_TYPE_NONE; frame->size = 0; fport->readpos = fport->buf + fport->bufsize; return status; } pj_memcpy(((char*)frame->buf)+endread, fport->buf, frame_size-endread); fport->readpos = fport->buf + (frame_size - endread); } if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW || fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ALAW) { unsigned i; pj_uint16_t *dst; pj_uint8_t *src; dst = (pj_uint16_t*)frame->buf + frame_size - 1; src = (pj_uint8_t*)frame->buf + frame_size - 1; if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW) { for (i = 0; i < frame_size; ++i) { *dst-- = (pj_uint16_t) pjmedia_ulaw2linear(*src--); } } else { for (i = 0; i < frame_size; ++i) { *dst-- = (pj_uint16_t) pjmedia_alaw2linear(*src--); } } } return PJ_SUCCESS; } static pj_status_t strm_on_destroy(pjmedia_port *this_port) { struct file_reader_port *fport = (struct file_reader_port*) this_port; VXIpromptImpl *impl = fport->impl; VXIinetStream *strm = (VXIinetStream *) fport->fd; pj_assert(this_port->info.signature == SIGNATURE); impl->inet->Close(impl->inet, &strm); return PJ_SUCCESS; } static VXIinetResult skip_stream(file_reader_port* fport, VXIulong size_to_skip ) { VXIbyte *buf; VXIulong size_read = 0; VXIinetResult result = VXIinet_RESULT_SUCCESS; if (size_to_skip < 0) return VXIinet_RESULT_INVALID_ARGUMENT; buf = new VXIbyte[size_to_skip]; result = read_stream( fport, buf, size_to_skip, &size_read); if ( (result == VXIinet_RESULT_SUCCESS) && (size_read != size_to_skip)) result = VXIinet_RESULT_END_OF_STREAM; delete buf; return result; } // A few conversion functions... static inline VXIpromptImpl * ToVXIpromptImpl(VXIpromptInterface * i) { return reinterpret_cast<VXIpromptImpl *>(i); } static inline VXIpromptImpl * ToVXIpromptImpl(VXIpromptInterfaceEx * i) { return reinterpret_cast<VXIpromptImpl *>(i); } /******************************************************* * * Utility functions * *******************************************************/ /** * Log an error */ static VXIlogResult Error(VXIpromptImpl *impl, VXIunsigned errorID, const VXIchar *format, ...) { VXIlogResult rc; va_list arguments; if ((! impl) || (! impl->log)) return VXIlog_RESULT_NON_FATAL_ERROR; if (format) { va_start(arguments, format); rc = (*impl->log->VError)(impl->log, COMPANY_DOMAIN L".VXIprompt", errorID, format, arguments); va_end(arguments); } else { rc = (*impl->log->Error)(impl->log, COMPANY_DOMAIN L".VXIprompt", errorID, NULL); } return rc; } /** * Log a diagnostic message */ static VXIlogResult Diag(VXIpromptImpl *impl, VXIunsigned tag, const VXIchar *subtag, const VXIchar *format, ...) { VXIlogResult rc; va_list arguments; if ((! impl) || (! impl->log)) return VXIlog_RESULT_NON_FATAL_ERROR; if (format) { va_start(arguments, format); rc = (*impl->log->VDiagnostic)(impl->log, tag + gblDiagLogBase, subtag, format, arguments); va_end(arguments); } else { rc = (*impl->log->Diagnostic)(impl->log, tag + gblDiagLogBase, subtag, NULL); } return rc; } static VXIinetResult read_stream(file_reader_port* fport, VXIbyte* buf, VXIulong size_to_read, VXIulong* size_read) { VXIpromptImpl *impl = fport->impl; VXIinetStream *strm = (VXIinetStream *) fport->fd; VXIinetResult result; result = impl->inet->Read( impl->inet, buf, size_to_read, size_read, strm); if ( result != VXIinet_RESULT_SUCCESS) { return result; } else { fport->fpos += *size_read; } return VXIinet_RESULT_SUCCESS; } static VXIchar* EscapeString(vxistring &str) { int i = 0; vxistring tempstr = L""; vxistring::size_type len = str.length(); if (len == 0) return NULL; for (i = 0; i < len; i++) { if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')) { tempstr += str[i]; continue; } else { //Search if this char needs to be escaped int j = 0; for (j = 0; j < ESCAPE_TABLE_SIZE; j++) { if (escape_char_table[j][0] == str[i]) break; } if (j < ESCAPE_TABLE_SIZE) tempstr += escape_char_value[j]; else tempstr += str[i]; } } str = tempstr.c_str(); return (VXIchar*)str.c_str(); } static void PruneWhitespace(vxistring &str) { vxistring::size_type len = str.length(); if (len == 0) return; // Convert all whitespace to spaces. unsigned int i; for (i = 0; i < len; ++i) { if (str[i] == '\r' || str[i] == '\n' || str[i] == '\t') str[i] = ' '; } // Eliminate trailing and double spaces bool lastWasSpace = true; for (i = len; i > 0; --i) { if (str[i-1] != ' ') { lastWasSpace = false; continue; } if (lastWasSpace) str.erase(i-1, 1); else lastWasSpace = true; } // Eliminate space at very beginning. if (str[0] == ' ') str.erase(0, 1); } /******************************************************* * * Method routines for VXIpromptInterface structure * *******************************************************/ // Get the VXIprompt interface version supported // static VXIint32 VXIpromptGetVersion(void) { return VXI_CURRENT_VERSION; } // Get the implementation name // static const VXIchar* VXIpromptGetImplementationName(void) { static const VXIchar IMPLEMENTATION_NAME[] = COMPANY_DOMAIN L".VXIprompt"; return IMPLEMENTATION_NAME; } // Begin a session // static VXIpromptResult VXIpromptBeginSession(VXIpromptInterface * pThis, VXIMap *pProps) { VXIpromptImpl *impl = ToVXIpromptImpl(pThis); VXIulong tempLong; //store the call id for this session // Get call num property GetVXIULong(pProps, CLIENT_CURRENT_NUMCALL, &tempLong); impl->call_id =tempLong; Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Session begin for call id %d",impl->call_id); pj_timer_entry_init(&impl->stop_filler_timer, -1, NULL, NULL); pj_list_init(&impl->play_files); pj_list_init(&impl->queued_files); impl->current_pfile = NULL; impl->play_result = VXIprompt_RESULT_SUCCESS; impl->player_id = PJSUA_INVALID_ID; impl->stop = PJ_FALSE; impl->event_pending = PJ_FALSE; pj_list_init(&impl->next_file_req); impl->pool = pjsua_pool_create("prompt%p", 4000,4000); if (impl->pool == NULL) return VXIprompt_RESULT_OUT_OF_MEMORY; pj_sem_create(impl->pool,"prompt",1,1,&impl->play_lock); return VXIprompt_RESULT_SUCCESS; } static void clean_list(struct prompt_details *lst) { struct prompt_details *it = NULL; if (lst) { it = lst->next; while ( it != lst) { it->src.~vxistring(); it = it->next; } pj_list_init(lst); } } // End a session // static VXIpromptResult VXIpromptEndSession(VXIpromptInterface *pThis, VXIMap *) { VXIpromptImpl *impl = ToVXIpromptImpl(pThis); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Session end for call id %d %p",impl->call_id, impl); if (impl->event_pending == PJ_TRUE) { struct prompt_sess_list *it; pj_mutex_lock(plist_mutex); it = sessions.next; Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Number of pending play requests %d",pj_list_size(&sessions)); while(it != &sessions) { if (impl == it->impl) { pj_list_erase(it); } it = sessions.next; } pj_mutex_unlock(plist_mutex); } impl->event_pending = PJ_FALSE; pj_mutex_lock(impl->obj_lock); impl->call_id = PJSUA_INVALID_ID; impl->current_pfile = NULL; clean_list(&impl->play_files); clean_list(&impl->queued_files); impl->play_result = VXIprompt_RESULT_SUCCESS; if (impl->player_id != PJSUA_INVALID_ID) { pjmedia_port *port =NULL; pjsua_player_get_port(impl->player_id,&port); pjmedia_wav_player_set_eof_cb(port,NULL,NULL); impl->player_id = PJSUA_INVALID_ID; } if ( impl->stop_filler_timer.id != PJSUA_INVALID_ID) { pjsip_endpt_cancel_timer(pjsua_var.endpt, &impl->stop_filler_timer); } pj_sem_destroy(impl->play_lock); pj_pool_release(impl->pool); pj_mutex_unlock(impl->obj_lock); return VXIprompt_RESULT_SUCCESS; } static void getFetchAttrs(struct prompt_details *prompt, VXIMap *map) { VXIInteger * val = NULL; if (prompt->fetch_timeout >0) { val = VXIIntegerCreate(prompt->fetch_timeout); if (val != NULL){ VXIMapSetProperty(map,INET_TIMEOUT_DOWNLOAD, reinterpret_cast<VXIValue*>(val)); } } if ( prompt->max_age > 0){ val = VXIIntegerCreate(prompt->max_age); if (val != NULL){ VXIMapSetProperty(map,INET_CACHE_CONTROL_MAX_AGE, reinterpret_cast<VXIValue*>(val)); } } if ( prompt->max_stale > 0){ val = VXIIntegerCreate(prompt->max_stale); if (val != NULL){ VXIMapSetProperty(map,INET_CACHE_CONTROL_MAX_STALE, reinterpret_cast<VXIValue*>(val)); } } } static VXIpromptResult PlayFileEntry(VXIpromptImpl *impl,struct prompt_details *prompt) { VXIinetStream *stream = NULL; VXIMapHolder streamInfo; VXIMapHolder fetchInfo; VXIinetResult open_result; vxistring filename = prompt->src; VXIContent *vxicontent = prompt->vxicontent; struct voice_details voice = prompt->voice; char fname[255]; if (filename.c_str() && (wcscmp(filename.c_str(), L"") != 0)) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing prompt src %s",filename.c_str()); getFetchAttrs(prompt, fetchInfo.GetValue()); open_result = impl->inet->Open(impl->inet,L"prompt",filename.c_str(),INET_MODE_READ,0,fetchInfo.GetValue(),streamInfo.GetValue(),&stream); if (open_result != VXIinet_RESULT_SUCCESS) { return VXIprompt_RESULT_FETCH_ERROR; } if (stream) { vxistring diagUri(filename); const VXIValue * val = NULL; VXIint32 file_source =0; //check the file source . use direct pjsip api for local files GetVXIInt(streamInfo.GetValue(), INET_INFO_DATA_SOURCE,&file_source); val = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_ABSOLUTE_NAME); if (val != NULL && VXIValueGetType(val) == VALUE_STRING) diagUri = VXIStringCStr(reinterpret_cast<const VXIString *>(val)); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing prompt file %s", diagUri.c_str()); wchar2char(fname, diagUri.c_str(), 255); if ( file_source == INET_DATA_SOURCE_FILE) { impl->inet->Close(impl->inet,&stream); return PlayLocalFile(impl, fname); } else { return PlayFileFromStream(impl, fname, stream, streamInfo.GetValue()); } } } else if (vxicontent) { VXIchar *contentType = NULL; VXIbyte *waveform = NULL; VXIulong len = 0; VXIvalueResult result; if ((result = VXIContentValue(vxicontent, (const VXIchar**)&contentType, (const VXIbyte**)&waveform, &len)) == VXIvalue_RESULT_SUCCESS) { return PlayBuffer(impl, waveform, len); } else { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Error playing buffer %s: %d", prompt->mark.c_str(), result); return (VXIpromptResult)result; } } else if (voice.valid) { const VXIchar *ttsstr = NULL; const VXIchar *ttsserver = gblTTSserver.c_str(); vxistring voiceName = gblTTSVoice.c_str(); vxistring voiceType = gblTTSVoiceType.c_str(); vxistring lang = gblTTSspchLang.c_str(); if (ttsserver == NULL || wcslen(ttsserver) <= 0) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"TTS disabled"); return VXIprompt_RESULT_SYSTEM_ERROR; } PruneWhitespace(voice.pvalue); ttsstr = EscapeString(voice.pvalue); PruneWhitespace(voice.name); if (voice.name.length() > 0) { voiceName = voice.name.c_str(); /* * Extract voice type from voice name. * Specific for OpenMary TTS only. */ const VXIchar *temp = voice.name.c_str(); voiceType = wcstok((wchar_t*)temp, L" "); } PruneWhitespace(voice.lang); if (voice.lang.length() > 0) { lang = voice.lang.c_str(); } vxistring querystr = L"http://"; querystr += ttsserver; querystr += TEXT_PREFIX; querystr += ttsstr; querystr += VOLUME_PREFIX; querystr += gblTTSspchVol.c_str(); querystr += VOICE_PREFIX; querystr += EscapeString(voiceName); querystr += LOCALE_PREFIX; querystr += EscapeString(lang); querystr += VOICE_PREFIX2; querystr += EscapeString(voiceType); querystr += AUDIO_TAG; Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing prompt src %s",querystr.c_str()); getFetchAttrs(prompt, fetchInfo.GetValue()); open_result = impl->inet->Open(impl->inet,L"prompt",querystr.c_str(),INET_MODE_READ,0,fetchInfo.GetValue(),streamInfo.GetValue(),&stream); if (open_result != VXIinet_RESULT_SUCCESS) { return VXIprompt_RESULT_FETCH_ERROR; } if (stream) { return PlayFileFromStream(impl, NULL, stream, streamInfo.GetValue()); } } else if (!prompt->pvalue.empty()) { const VXIchar *ttsstr = NULL; const VXIchar *ttsserver = gblTTSserver.c_str(); if (ttsserver == NULL || wcslen(ttsserver) <= 0) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"TTS disabled"); return VXIprompt_RESULT_SYSTEM_ERROR; } PruneWhitespace(prompt->pvalue); ttsstr = EscapeString(prompt->pvalue); vxistring querystr = L"http://"; querystr += ttsserver; querystr += TEXT_PREFIX; querystr += ttsstr; querystr += VOLUME_PREFIX; querystr += gblTTSspchVol.c_str(); querystr += VOICE_PREFIX; querystr += EscapeString(gblTTSVoice); querystr += LOCALE_PREFIX; querystr += EscapeString(gblTTSspchLang); querystr += VOICE_PREFIX2; querystr += EscapeString(gblTTSVoiceType); querystr += AUDIO_TAG; Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing prompt src %s",querystr.c_str()); getFetchAttrs(prompt, fetchInfo.GetValue()); open_result = impl->inet->Open(impl->inet,L"prompt",querystr.c_str(),INET_MODE_READ,0,fetchInfo.GetValue(),streamInfo.GetValue(),&stream); if (open_result != VXIinet_RESULT_SUCCESS) { return VXIprompt_RESULT_FETCH_ERROR; } if (stream) { return PlayFileFromStream(impl, NULL, stream, streamInfo.GetValue()); } } return VXIprompt_RESULT_SUCCESS; } static pj_status_t onPlayFileComplete( pjmedia_port *port, void *usr_data ) { VXIpromptImpl *impl =reinterpret_cast<VXIpromptImpl *>(usr_data); struct prompt_sess_list *entry = NULL; //reset the callback pjmedia_wav_player_set_eof_cb(port,NULL,NULL); entry = &impl->next_file_req; entry->impl= impl; pj_mutex_lock(plist_mutex); if (pj_list_find_node(&sessions, entry) == NULL) { impl->event_pending = PJ_TRUE; pj_list_push_back(&sessions,entry); pj_mutex_unlock(plist_mutex); pj_sem_post(player_sem); } else { pj_mutex_unlock(plist_mutex); } return PJ_SUCCESS; } static pj_status_t PlayNextFile(VXIpromptImpl *impl) { struct prompt_details *it; VXIpromptResult ret; pj_mutex_lock(impl->obj_lock); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing next file for callid %d %p", impl->call_id, impl); if (impl->current_pfile == NULL || (impl->current_pfile->next == NULL || pj_list_find_node(&impl->play_files, impl->current_pfile->next) == NULL)) { pj_sem_trywait(impl->play_lock); pj_sem_post(impl->play_lock); pj_mutex_unlock(impl->obj_lock); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Error playing next file for callid %d %p", impl->call_id, impl); return PJ_SUCCESS; } pjsua_player_destroy(impl->player_id); impl->player_id = PJSUA_INVALID_ID; it = impl->current_pfile->next; /* check if we already are at end of the list * or stop has been requested */ if ( (impl->stop == PJ_TRUE)||it == &impl->play_files) { pj_list_init(&impl->play_files); impl->current_pfile = NULL; pj_sem_post(impl->play_lock); //stop has been processed impl->stop = PJ_FALSE; pj_mutex_unlock(impl->obj_lock); return PJ_SUCCESS; } while ( it != &impl->play_files) { //play remaining entries if ( (ret = PlayFileEntry(impl,it)) == VXIprompt_RESULT_SUCCESS) { //successfully playing file impl->current_pfile = it; //store the play start time in the entry pj_gettimeofday(&impl->current_pfile->play_start_time); break; } if ( (ret < impl->play_result)||(ret>0 && impl->play_result == VXIprompt_RESULT_SUCCESS )) impl->play_result = ret; it = it->next; } //check if we have finished all list entries if ( it == &impl->play_files && ret != VXIprompt_RESULT_SUCCESS) { pj_list_init(&impl->play_files); impl->current_pfile = NULL; pj_sem_post(impl->play_lock); pj_mutex_unlock(impl->obj_lock); return PJ_SUCCESS; } pj_mutex_unlock(impl->obj_lock); return PJ_SUCCESS; } static VXIpromptResult PlayLocalFile(VXIpromptImpl *impl,char *filename) { pj_status_t ret; ret = sipPhone::_PlayFile(impl->call_id,filename,PJ_FALSE,PJ_FALSE,impl,onPlayFileComplete,&impl->player_id); if ( ret != PJ_SUCCESS) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Failed to play local file %d",ret); return VXIprompt_RESULT_PLATFORM_ERROR; } return VXIprompt_RESULT_SUCCESS; } static VXIpromptResult PlayBuffer(VXIpromptImpl *impl, VXIbyte *content, VXIulong contentlen) { pj_status_t ret; //ret = sipPhone::_PlayFile(impl->call_id,filename,PJ_FALSE,PJ_FALSE,impl,onPlayFileComplete,&impl->player_id); ret = sipPhone::getInstance().PlayBuffer(impl->call_id, (char*)content, (int)contentlen, PJ_FALSE, PJ_FALSE, impl, onPlayFileComplete, &impl->player_id); if (ret != PJ_SUCCESS) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Failed to play buffer file %d",ret); return VXIprompt_RESULT_PLATFORM_ERROR; } return VXIprompt_RESULT_SUCCESS; } static pj_status_t fill_port_buffer(struct file_reader_port *fport) { pj_ssize_t size_left = fport->bufsize; unsigned size_to_read; pj_ssize_t size; pj_status_t status; VXIinetResult inet_result; fport->eofpos = NULL; while (size_left > 0) { /* Calculate how many bytes to read in this run. */ size = size_to_read = size_left; inet_result = read_stream(fport,reinterpret_cast<VXIbyte*>(&fport->buf[fport->bufsize-size_left]) ,(VXIulong) size_to_read,(VXIulong*)&size); if (((inet_result !=VXIinet_RESULT_END_OF_STREAM) && (inet_result != VXIinet_RESULT_SUCCESS)) || (size <= 0 )) { pjmedia_port *port = (pjmedia_port *) fport; //simulate end of file to destroy the player fport->impl->play_result = VXIprompt_RESULT_IO_ERROR; fport->data_left = 0; fport->eof = PJ_TRUE; return PJ_ECANCELLED; } if (size > (pj_ssize_t)fport->data_left) { /* We passed the end of the data chunk, * only count the portion read from the data chunk. */ size = (pj_ssize_t)fport->data_left; } size_left -= size; fport->data_left -= size; /* If size is less than size_to_read, it indicates that we've * encountered EOF. Rewind the file. */ if (size < (pj_ssize_t)size_to_read) { fport->eof = PJ_TRUE; fport->eofpos = fport->buf + fport->bufsize - size_left; if (fport->options & PJMEDIA_FILE_NO_LOOP) { size_left = 0; /* Zero remaining buffer */ if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_PCM) { pj_bzero(fport->eofpos, size_left); } else if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW) { int val = pjmedia_linear2ulaw(0); pj_memset(fport->eofpos, val, size_left); } else if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ALAW) { int val = pjmedia_linear2alaw(0); pj_memset(fport->eofpos, val, size_left); } } /* Rewind file */ //fport->fpos = fport->start_data; /*pj_file_setpos( fport->fd, fport->fpos, PJ_SEEK_SET);*/ //fport->data_left = fport->data_len; } } /* Convert samples to host rep */ samples_to_host((pj_int16_t*)fport->buf, fport->bufsize/fport->bytes_per_sample); return PJ_SUCCESS; } static struct file_reader_port* create_file_stream_port(VXIpromptImpl *impl, char *filename, VXIinetStream *strm) { const pj_str_t name = pj_str("stream"); struct file_reader_port *fport; fport = PJ_POOL_ZALLOC_T(impl->pool, struct file_reader_port); if (!fport) return NULL; /* Put in default values. * These will be overriden once the file is read. */ pjmedia_port_info_init(&fport->base.info, &name, SIGNATURE, 8000, 1, 16, 80); pj_strdup2(impl->pool, &fport->base.info.name, filename); fport->base.get_frame = &strm_get_frame; fport->base.on_destroy = &strm_on_destroy; fport->fd = strm; fport->impl = impl; return fport; } static pj_status_t vxi_strmplayer_port_create( VXIpromptImpl *impl, char *filename, VXIinetStream *strm, VXIMap *strmprops, pjmedia_port **p_port ) { pjmedia_wave_hdr wave_hdr; pj_ssize_t size_to_read, size_read; struct file_reader_port *fport; pj_off_t pos; pj_status_t status = PJ_SUCCESS; pj_ssize_t buff_size = PJMEDIA_FILE_PORT_BUFSIZE; unsigned ptime; VXIint32 tempint; VXIinetResult inet_result; if (!strm || ! p_port) return PJ_EINVAL; //initialize ptime ptime = pjsua_var.mconf_cfg.samples_per_frame *1000 / pjsua_var.media_cfg.channel_count / pjsua_var.media_cfg.clock_rate; if (ptime == 0) ptime = 20; /* Create fport instance. */ fport = create_file_stream_port(impl, filename, strm); if (!fport) { return PJ_ENOMEM; } /* Get the file size. */ GetVXIInt(strmprops,INET_INFO_SIZE_BYTES,&tempint); fport->fsize = tempint; /* Size must be more than WAVE header size */ if (fport->fsize <= sizeof(pjmedia_wave_hdr)) { return PJMEDIA_ENOTVALIDWAVE; } /* Read the file header plus fmt header only. */ size_read = size_to_read = sizeof(wave_hdr) - 8; inet_result = read_stream(fport,reinterpret_cast<VXIbyte*>(&wave_hdr) ,(VXIulong) size_to_read,(VXIulong*)&size_read); if ((inet_result != VXIinet_RESULT_SUCCESS) || (size_read != size_to_read)) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_ENOTVALIDWAVE; } /* Normalize WAVE header fields values from little-endian to host * byte order. */ pjmedia_wave_hdr_file_to_host(&wave_hdr); /* Validate WAVE file. */ if (wave_hdr.riff_hdr.riff != PJMEDIA_RIFF_TAG || wave_hdr.riff_hdr.wave != PJMEDIA_WAVE_TAG || wave_hdr.fmt_hdr.fmt != PJMEDIA_FMT_TAG) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_ENOTVALIDWAVE; } /* Validate format and its attributes (i.e: bits per sample, block align) */ switch (wave_hdr.fmt_hdr.fmt_tag) { case PJMEDIA_WAVE_FMT_TAG_PCM: if (wave_hdr.fmt_hdr.bits_per_sample != 16 || wave_hdr.fmt_hdr.block_align != 2 * wave_hdr.fmt_hdr.nchan) status = PJMEDIA_EWAVEUNSUPP; break; case PJMEDIA_WAVE_FMT_TAG_ALAW: case PJMEDIA_WAVE_FMT_TAG_ULAW: if (wave_hdr.fmt_hdr.bits_per_sample != 8 || wave_hdr.fmt_hdr.block_align != wave_hdr.fmt_hdr.nchan) status = PJMEDIA_ENOTVALIDWAVE; break; default: status = PJMEDIA_EWAVEUNSUPP; break; } if (status != PJ_SUCCESS) { impl->inet->Close(impl->inet, &strm); return status; } fport->fmt_tag = (pjmedia_wave_fmt_tag)wave_hdr.fmt_hdr.fmt_tag; fport->bytes_per_sample = (pj_uint16_t) (wave_hdr.fmt_hdr.bits_per_sample / 8); /* If length of fmt_header is greater than 16, skip the remaining * fmt header data. */ if (wave_hdr.fmt_hdr.len > 16) { size_to_read = wave_hdr.fmt_hdr.len - 16; inet_result = skip_stream(fport,(VXIulong) size_to_read); if (inet_result != VXIinet_RESULT_SUCCESS) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_ENOTVALIDWAVE; } } /* Repeat reading the WAVE file until we have 'data' chunk */ for (;;) { pjmedia_wave_subchunk subchunk; size_to_read = size_read = 8; inet_result = read_stream(fport,reinterpret_cast<VXIbyte*>(&subchunk) ,(VXIulong) size_to_read,(VXIulong*)&size_read); if ((inet_result != VXIinet_RESULT_SUCCESS) || (size_read != size_to_read)) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_EWAVETOOSHORT; } /* Normalize endianness */ PJMEDIA_WAVE_NORMALIZE_SUBCHUNK(&subchunk); /* Break if this is "data" chunk */ if (subchunk.id == PJMEDIA_DATA_TAG) { wave_hdr.data_hdr.data = PJMEDIA_DATA_TAG; wave_hdr.data_hdr.len = subchunk.len; break; } /* Otherwise skip the chunk contents */ size_to_read = subchunk.len; inet_result = skip_stream(fport,(VXIulong) size_to_read); if (inet_result != VXIinet_RESULT_SUCCESS) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_ENOTVALIDWAVE; } } /* Current file position now points to start of data */ fport->start_data = fport->fpos; fport->data_len = wave_hdr.data_hdr.len; fport->data_left = wave_hdr.data_hdr.len; /* Validate length. */ if (wave_hdr.data_hdr.len > fport->fsize - fport->start_data) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_EWAVEUNSUPP; } if (wave_hdr.data_hdr.len < ptime * wave_hdr.fmt_hdr.sample_rate * wave_hdr.fmt_hdr.nchan / 1000) { impl->inet->Close(impl->inet, &strm); return PJMEDIA_EWAVETOOSHORT; } /* Initialize ::no loop support yet*/ fport->options = PJMEDIA_FILE_NO_LOOP; /* Update port info. */ fport->base.info.channel_count = wave_hdr.fmt_hdr.nchan; fport->base.info.clock_rate = wave_hdr.fmt_hdr.sample_rate; fport->base.info.bits_per_sample = 16; fport->base.info.samples_per_frame = fport->base.info.clock_rate * wave_hdr.fmt_hdr.nchan * ptime / 1000; fport->base.info.bytes_per_frame = fport->base.info.samples_per_frame * fport->base.info.bits_per_sample / 8; if (wave_hdr.data_hdr.len < (unsigned)buff_size) buff_size = wave_hdr.data_hdr.len; /* Create file buffer. */ fport->bufsize = buff_size; /* samples_per_frame must be smaller than bufsize (because get_frame() * doesn't handle this case). */ if (fport->base.info.samples_per_frame * fport->bytes_per_sample >= fport->bufsize) { impl->inet->Close(impl->inet, &strm); return PJ_EINVAL; } /* Create buffer. */ fport->buf = (char*) pj_pool_alloc(impl->pool, fport->bufsize); if (!fport->buf) { impl->inet->Close(impl->inet, &strm); return PJ_ENOMEM; } fport->readpos = fport->buf; /* Fill up the buffer. */ status = fill_port_buffer(fport); if (status != PJ_SUCCESS) { impl->inet->Close(impl->inet, &strm); return status; } /* Done. */ *p_port = &fport->base; return PJ_SUCCESS; } static VXIpromptResult PlayFileFromStream(VXIpromptImpl *impl,char *filename,VXIinetStream *stream, VXIMap *strmprops){ pjmedia_port *port = NULL; pj_status_t ret; pjsua_call_id pj_call_id = PJSUA_INVALID_ID; struct file_reader_port *fport; ret = vxi_strmplayer_port_create(impl, filename, stream, strmprops,&port ); if ( (ret != PJ_SUCCESS) || !port) return VXIprompt_RESULT_NO_RESOURCE; ret = pjsua_player_create_fport( &pj_str(filename), 0, port, &impl->player_id); pj_call_id = sipPhone::GetPJSIPCallId (impl->call_id); if ( (ret != PJ_SUCCESS) || (impl->player_id== PJSUA_INVALID_ID)|| (pj_call_id == PJSUA_INVALID_ID)) return VXIprompt_RESULT_PLATFORM_ERROR; pjmedia_port* mport; ret = pjsua_player_get_port(impl->player_id, &mport); if (ret != PJ_SUCCESS) { return VXIprompt_RESULT_PLATFORM_ERROR; } // specify the method to be called when the wav file finishes playing fport = (struct file_reader_port *)port; fport->base.port_data.pdata = impl; fport->cb = onPlayFileComplete; ret = pjsua_conf_connect(pjsua_player_get_conf_port (impl->player_id), pjsua_call_get_conf_port(pj_call_id)); if( ret != PJ_SUCCESS ) { return VXIprompt_RESULT_PLATFORM_ERROR; } return VXIprompt_RESULT_SUCCESS; } // Start playing queued prompts. This call is non-blocking. // static VXIpromptResult VXIpromptPlay(VXIpromptInterface * vxip) { VXIpromptImpl *impl = ToVXIpromptImpl(vxip); struct prompt_details *it; VXIpromptResult ret; Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing queued prompt"); pj_mutex_lock(impl->obj_lock); StopFiller(impl); //merge queued files to be played pj_list_merge_last(&impl->play_files, &impl->queued_files); //check if files are currently being played if (pj_sem_trywait(impl->play_lock) != PJ_SUCCESS) { pj_mutex_unlock(impl->obj_lock); return VXIprompt_RESULT_SUCCESS; } pj_sem_post(impl->play_lock); // iterate over queued prompts it = impl->play_files.next; while(it != &impl->play_files) { if ( (ret = PlayFileEntry(impl,it)) == VXIprompt_RESULT_SUCCESS) { //successfully playing file Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Issuing wait on play lock"); pj_sem_wait(impl->play_lock); impl->current_pfile = it; pj_gettimeofday(&impl->current_pfile->play_start_time); break; } if ( (ret < impl->play_result)||(ret>0 && impl->play_result == VXIprompt_RESULT_SUCCESS )) impl->play_result = ret; it = it->next; } pj_mutex_unlock(impl->obj_lock); return VXIprompt_RESULT_SUCCESS; } static void stop_filler_cb( pj_timer_heap_t *th, pj_timer_entry *entry) { VXIpromptImpl *impl = NULL; pjmedia_port *port= NULL; if ( !entry->user_data) return; impl = ToVXIpromptImpl((VXIpromptInterface*)entry->user_data); Diag(impl, DIAG_TAG_PROMPTING, L"StopFiller", L"Timer fired for stopping Filler audio"); pj_mutex_lock(impl->obj_lock); // confirm if we still are playing filler if ((impl->current_pfile != NULL) && (impl->current_pfile->is_filler == PJ_TRUE) && (impl->player_id != PJSUA_INVALID_ID)) { pjsua_player_get_port(impl->player_id,&port); //simulate file play end if (port) onPlayFileComplete(port,impl); } //reset timer pj_timer_entry_init(&impl->stop_filler_timer, PJSUA_INVALID_ID, NULL, NULL); pj_mutex_unlock(impl->obj_lock); } static VXIpromptResult StopFiller(VXIpromptImpl *impl) { struct prompt_details *it = NULL; struct prompt_details *curr = NULL; pjmedia_port *port= NULL; // check if we already have a timer if ( impl->stop_filler_timer.id >0) return VXIprompt_RESULT_SUCCESS; it = impl->play_files.next; while ( it != &impl->play_files) { curr = it; it = it->next; if (curr->is_filler == PJ_TRUE && (curr !=impl->current_pfile)) { curr->src.~vxistring(); pj_list_erase(curr); } } // see if the filler is currently playing if ((impl->current_pfile != NULL) && (impl->current_pfile->is_filler == PJ_TRUE) && (impl->player_id != PJSUA_INVALID_ID)) { pj_time_val now; Diag(impl, DIAG_TAG_PROMPTING, L"StopFiller", L"Stopping Filler audio %s", impl->current_pfile->src.c_str()); // check if filler has finished its minimum duration if ( impl->current_pfile->min_play_msec >0) { pj_gettimeofday(&now); PJ_TIME_VAL_SUB(now,impl->current_pfile->play_start_time); if ( PJ_TIME_VAL_MSEC(now) >= impl->current_pfile->min_play_msec) { pjsua_player_get_port(impl->player_id,&port); //simulate file play end if (port) onPlayFileComplete(port,impl); }else{ //schedule timer to stop the filler pj_time_val delay; pj_timer_entry_init(&impl->stop_filler_timer, PJ_TRUE, impl, &stop_filler_cb); VXIlong remainingPlayTime = impl->current_pfile->min_play_msec - PJ_TIME_VAL_MSEC(now); delay.msec = remainingPlayTime%1000; delay.sec = remainingPlayTime/1000; Diag(impl, DIAG_TAG_PROMPTING, L"StopFiller", L"Scheduling timer to stop filler after %d msec", PJ_TIME_VAL_MSEC(delay)); pjsip_endpt_schedule_timer(pjsua_var.endpt, &impl->stop_filler_timer, &delay); } } } return VXIprompt_RESULT_SUCCESS; } // Start the special play of a filler prompt. This call is non-blocking. // static VXIpromptResult VXIpromptPlayFiller(VXIpromptInterface * vxip, const VXIchar *type, const VXIchar *src, const VXIchar *text, const VXIMap* properties, VXIlong min_play_msec) { VXIpromptImpl *impl = ToVXIpromptImpl(vxip); struct prompt_details *it = NULL; struct prompt_details *filler = NULL; VXIpromptResult ret; Diag(impl, DIAG_TAG_PROMPTING, L"VXIpromptPlayFiller", L"%s", (src? src : L"NULL")); pj_mutex_lock(impl->obj_lock); // check if already have filler audio StopFiller(impl); filler = PJ_POOL_ZALLOC_T(impl->pool, struct prompt_details); if ( !filler ) return VXIprompt_RESULT_OUT_OF_MEMORY; filler->src.assign(src); filler->is_filler = PJ_TRUE; filler->min_play_msec = min_play_msec; pj_list_push_back(&impl->play_files,filler); //check if files are currently being played if (pj_sem_trywait(impl->play_lock) != PJ_SUCCESS) { pj_mutex_unlock(impl->obj_lock); return VXIprompt_RESULT_SUCCESS; } pj_sem_post(impl->play_lock); // iterate over queued prompts it = impl->play_files.next; while(it != &impl->play_files) { if ( (ret = PlayFileEntry(impl,it)) == VXIprompt_RESULT_SUCCESS) { //successfully playing file Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Issuing wait on play lock"); pj_sem_wait(impl->play_lock); impl->current_pfile = it; pj_gettimeofday(&impl->current_pfile->play_start_time); break; } it = it->next; } pj_mutex_unlock(impl->obj_lock); return VXIprompt_RESULT_SUCCESS; } static VXIpromptResult VXIpromptPrefetch(VXIpromptInterface * vxip, const VXIchar *type, const VXIchar *src, const VXIchar *text, const VXIMap* properties) { VXIpromptImpl *impl = ToVXIpromptImpl(vxip); Diag(impl, DIAG_TAG_PREFETCHING, L"VXIpromptPrefetch", L"%s", (text ? text : L"NULL")); return VXIprompt_RESULT_SUCCESS; } static VXIint ConvertStringToInt(const VXIchar *time){ VXIint value = 0; vxistring attr = vxistring(time); #if defined(__GNUC__) // The G++ 2.95/3.0 implementation of basic_stringstream is faulty. VXIchar * temp; value = VXIint(wcstol(attr.c_str(), &temp, 10)); if (*temp) value = -1; #else std::basic_stringstream<VXIchar> attrStream(attr); attrStream >> value; if (attrStream.bad()) value = -1; #endif return value; } static VXIint ConvertToMs(const VXIchar *time) { vxistring str_time(time); VXIint result = 0; double final = 0.0, fraction = -1.0; bool fflag = false; if (str_time.empty()) return 0; for (unsigned int i = 0; i < str_time.length(); ++i) { char c; switch (str_time[i]) { // ignore white spaces and plus sign case L' ': case L'\t': case L'\n': case L'\r': case L'+': continue; case L'-': // do not allow negative conversion return 0; case L'0': c = 0; break; case L'1': c = 1; break; case L'2': c = 2; break; case L'3': c = 3; break; case L'4': c = 4; break; case L'5': c = 5; break; case L'6': c = 6; break; case L'7': c = 7; break; case L'8': c = 8; break; case L'9': c = 9; break; case L'.': // disallow illegal fraction number if( fflag ) { return 0; } fflag = true; continue; default: const vxistring units = str_time.substr(i, str_time.length() - i); if (units == L"ms") { result = (VXIint) final; return result; } if (units == L"s") { result = (VXIint) (final * 1000); return result; } return 0; } if( fflag ) { fraction = fraction < 0 ? 0.1 : fraction / 10; final += (fraction * c ); } else final = 10.0*final + c; } return 0; } static struct prompt_details* processVoiceTag(VXIpromptImpl *impl, DOMElement *elem) { /* * Note: Do not support recursion or any other tag inside the voice element */ static const VXIchar *nameAttr= L"name"; static const VXIchar *xmlLangAttr= L"xml:lang"; static const VXIchar *genderAttr= L"gender"; static const VXIchar *ageAttr= L"age"; static const VXIchar *variantAttr= L"variant"; struct prompt_details *prompt = NULL; const XMLCh* tmp = NULL; const XMLCh* elemName = NULL; VXIcharToXMLCh xmlchnameAttr(nameAttr); VXIcharToXMLCh xmlchxmlLangAttr(xmlLangAttr); VXIcharToXMLCh xmlchgenderAttr(genderAttr); VXIcharToXMLCh xmlchageAttr(ageAttr); VXIcharToXMLCh xmlchvariantAttr(variantAttr); elemName = elem->getTagName(); //voice string for TTS DOMNode *node = (DOMNode*)elem; DOMNode *child = node->getFirstChild(); vxistring ttsstring = L""; while (child) { const XMLCh *xmlchNodeVal = NULL; short type = child->getNodeType(); if (type != 3) { DOMNode *cnode = child->getFirstChild(); xmlchNodeVal = cnode->getNodeValue(); } else { xmlchNodeVal = child->getNodeValue(); } if (xmlchNodeVal) { XMLChToVXIchar nodeVal(xmlchNodeVal); ttsstring += nodeVal.c_str(); } child = child->getNextSibling(); } if (ttsstring.length() > 0) { prompt = (struct prompt_details *)pj_pool_calloc(impl->pool, sizeof(struct prompt_details),1); if (!prompt) return NULL; prompt->voice.valid = true; prompt->voice.pvalue = vxistring(); prompt->voice.pvalue.assign(ttsstring.c_str()); } else { return NULL; } // name attribute tmp = elem->getAttribute(xmlchnameAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar nameString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"name %s",nameString.c_str() ); //Add to list play if (!prompt) return NULL; prompt->voice.name = vxistring(); prompt->voice.name.assign(nameString.c_str()); } // lang attribute tmp = elem->getAttribute(xmlchxmlLangAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar langString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"voice xml:lang %s", langString.c_str() ); //Add to list play if (!prompt) return NULL; prompt->voice.lang = vxistring(); prompt->voice.lang.assign(langString.c_str()); } // gender attribute tmp = elem->getAttribute(xmlchgenderAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar genderString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"voice gender %s", genderString.c_str() ); //Add to list play if (!prompt) return NULL; prompt->voice.gender = vxistring(); prompt->voice.gender.assign(genderString.c_str()); } // age attribute tmp = elem->getAttribute(xmlchageAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar ageString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"voice age %s", ageString.c_str() ); //Add to list play if (!prompt) return NULL; prompt->voice.age = _wtoi(ageString.c_str()); } // variant attribute tmp = elem->getAttribute(xmlchvariantAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar varString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"voice variant %s", varString.c_str() ); //Add to list play if (!prompt) return NULL; prompt->voice.variant = _wtoi(varString.c_str()); } return prompt; } static struct prompt_details* getPromptInfo(VXIpromptImpl *impl, DOMElement *elem) { static const VXIchar *srcAttr= L"src"; static const VXIchar *nameAttr= L"name"; static const VXIchar *timeoutAttr= L"fetchtimeout"; static const VXIchar *fhintAttr= L"fetchhint"; static const VXIchar *maxageAttr= L"maxage"; static const VXIchar *maxstaleAttr= L"maxstale"; struct prompt_details *prompt = NULL; const XMLCh* tmp = NULL; const XMLCh* elemName = NULL; VXIcharToXMLCh xmlchsrcAttr(srcAttr); VXIcharToXMLCh xmlchnameAttr(nameAttr); VXIcharToXMLCh xmlchftoutAttr(timeoutAttr); VXIcharToXMLCh xmlchfhintAttr(fhintAttr); VXIcharToXMLCh xmlchmaxageAttr(maxageAttr); VXIcharToXMLCh xmlchmaxstaleAttr(maxstaleAttr); elemName = elem->getTagName(); if (wcscmp((const wchar_t*)elemName, L"speak") == 0) { DOMNode *node = (DOMNode*)elem; DOMNode *child = node->getFirstChild(); if (child) { const XMLCh *xmlchNodeVal = child->getNodeValue(); if (xmlchNodeVal) { XMLChToVXIchar nodeVal(xmlchNodeVal); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Prompt string %s", nodeVal.c_str() ); //queue it prompt = (struct prompt_details *)pj_pool_calloc(impl->pool, sizeof(struct prompt_details),1); if (!prompt) return NULL; prompt->pvalue = vxistring(); prompt->pvalue.assign(nodeVal.c_str()); } } } tmp = elem->getAttribute(xmlchnameAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar nameString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"audio mark name %s",nameString.c_str() ); //Add to list play prompt = (struct prompt_details *)pj_pool_calloc(impl->pool, sizeof(struct prompt_details),1); if (!prompt) return NULL; prompt->mark = vxistring(); prompt->mark.assign(nameString.c_str()); } // src attribute tmp = elem->getAttribute(xmlchsrcAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar srcString(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"audio prompt src %s",srcString.c_str() ); //Add to list play prompt = (struct prompt_details *)pj_pool_calloc(impl->pool, sizeof(struct prompt_details),1); if (!prompt) return NULL; prompt->src = vxistring(); prompt->src.assign(srcString.c_str()); } //fetchtimeout attribute tmp = elem->getAttribute(xmlchftoutAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar fetchTimeout(tmp); prompt->fetch_timeout = ConvertToMs(fetchTimeout.c_str()); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"audio prompt fetchtimeout %d",prompt->fetch_timeout ); } //fetchhint attribute tmp = elem->getAttribute(xmlchfhintAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar fetchHint(tmp); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"audio prompt fetchhint %s",fetchHint.c_str() ); } //maxage attribute tmp = elem->getAttribute(xmlchmaxageAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar maxAge(tmp); prompt->max_age = ConvertStringToInt(maxAge.c_str()); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"audio prompt maxage %d",prompt->max_age ); } //maxstale attribute tmp = elem->getAttribute(xmlchmaxstaleAttr.c_str()); if (tmp && wcscmp((const wchar_t*)tmp, L"") != 0) { XMLChToVXIchar maxStale(tmp); prompt->max_stale = ConvertStringToInt(maxStale.c_str()); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"audio prompt maxstale %d",prompt->max_stale ); } return prompt; } int getAudioSegsFromSSML(VXIpromptImpl *impl, vxistring SSMLDoc, const VXIMap *properties, pj_bool_t bargein) { DocumentParser *parser = new DocumentParser(); DOMDocument *doc = NULL; DOMNodeList *audioNodes = NULL; DOMNodeList *markNodes = NULL; DOMNodeList *voiceNodes = NULL; DOMNodeList *speakNodes = NULL; static const VXIchar *audioTag= L"audio"; static const VXIchar *markTag= L"mark"; static const VXIchar *voiceTag= L"voice"; static const VXIchar *speakTag= L"speak"; DOMElement *elem = NULL; VXIinetStream *stream = NULL; VXIcharToXMLCh audioElem(audioTag); VXIcharToXMLCh markElem(markTag); VXIcharToXMLCh voiceElem(voiceTag); VXIcharToXMLCh speakElem(speakTag); struct prompt_details *prompt = NULL; int result = parser->ParseXML(L"ssmldoc",(const VXIbyte*)SSMLDoc.c_str(),wcslen(SSMLDoc.c_str())*sizeof(wchar_t), &doc); if (result) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Error parsing SSML doc %d", result); delete parser; return result; } Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Successfully parsed SSML doc"); speakNodes = doc->getElementsByTagName(speakElem.c_str()); if (speakNodes && (speakNodes->getLength() > 0)) { pj_mutex_lock(impl->obj_lock); for ( int i=0; i< speakNodes->getLength();i++) { if (speakNodes->item(i)->getNodeType() != 1 ) continue; elem = (DOMElement *)speakNodes->item(i); prompt = getPromptInfo(impl,elem); if (prompt) { prompt->bargein_allowed = bargein; pj_list_push_back(&impl->queued_files, prompt); } } pj_mutex_unlock(impl->obj_lock); } audioNodes = doc->getElementsByTagName(audioElem.c_str()); if (!audioNodes || (audioNodes->getLength() <= 0)) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"No audio prompts in SSML doc"); } else { pj_mutex_lock(impl->obj_lock); for ( int i=0; i< audioNodes->getLength();i++) { if (audioNodes->item(i)->getNodeType() != 1 ) continue; elem = (DOMElement *)audioNodes->item(i); prompt = getPromptInfo(impl,elem); if (prompt) { prompt->bargein_allowed = bargein; pj_list_push_back(&impl->queued_files, prompt); } } pj_mutex_unlock(impl->obj_lock); } markNodes = doc->getElementsByTagName(markElem.c_str()); if (!markNodes || (markNodes->getLength() <= 0)) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"No audio expr in SSML doc"); } else { pj_mutex_lock(impl->obj_lock); for (int i = 0; i < markNodes->getLength(); i++) { if (markNodes->item(i)->getNodeType() != 1 ) continue; elem = (DOMElement *)markNodes->item(i); prompt = getPromptInfo(impl,elem); const VXIValue *val = VXIMapGetProperty(properties, PROMPT_AUDIO_REFS); if (val && VXIValueGetType(val) == VALUE_MAP) { VXIMap *map = (VXIMap*)val; const VXIValue *value = VXIMapGetProperty(map, prompt->mark.c_str()); if (value && VXIValueGetType(value) == VALUE_CONTENT && prompt) { prompt->vxicontent = (VXIContent*)VXIValueClone(value); } } if (prompt) { prompt->bargein_allowed = bargein; pj_list_push_back(&impl->queued_files, prompt); } } pj_mutex_unlock(impl->obj_lock); } voiceNodes = doc->getElementsByTagName(voiceElem.c_str()); if (!voiceNodes || (voiceNodes->getLength() <= 0)) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"No voice element in SSML doc"); delete parser; return 0; } else { pj_mutex_lock(impl->obj_lock); for (int i = 0; i < voiceNodes->getLength(); i++) { if (voiceNodes->item(i)->getNodeType() != 1 ) continue; elem = (DOMElement *)voiceNodes->item(i); prompt = processVoiceTag(impl,elem); if (prompt) { prompt->bargein_allowed = bargein; pj_list_push_back(&impl->queued_files, prompt); } } pj_mutex_unlock(impl->obj_lock); } delete parser; return result; } // Queue prompt for playing. This call is non-blocking. The prompt // is not played until VXIpromptPlay( ) is called. // static VXIpromptResult VXIpromptQueue(VXIpromptInterface* vxip, const VXIchar *raw_type, const VXIchar *raw_src, /* no longer used */ const VXIchar *raw_text, const VXIMap *properties) { VXIpromptImpl *impl = ToVXIpromptImpl(vxip); pj_bool_t bargein_allowed = PJ_FALSE; PJ_LOG(4, ("VXIPROMPT", "Prompt queue called %s %p", raw_type, raw_text)); vxistring type(L""), text(L""); if (raw_type) type = raw_type; if (raw_text) text = raw_text; // Handle the resolved information to queue. if (text.empty()) return VXIprompt_RESULT_INVALID_ARGUMENT; // currently, vxi only queues SSML if (type == VXI_MIME_SSML) { vxistring bargein; const VXIValue *val = VXIMapGetProperty(properties, L"bargein"); if (val != NULL) bargein = VXIStringCStr(reinterpret_cast<const VXIString*>(val)); vxistring bargeintype; val = VXIMapGetProperty(properties, L"bargeintype"); if (val != NULL) bargeintype = VXIStringCStr(reinterpret_cast<const VXIString*>(val)); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Queuing TTS: bargein=%s, bargeintype=%s, ssml=%s", bargein.c_str(), bargeintype.c_str(), text.c_str()); //parse SSML doc if( bargein == L"true") { bargein_allowed = PJ_TRUE; } getAudioSegsFromSSML(impl, text, properties, bargein_allowed); } else { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Queuing Unknown type text (%s): %s" , type.c_str(), text.c_str()); return VXIprompt_RESULT_UNSUPPORTED; } return VXIprompt_RESULT_SUCCESS; } // Wait until all queued prompts finish playing. // static VXIpromptResult VXIpromptWait(VXIpromptInterface* vxip, VXIpromptResult* playResult) { VXIpromptImpl *impl = ToVXIpromptImpl(vxip); Diag(impl, DIAG_TAG_PROMPTING, NULL, L"%s" , L"VXIpromptWait"); pj_mutex_lock(impl->obj_lock); StopFiller(impl); pj_mutex_unlock(impl->obj_lock); pj_sem_wait(impl->play_lock); *playResult = impl->play_result; Diag(impl, DIAG_TAG_PROMPTING, NULL, L"VXIpromptWait returning with status %d", impl->play_result); impl->play_result = VXIprompt_RESULT_SUCCESS; pj_sem_post(impl->play_lock); return VXIprompt_RESULT_SUCCESS; } // Stop the current playing prompt. // static VXIpromptResult VXIpromptStop (VXIpromptInterfaceEx *prompt, VXIbool force) { VXIpromptImpl *impl = NULL; pjmedia_port *port = NULL; if (prompt == NULL) return VXIprompt_RESULT_INVALID_ARGUMENT; impl=ToVXIpromptImpl(prompt); if (impl->stop == PJ_TRUE || impl->player_id == PJSUA_INVALID_ID||impl->current_pfile == NULL ) { return VXIprompt_RESULT_SUCCESS; } Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Stopping prompt play %d", impl->call_id); if (!(force ||(impl->current_pfile != NULL && impl->current_pfile->bargein_allowed))) { Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Prompt stop not allowed"); //operation not permitted return VXIprompt_RESULT_SUCCESS; } impl->stop = PJ_TRUE; pjsua_player_get_port(impl->player_id,&port); if (port) onPlayFileComplete(port, impl); return VXIprompt_RESULT_SUCCESS; } /* When pjsip signals end of file playback ,conf mutex is held by the cal... [truncated message content] |
From: Lauters M. <meh...@gm...> - 2012-06-20 07:16:38
|
Hi, > Hi, > > Sorry for delayed response. > Thanks to answer!! > Your prompt is not in English so maybe you need to provide a language tag. > Look at http://www.w3.org/TR/voicexml20/#dml4.1. Otherwise you > understanding is correct. Also check the log file for any error messages. > Log file path is specified in {base vxi path}\config\sbclient.cfg. > I'll try and have a look on logs > For reference, I have attached my vxiprompt implementation too. It has, of > course, reference to thrid party libs which you will have to filter out. > Maybe I'm wrong but I think you forget the attached file. > > Regards, > Anshuman > > PS: I see a lot of crashes with mozjs1.8.5 on Windows. Hows your > experience so far? > I'm working on linux, and I'm not using mozjs1.8.5 because I didn't succed to compile it. I'm using SpiderMonkey 1.5rc5. For now, i didn't use javascipt in vxml files and evry thin is going right. Regards, Mehdi |
From: Anshuman S. R. <ar...@3c...> - 2012-06-19 14:35:21
|
Hi, Sorry for delayed response. Your prompt is not in English so maybe you need to provide a language tag. Look at http://www.w3.org/TR/voicexml20/#dml4.1. Otherwise you understanding is correct. Also check the log file for any error messages. Log file path is specified in {base vxi path}\config\sbclient.cfg. For reference, I have attached my vxiprompt implementation too. It has, of course, reference to thrid party libs which you will have to filter out. Regards, Anshuman PS: I see a lot of crashes with mozjs1.8.5 on Windows. Hows your experience so far? ----- Original Message ----- From: Lauters Mehdi To: Anshuman S. Rawat Cc: ope...@li... Sent: Wednesday, June 13, 2012 11:05 PM Subject: Re: [Openvxi-discuss] Compiling openvxi on latest ubuntu platform Hi, Thanks for the rec file. Now I'm able to read from the keyboard according to the grammar. But I still can't display the prompt text on the screen. What I understood is that first VXIpromptQueue is called, and then VXIpromptPlay. So I tried fisrt to check the VXIpromptQueue input data. From what I understand the raw_text argument from VXIpromptQueue should be "Enter un number please" isn't it? I'm always getting null value... What could be wrong? My grammar? I'm testing with the given grammar: <?xml version="1.0"?> <!DOCTYPE vxml PUBLIC "-//BeVocal Inc//VoiceXML 1.0//EN" "http://cafe.bevocal.com/libraries/dtd/vxml1-0-bevocal.dtd"> <vxml version = "2.1" > <grammar version="1.0" root="testGrammar" > <rule id="testGrammar"> <one-of> <item> one </item> <item> two </item> <item> three </item> </one-of> </rule> </grammar> <form> <field name="number"> <prompt> Enter un number please </prompt> <grammar src="sample.vxml" type="application/srgs+xml"/> <filled> that's a number </filled> </field> </form> </vxml> Thanks for your help Regards, Mehdi ------------------------------------------------------------------------------ No virus found in this incoming message. Checked by AVG - www.avg.com Version: 9.0.930 / Virus Database: 2433.1.1/5065 - Release Date: 06/13/12 00:28:00 |
From: Lauters M. <meh...@gm...> - 2012-06-13 17:35:39
|
Hi, Thanks for the rec file. Now I'm able to read from the keyboard according to the grammar. But I still can't display the prompt text on the screen. What I understood is that first *VXIpromptQueue* is called, and then * VXIpromptPlay*. So I tried fisrt to check the VXIpromptQueue input data. >From what I understand the *raw_text* argument from VXIpromptQueue should be "*Enter un number please*" isn't it? I'm always getting null value... What could be wrong? My grammar? I'm testing with the given grammar: *<?xml* version="1.0"*?>* *<!DOCTYPE *vxml PUBLIC "-//BeVocal Inc//VoiceXML 1.0//EN" "http://cafe.bevocal.com/libraries/dtd/vxml1-0-bevocal.dtd"*>* *<vxml* version = "2.1" *>** <grammar* version="1.0" root="testGrammar" *>* *<rule* id="testGrammar"*>* *<one-of>* *<item>* one *</item>* *<item>* two *</item>* *<item>* three *</item>* *</one-of>**</rule>** </grammar> * *<form>* *<field* name="number"*>**<prompt>* Enter un number please *</prompt>* *<grammar* src="sample.vxml" type="application/srgs+xml"*/>* *<filled>* that's a number *</filled>* *</field>* *</form>* *</vxml>* Thanks for your help Regards, Mehdi |
From: Anshuman S. R. <ar...@3c...> - 2012-06-07 12:06:59
|
/****************License************************************************ * Vocalocity OpenVXI * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or * registered trademarks of Vocalocity, Inc. * OpenVXI is a trademark of Scansoft, Inc. and used under license * by Vocalocity. ***********************************************************************/ #define VXIREC_EXPORTS #include "VXIrecAPI.h" #include "VXIrec_utils.h" #include "LogBlock.hpp" #include <cstdio> #include <cstring> #include <sstream> // ------*---------*---------*---------*---------*---------*---------*--------- static void ResultContentDestroy(VXIbyte **content, void *userData) { if (content && *content) delete [] *content; *content = NULL; } class VXIVectorHolder { public: VXIVectorHolder() : _vector(NULL) { _vector = VXIVectorCreate(); } VXIVectorHolder(VXIVector * m) : _vector(m) { } ~VXIVectorHolder() { if (_vector != NULL) VXIVectorDestroy(&_vector);} VXIVectorHolder & operator=(const VXIVectorHolder & x) { if (this != &x) { if (_vector != NULL) VXIVectorDestroy(&_vector); _vector = VXIVectorClone(x._vector); } return *this; } // GetValue returns the internal vector. The standard vector manipulation // functions may then be used. VXIVector * GetValue() const { return _vector; } // These functions allow the holder to take ownership of an existing vector // or to release the internal one. VXIVector * Release() { VXIVector * m = _vector; _vector = NULL; return m; } void Acquire(VXIVector * m) { if (_vector != NULL) VXIVectorDestroy(&_vector); else _vector = m; } private: VXIVectorHolder(const VXIVectorHolder &); // intentionally not defined. VXIVector * _vector; }; // ------*---------*---------*---------*---------*---------*---------*--------- // Global for the base diagnostic tag ID, see osbrec_utils.h for tags // static VXIunsigned gblDiagLogBase = 0; // VXIrec implementation of the VXIrec interface // extern "C" { //Anshuman: created a replica of structure in pjsip_vxi branch //for debugging purposes only. Not intended for actual use. struct VXIrecImpl { // Base interface, must be first VXIrecInterface intf; // Class for managing grammars VXIrecData *recData; // call id int call_id; //memory pool for this prompt resource void *pool; //lock for synchronizing various operations void *obj_lock; //semaphore for input event void *input_lock; //store for input events VXIMap *pProperty; VXIrecResult result; }; } static struct VXIrecImpl *recImplTable[100]; // A few conversion functions... static inline VXIrecGrammar * ToVXIrecGrammar(VXIrecGrammar * i) { return reinterpret_cast<VXIrecGrammar *>(i); } static inline VXIrecGrammar * FromVXIrecGrammar(VXIrecGrammar * i) { return reinterpret_cast<VXIrecGrammar *>(i); } static inline VXIrecData * GetRecData(VXIrecInterface * i) { if (i == NULL) return NULL; return reinterpret_cast<VXIrecImpl *>(i)->recData; } /******************************************************* * Method routines for VXIrecInterface structure *******************************************************/ // Get the VXIrec interface version supported // static VXIint32 VXIrecGetVersion(void) { return VXI_CURRENT_VERSION; } // Get the implementation name // static const VXIchar* VXIrecGetImplementationName(void) { static const VXIchar IMPLEMENTATION_NAME[] = COMPANY_DOMAIN L".VXIrec"; return IMPLEMENTATION_NAME; } static VXIrecResult VXIrecBeginSession(VXIrecInterface * pThis, VXIMap *m) { const wchar_t* fnname = L"VXIrecBeginSession"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecBeginSession\n"); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecEndSession(VXIrecInterface *pThis, VXIMap *) { const wchar_t* fnname = L"VXIrecEndSession"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecEndSession\n"); tp->Clear(); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecLoadGrammarFromString(VXIrecInterface *pThis, const VXIMap *prop, const VXIchar *type, const VXIchar *str, VXIrecGrammar **gram) { const wchar_t* fnname = L"VXIrecLoadGrammarFromString"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecLoadGrammarFromString: \ntype: %S,\nstr: %S\n", type, str); // Check the arguments if (str == NULL) { logger = VXIrec_RESULT_INVALID_ARGUMENT; return VXIrec_RESULT_INVALID_ARGUMENT; } if (type == NULL) { logger = VXIrec_RESULT_UNSUPPORTED; return VXIrec_RESULT_UNSUPPORTED; } VXIrecGrammar * gp = NULL; vxistring srgsGram, mtype(type); logger.logDiag(DIAG_TAG_GRAMMARS, L"%s%s", L"TYPE: ", mtype.c_str()); tp->ShowPropertyValue(prop); if( mtype == L"application/x-jsgf" || mtype == REC_MIME_CHOICE || mtype == REC_MIME_CHOICE_DTMF) { // first crack the srgs grammar JSGFInfo info; tp->ConvertJSGFType(str, info); // then try to convert to SRGS format if( !tp->JSGFToSRGS(info.contentStr, srgsGram, prop) ) return VXIrec_RESULT_FAILURE; mtype = VXI_MIME_SRGS; // reset mime type logger.logDiag(DIAG_TAG_GRAMMARS, L"%s%s", L"Converted GRAMMAR: ", srgsGram.c_str()); } else if( mtype == VXI_MIME_SRGS ) { // processing below srgsGram = str; printf("VXIrecLoadGrammarFromString: VXI_MIME_SRGS grammar\n"); } else { // Handle your own type here, return unsupported for now logger = VXIrec_RESULT_UNSUPPORTED; return VXIrec_RESULT_UNSUPPORTED; } // Parsing SRGS grammar. // NOTES: The parsing is very simple, therefore it may not work // for complex grammar. As you know, this is a simulator!!! VXIrecGrammar * gramPtr = tp->ParseSRGSGrammar(srgsGram, prop); if( gramPtr == NULL ) return VXIrec_RESULT_FAILURE; tp->AddGrammar(gramPtr); *gram = ToVXIrecGrammar(gramPtr); printf("VXIrecLoadGrammarFromString returning success\n"); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecLoadGrammarFromURI(struct VXIrecInterface *pThis, const VXIMap *properties, const VXIchar *type, const VXIchar *uri, const VXIMap *uriArgs, VXIrecGrammar **gram) { VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; const wchar_t* fnname = L"VXIrecLoadGrammarFromURI"; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecLoadGrammarFromURI\n"); tp->ShowPropertyValue(properties); if (wcsncmp(uri, L"builtin", 7) == 0 ){ logger.logDiag(DIAG_TAG_GRAMMARS, L"%s", L"built-in not supported"); return VXIrec_RESULT_UNSUPPORTED; } VXIbyte *buffer = NULL; VXIulong read = 0; if (!tp->FetchContent(uri, uriArgs, &buffer, read)) return VXIrec_RESULT_FAILURE; // NOTE: this code assumes the retieved buffer is // composed of single byte chars. in the real world, // that can't be assumed. buffer[read] = 0; VXIchar *charbuff = new VXIchar[read+1]; mbstowcs(charbuff, (char*)buffer, read+1); VXIrecResult rc = VXIrecLoadGrammarFromString(pThis, properties, type, charbuff, gram); printf("VXIrecLoadGrammarFromURI: result rc: %d\n", rc); delete[] buffer; delete[] charbuff; return rc; } static VXIrecResult VXIrecLoadGrammarOption(VXIrecInterface * pThis, const VXIMap * properties, const VXIVector * gramChoice, const VXIVector * gramValue, const VXIVector * gramAcceptance, const VXIbool isDTMF, VXIrecGrammar ** gram) { const wchar_t* fnname = L"VXIrecLoadGrammarOption"; // Check the arguments VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecLoadGrammarOption\n"); if (gram == NULL) { logger = VXIrec_RESULT_INVALID_ARGUMENT; return VXIrec_RESULT_INVALID_ARGUMENT; } tp->ShowPropertyValue(properties); VXIrecGrammar * gp = NULL; vxistring srgsGram; if( !tp->OptionToSRGS(properties, gramChoice, gramValue, gramAcceptance, isDTMF, srgsGram) ) return VXIrec_RESULT_FAILURE; // Parsing SRGS grammar. // NOTES: The parsing is very simple, therefore it may not work // for complex grammar. As you know, this is a simulator!!! VXIrecGrammar * gramPtr = tp->ParseSRGSGrammar(srgsGram, properties, isDTMF); if( gramPtr == NULL ) return VXIrec_RESULT_FAILURE; tp->AddGrammar(gramPtr); *gram = ToVXIrecGrammar(gramPtr); printf("VXIrecLoadGrammarOption returning success\n"); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecFreeGrammar(VXIrecInterface *pThis, VXIrecGrammar **gram) { const wchar_t* fnname = L"VXIrecFreeGrammar"; // Check the arguments VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecFreeGrammar\n"); // If the grammar pointer is null, there is nothing to free. if (gram == NULL || *gram == NULL) VXIrec_RESULT_SUCCESS; tp->FreeGrammar(FromVXIrecGrammar(*gram)); *gram = NULL; printf("VXIrecFreeGrammar returning success\n"); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecActivateGrammar(VXIrecInterface *pThis, const VXIMap *properties, VXIrecGrammar *gram) { const wchar_t* fnname = L"VXIrecActivateGrammar"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecActivateGrammar\n"); if (gram == NULL) { logger = VXIrec_RESULT_INVALID_ARGUMENT; return VXIrec_RESULT_INVALID_ARGUMENT; } tp->ActivateGrammar(FromVXIrecGrammar(gram)); printf("VXIrecActivateGrammar returning success\n"); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecDeactivateGrammar(VXIrecInterface *pThis, VXIrecGrammar *gram) { const wchar_t* fnname = L"VXIrecDeactivateGrammar"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecDeactivateGrammar\n"); if (gram == NULL) { logger = VXIrec_RESULT_INVALID_ARGUMENT; return VXIrec_RESULT_INVALID_ARGUMENT; } tp->DeactivateGrammar(FromVXIrecGrammar(gram)); printf("VXIrecDeactivateGrammar returning success\n"); return VXIrec_RESULT_SUCCESS; } /******************************************************* * Recognize related *******************************************************/ static void RecognitionResultDestroy(VXIrecRecognitionResult **Result) { if (Result == NULL || *Result == NULL) return; VXIrecRecognitionResult * result = *Result; if (result->utterance != NULL) VXIContentDestroy(&result->utterance); if (result->xmlresult != NULL) VXIContentDestroy(&result->xmlresult); if (result->markname != NULL) VXIStringDestroy(&result->markname); delete result; *Result = NULL; } static void TransferResultDestroy(VXIrecTransferResult **Result) { if (Result == NULL || *Result == NULL) return; VXIrecTransferResult * result = *Result; if (result->utterance != NULL) VXIContentDestroy(&result->utterance); if (result->xmlresult != NULL) VXIContentDestroy(&result->xmlresult); if (result->markname != NULL) VXIStringDestroy(&result->markname); delete result; *Result = NULL; } static const unsigned int NLSML_NOINPUT_SIZE = 109; static const VXIchar NLSML_NOINPUT[NLSML_NOINPUT_SIZE] = L"<?xml version='1.0'?>" L"<result>" L"<interpretation>" L"<instance/>" L"<input><noinput/></input>" L"</interpretation>" L"</result>\0"; static const unsigned int NLSML_NOMATCH_SIZE = 109; static const VXIchar NLSML_NOMATCH[NLSML_NOMATCH_SIZE] = L"<?xml version='1.0'?>" L"<result>" L"<interpretation>" L"<instance/>" L"<input><nomatch/></input>" L"</interpretation>" L"</result>\0"; void DestroyNLSMLBuffer(VXIbyte ** buffer, void * ok) { // Return immediate if we know the buffer is static memory, // i.e: noinput, nomatch as defined above if (ok == NULL || buffer == NULL) return; // otherwise reclaim the memory delete[] (*buffer); *buffer = NULL; } static VXIrecResult VXIrecRecognize(VXIrecInterface *pThis, const VXIMap *properties, VXIrecRecognitionResult **recogResult) { const wchar_t* fnname = L"VXIrecRecognize"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecRecognize\n"); VXIchar* input = L"111#"; VXIMap* res = NULL; VXIchar* str = NULL; VXIchar console[512]; bool recordUtterance = false; bool haveUtterance = true; VXIint32 dtmf_timeout = -1; VXIint32 dtmf_interdigit_timeout = -1; VXIint32 dtmf_timeout_terminator = -1; VXIchar* dtmf_terminator_char = NULL; if (properties != NULL) { const VXIValue *rec_dtmf_timeout = VXIMapGetProperty(properties, REC_DTMF_TIMEOUT); if (VXIValueGetType(rec_dtmf_timeout) == VALUE_INTEGER) dtmf_timeout = VXIIntegerValue((VXIInteger*)rec_dtmf_timeout); const VXIValue *rec_dtmf_interdigit_timeout = VXIMapGetProperty(properties, REC_DTMF_TIMEOUT_INTERDIGIT); if (VXIValueGetType(rec_dtmf_interdigit_timeout) == VALUE_INTEGER) dtmf_interdigit_timeout = VXIIntegerValue((VXIInteger*)rec_dtmf_interdigit_timeout); const VXIValue *rec_dtmf_timeout_terminator = VXIMapGetProperty(properties, REC_DTMF_TIMEOUT_TERMINATOR); if (VXIValueGetType(rec_dtmf_timeout_terminator) == VALUE_INTEGER) dtmf_timeout_terminator = VXIIntegerValue((VXIInteger*)rec_dtmf_timeout_terminator); const VXIValue *rec_dtmf_terminator_char = VXIMapGetProperty(properties, REC_DTMF_TERMINATOR_CHAR); if (VXIValueGetType(rec_dtmf_terminator_char) == VALUE_STRING) dtmf_terminator_char = (VXIchar*)VXIStringCStr((const VXIString*)rec_dtmf_terminator_char); const VXIValue * ru = VXIMapGetProperty(properties, REC_RECORDUTTERANCE); if (ru) recordUtterance = wcscmp(VXIStringCStr((const VXIString*)ru), L"true") == 0; const VXIValue * val = VXIMapGetProperty(properties, L"SpeechInput"); if (val) { logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"SpeechInput: ", VXIStringCStr((const VXIString*)val)); } if (val == NULL || VXIValueGetType(val) != VALUE_STRING) { val = VXIMapGetProperty(properties, L"DTMFInput"); if (val) { logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"DTMFInput: ", VXIStringCStr((const VXIString*)val)); } } VXIString* vect = (VXIString*) val; if (vect != NULL) input = (VXIchar*) VXIStringCStr(vect); if (input && wcscmp(input, L"-") == 0) { unsigned int i; VXIchar* cp = console; char lbuf[512]; printf("Console: "); fgets(lbuf, 511, stdin); // copy to VXIchar for(i = 0; i < strlen(lbuf); ++i) { if (lbuf[i] == '\r' || lbuf[i] == '\n') continue; *cp++ = lbuf[i] & 0x7f; } *cp++ = 0; input = console; logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"Input: ", (input ? input : L"NULL")); } } // Create a new results structure. const unsigned int CHARSIZE = sizeof(VXIchar) / sizeof(VXIbyte); VXIContent * xmlresult = NULL; // Looking for matched phrase, if not act appropriately vxistring nlsmlresult; bool terminate = input ? (wcscmp(input, dtmf_terminator_char) == 0) : false; bool recogComplete = false; bool found = false; for (int i = 0; i < wcslen(input); i++) { logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"Input: ", &input[i]); if (terminate) break; found = tp->ConstructNLSMLForInput(&input[i], nlsmlresult, recogComplete); if (recogComplete) { if (!found) { if (!input || input[0] == L'\0') { // No input case haveUtterance = false; logger.logDiag(DIAG_TAG_RECOGNITION, L"%s", L"-- NO_INPUT RESULT --"); xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT, (VXIbyte *) NLSML_NOINPUT, NLSML_NOINPUT_SIZE * CHARSIZE, DestroyNLSMLBuffer, NULL); } else { // No match case logger.logDiag(DIAG_TAG_RECOGNITION, L"%s", L"-- NO_MATCH RESULT --"); xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT, (VXIbyte *) NLSML_NOMATCH, NLSML_NOMATCH_SIZE * CHARSIZE, DestroyNLSMLBuffer, NULL); } } else { // Found matched grammar logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"NLSML_RESULT: ", nlsmlresult.c_str()); unsigned int BUFFERSIZE = (nlsmlresult.length() + 1) * CHARSIZE; VXIbyte * buffer = new VXIbyte[BUFFERSIZE]; if (buffer == NULL) return VXIrec_RESULT_OUT_OF_MEMORY; memcpy(buffer, nlsmlresult.c_str(), BUFFERSIZE); xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT, buffer, BUFFERSIZE, DestroyNLSMLBuffer, buffer); if (xmlresult == NULL) { delete [] buffer; return VXIrec_RESULT_OUT_OF_MEMORY; } } } } if (!xmlresult) { //xmlresult null means matching failed but result wasn't generated logger.logDiag(DIAG_TAG_RECOGNITION, L"%s", L"-- NO_MATCH RESULT --"); xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT, (VXIbyte *) NLSML_NOMATCH, NLSML_NOMATCH_SIZE * CHARSIZE, DestroyNLSMLBuffer, NULL); } VXIrecRecognitionResult * result = new VXIrecRecognitionResult(); if (result == NULL) { VXIContentDestroy(&xmlresult); return VXIrec_RESULT_OUT_OF_MEMORY; } result->Destroy = RecognitionResultDestroy; result->markname = NULL; result->marktime = 0; result->xmlresult = xmlresult; if (!haveUtterance ||!recordUtterance) { result->utterance = NULL; result->utteranceDuration = 0; } else { result->utteranceDuration = 5000; // 5sec unsigned int waveformSizeBytes = (result->utteranceDuration / 1000 ) * 8000 * sizeof(unsigned char); unsigned char * c_waveform = new unsigned char[waveformSizeBytes]; if (c_waveform == NULL) { result->utterance = NULL; result->utteranceDuration = 0; } else { for (unsigned int i = 0; i < waveformSizeBytes; ++i) c_waveform[i] = i & 0x00ff; result->utterance = VXIContentCreate(VXIREC_MIMETYPE_ULAW, c_waveform, waveformSizeBytes, ResultContentDestroy, NULL); } } *recogResult = result; printf("VXIrecRecognize returning success\n"); return VXIrec_RESULT_SUCCESS; } static VXIrecResult VXIrecGetMatchedGrammar(VXIrecInterface *pThis, const VXIchar *grammarID, const VXIrecGrammar **gram) { const wchar_t* fnname = L"VXIrecGetMatchedGrammar"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecGetMatchedGrammar\n"); if (grammarID == NULL || gram == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; VXIrecGrammar * mgram = NULL; SWIswscanf(grammarID, L"%p", &mgram); *gram = mgram; logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%p", L"Got Matched grammar: ", mgram); printf("VXIrecGetMatchedGrammar returning success\n"); return VXIrec_RESULT_SUCCESS; } static void RecordResultDestroy(VXIrecRecordResult **Result) { if (Result == NULL || *Result == NULL) return; VXIrecRecordResult * result = *Result; if (result->waveform != NULL) VXIContentDestroy(&result->waveform); if (result->xmlresult != NULL) VXIContentDestroy(&result->xmlresult); delete result; *Result = NULL; } static VXIrecResult VXIrecRecord(VXIrecInterface *pThis, const VXIMap *props, VXIrecRecordResult **recordResult) { const wchar_t* fnname = L"VXIrecRecord"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); if (recordResult == NULL) { logger = VXIrec_RESULT_INVALID_ARGUMENT; return VXIrec_RESULT_INVALID_ARGUMENT; } // (1) Create record structure VXIrecRecordResult *result = new VXIrecRecordResult(); if (result == NULL) { logger = VXIrec_RESULT_OUT_OF_MEMORY; return VXIrec_RESULT_OUT_OF_MEMORY; } result->Destroy = RecordResultDestroy; result->waveform = NULL; result->xmlresult = NULL; result->duration = 0; result->termchar = 0; result->maxtime = FALSE; result->markname = NULL; result->marktime = 0; *recordResult = result; VXIlong duration = -1; VXIlong maxtime = 0; VXIlong finalsilence = 0; // (2) Get maxtime const VXIValue* val = VXIMapGetProperty(props, REC_MAX_RECORDING_TIME); if (val != NULL && VXIValueGetType(val) == VALUE_INTEGER ) maxtime = VXIIntegerValue(reinterpret_cast<const VXIInteger *>(val)); else maxtime = 1000 * 20; // in milliseconds (default to 20 secs) // (2.1) adjust duration for simulator if( duration < 0 ) duration = maxtime; (*recordResult)->duration = duration; if( duration == maxtime ) (*recordResult)->maxtime = TRUE; // (2.2) Get MIME type VXIchar *mimeType = VXI_MIME_WAV; val = VXIMapGetProperty(props, REC_RECORD_MIME_TYPE); if (val != NULL && VXIValueGetType(val) == VALUE_STRING) mimeType = (VXIchar*)VXIStringCStr((const VXIString*)val); // TODO: this should use the media type. For now just construct // raw ulaw audio with silence unsigned int waveformSizeBytes = (duration / 1000 ) * 8000 * sizeof(unsigned char); unsigned char * c_waveform = new unsigned char[waveformSizeBytes]; if (c_waveform == NULL) { (*recordResult)->Destroy(recordResult); tp->LogError(400, L"%s%s", L"Error", L"out of memory"); return VXIrec_RESULT_OUT_OF_MEMORY; } for (unsigned int i = 0; i < waveformSizeBytes; ++i) c_waveform[i] = i & 0x00ff; (*recordResult)->waveform = VXIContentCreate(VXIREC_MIMETYPE_ULAW, c_waveform, waveformSizeBytes, ResultContentDestroy, NULL); if((*recordResult)->waveform == NULL ) { (*recordResult)->Destroy(recordResult); tp->LogError(400, L"%s%s", L"Error", L"out of memory"); return VXIrec_RESULT_OUT_OF_MEMORY; } printf("VXIrecRecord returning success\n"); return VXIrec_RESULT_SUCCESS; } static VXIbool VXIrecSupportsHotwordTransfer( struct VXIrecInterface * pThis, const VXIMap * properties, const VXIchar * transferDest) { VXIbool result = FALSE; printf("VXIrecSupportsHotwordTransfer\n"); // this is really just to demonstrate how the platform could // support hotword for some type of transfers, but not others. // this could just as easily been based on other properties of // the transfer. i.e., destination type, required line type, etc... const VXIValue* dval = VXIMapGetProperty(properties, TEL_TRANSFER_TYPE); if( dval && VXIValueGetType(dval) == VALUE_STRING ){ const wchar_t* hid = VXIStringCStr(reinterpret_cast<const VXIString *>(dval)); if (wcscmp(hid, L"consultation") == 0) return FALSE; } dval = VXIMapGetProperty(properties, L"SupportsHotwordTransfer"); if( dval && VXIValueGetType(dval) == VALUE_STRING ){ const wchar_t* hid = VXIStringCStr(reinterpret_cast<const VXIString *>(dval)); result = (wcscmp(hid, L"true") == 0) ? TRUE : FALSE; } return result; } static VXIrecResult VXIrecHotwordTransfer ( struct VXIrecInterface * pThis, struct VXItelInterface * tel, const VXIMap *properties, const VXIchar* transferDest, VXIrecTransferResult ** transferResult ) { const wchar_t* fnname = L"VXIrecHotwordTransfer"; VXIrecData* tp = GetRecData(pThis); if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); VXIrecResult res = VXIrec_RESULT_SUCCESS; printf("VXIrecHotwordTransfer\n"); // this is probably not how it would be done in real life...but for this // sample app it will suffice: // Do the transfer int activeGrammars = tp->GetActiveCount(); VXIMap *xferResp = NULL; VXItelResult xferResult = tel->TransferBridge(tel, properties, transferDest, &xferResp); if (xferResult != VXItel_RESULT_SUCCESS) { res = VXIrec_RESULT_FAILURE; } else if (activeGrammars == 0) { *transferResult = new VXIrecTransferResult(); (*transferResult)->Destroy = TransferResultDestroy; (*transferResult)->utterance = NULL; (*transferResult)->markname = NULL; (*transferResult)->marktime = 0; (*transferResult)->xmlresult = NULL; const VXIValue * v = VXIMapGetProperty(xferResp, TEL_TRANSFER_DURATION); if (v != NULL && VXIValueGetType(v) == VALUE_INTEGER) (*transferResult)->duration = VXIIntegerValue(reinterpret_cast<const VXIInteger*>(v)); v = VXIMapGetProperty(xferResp, TEL_TRANSFER_STATUS); if (v != NULL && VXIValueGetType(v) == VALUE_INTEGER) { long temp = VXIIntegerValue(reinterpret_cast<const VXIInteger *>(v)); (*transferResult)->status = VXItelTransferStatus(temp); } VXIMapDestroy(&xferResp); } else { // get input from the user. VXIrecRecognitionResult *recResult = NULL; VXIrecResult localRes = pThis->Recognize(pThis, properties, &recResult); if (localRes == VXIrec_RESULT_SUCCESS){ *transferResult = new VXIrecTransferResult(); if ((*transferResult) == NULL) { recResult->Destroy(&recResult); VXIMapDestroy(&xferResp); return VXIrec_RESULT_OUT_OF_MEMORY; } // setup the transfer result by first copying the // RecResult. (*transferResult)->Destroy = TransferResultDestroy; (*transferResult)->utterance = recResult->utterance; (*transferResult)->markname = recResult->markname; (*transferResult)->marktime = recResult->marktime; (*transferResult)->xmlresult = recResult->xmlresult; (*transferResult)->duration = 0; (*transferResult)->status = VXItel_TRANSFER_FAR_END_DISCONNECT; // we no long need the rec result (but we don't want the VXIContent // fields destroyed). recResult->utterance = NULL; recResult->xmlresult = NULL; recResult->Destroy(&recResult); // translate the status and duration to the transfer result fields. // since this code is simply so that Hotword transfers work, any // valid recognition (ignoring noinput and nomatch) will set the // transfer to "near_end_disconnect". Otherwise, we pretend that // the other end terminated the transfer. if((*transferResult)->xmlresult){ // we're going to ignore noinput and nomatch results. const VXIchar * contentType; const VXIbyte * content; VXIulong contentSize = 0; VXIContentValue((*transferResult)->xmlresult, &contentType, &content, &contentSize); // we're going to ignore noinput and nomatch results. if ( !wcsstr((VXIchar*)content, L"<noinput/>") && !wcsstr((VXIchar*)content, L"<nomatch/>")){ (*transferResult)->status = VXItel_TRANSFER_NEAR_END_DISCONNECT; } } const VXIValue * v = VXIMapGetProperty(xferResp, TEL_TRANSFER_DURATION); if (v != NULL && VXIValueGetType(v) == VALUE_INTEGER) (*transferResult)->duration = VXIIntegerValue(reinterpret_cast<const VXIInteger*>(v)); VXIMapDestroy(&xferResp); } } printf("VXIrecHotwordTransfer return res: %d\n", res); return res; } /******************************************************* * Init and factory routines *******************************************************/ static inline VXIrecImpl * ToVXIrecImpl(VXIrecInterface * i) { return reinterpret_cast<VXIrecImpl *>(i); } // Global init - Don't need to do much here // VXIREC_API VXIrecResult VXIrecInit(VXIlogInterface *log, VXIunsigned diagLogBase, VXIMap *args) { if (!log) return VXIrec_RESULT_INVALID_ARGUMENT; gblDiagLogBase = diagLogBase; const wchar_t* fnname = L"VXIrecInit"; LogBlock logger(log, gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecInit\n"); memset(recImplTable, 0, sizeof(recImplTable)); for (int i = 0; i < (sizeof(recImplTable)/sizeof(recImplTable[0])); i++) { recImplTable[i] = NULL; } logger = VXIrecData::Initialize(log, diagLogBase); return VXIrec_RESULT_SUCCESS; } // Global shutdown // VXIREC_API VXIrecResult VXIrecShutDown(VXIlogInterface *log) { if (!log) return VXIrec_RESULT_INVALID_ARGUMENT; const wchar_t* fnname = L"VXIrecShutDown"; LogBlock logger(log, gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecShutDown\n"); logger = VXIrecData::ShutDown(); return VXIrec_RESULT_SUCCESS; } // Create an VXIrecInterface object and return. // VXIREC_API VXIrecResult VXIrecCreateResource(VXIlogInterface *log, VXIinetInterface *inet, VXIcacheInterface *cache, VXIpromptInterface *prompt, VXItelInterface *tel, VXIrecInterface **rec) { if (!log) return VXIrec_RESULT_INVALID_ARGUMENT; const wchar_t* fnname = L"VXIrecCreateResource"; LogBlock logger(log, gblDiagLogBase, fnname, VXIREC_MODULE); printf("VXIrecCreateResource\n"); VXIrecImpl* pp = new VXIrecImpl(); if (pp == NULL) { logger = VXIrec_RESULT_OUT_OF_MEMORY; return VXIrec_RESULT_OUT_OF_MEMORY; } VXIrecData* tp = new VXIrecData(log, inet); if (tp == NULL) { logger = VXIrec_RESULT_OUT_OF_MEMORY; return VXIrec_RESULT_OUT_OF_MEMORY; } pp->recData = tp; pp->intf.GetVersion = VXIrecGetVersion; pp->intf.GetImplementationName = VXIrecGetImplementationName; pp->intf.BeginSession = VXIrecBeginSession; pp->intf.EndSession = VXIrecEndSession; pp->intf.LoadGrammarURI = VXIrecLoadGrammarFromURI; pp->intf.LoadGrammarString = VXIrecLoadGrammarFromString; pp->intf.LoadGrammarOption = VXIrecLoadGrammarOption; pp->intf.ActivateGrammar = VXIrecActivateGrammar; pp->intf.DeactivateGrammar = VXIrecDeactivateGrammar; pp->intf.FreeGrammar = VXIrecFreeGrammar; pp->intf.Recognize = VXIrecRecognize; pp->intf.Record = VXIrecRecord; pp->intf.HotwordTransfer = VXIrecHotwordTransfer; pp->intf.SupportsHotwordTransfer = VXIrecSupportsHotwordTransfer; pp->intf.GetMatchedGrammar = VXIrecGetMatchedGrammar; *rec = &pp->intf; printf("VXIrecCreateResource returning success\n"); return VXIrec_RESULT_SUCCESS; } // Free VXIrec structure allocated in VXIrecCreateResource. // VXIREC_API VXIrecResult VXIrecDestroyResource(VXIrecInterface **rec) { if (rec == NULL || *rec == NULL) return VXIrec_RESULT_INVALID_ARGUMENT; VXIrecImpl* recImpl = reinterpret_cast<VXIrecImpl*>(*rec); printf("VXIrecDestroyResource\n"); VXIrecData * tp = recImpl->recData; if ( tp ) { const wchar_t* fnname = L"VXIrecDestroyResource"; LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE); delete tp; } delete recImpl; *rec = NULL; return VXIrec_RESULT_SUCCESS; } |
From: Anshuman S. R. <ar...@3c...> - 2012-05-29 06:48:33
|
Yes. We might be moving our solution over to Linux in 3-6 months so you inputs will definitely be helpful. Do let me know how it goes. I don't think there's anyone else besides us on this mailing list and I had a tough time getting everything sorted out when we took up this solution for our IVR (that was about 6 months ago). Thanks, Anshuman ----- Original Message ----- From: Lauters Mehdi To: Anshuman S. Rawat Sent: Tuesday, May 29, 2012 1:32 AM Subject: Re: [Openvxi-discuss] Compiling openvxi on latest ubuntu platform Thanks for that! Are you interrested if I get it working? Regards Mehdi ------------------------------------------------------------------------------ No virus found in this incoming message. Checked by AVG - www.avg.com Version: 9.0.930 / Virus Database: 2410.1.1/5027 - Release Date: 05/28/12 12:04:00 |
From: Anshuman S. R. <ar...@3c...> - 2012-05-23 08:35:38
|
Hi, We recently (about a month ago) moved to mozjs 1.8.5 on windows and it seems to be working fine as of now. Unfortunately, the person who did this is no longer with the company anymore. So it will take me some time to figure out how he did this. If you are still stuck, I can try to take a look. But he did have to update some APIs in SBjsi to work with the new version. Regards, Anshuman ----- Original Message ----- From: Lauters Mehdi To: ope...@li... Sent: Tuesday, May 22, 2012 2:39 AM Subject: [Openvxi-discuss] Compiling openvxi on latest ubuntu platform Hi, I'm trying for a while to compile openvxi on a recent linux distribution, with libmozjs.1.8.5-1.0.0ubuntu8 but i get an error In file included from openvxi-3.4/src/jsi/SBjsi.cpp:48:0: openvxi-3.4/src/jsi/JsiRuntime.hpp:90:17: erreur: expected ‘;’ at end of member declaration openvxi-3.4/src/jsi/JsiRuntime.hpp:90:77: erreur: ISO C++ forbids declaration of ‘GCCallback’ with no type [-fpermissive] and this is this line: static JSBool JS_DLL_CALLBACK GCCallback (JSContext *cx, JSGCStatus status); What could be wrong? Thanks ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ------------------------------------------------------------------------------ _______________________________________________ Openvxi-discuss mailing list Ope...@li... https://lists.sourceforge.net/lists/listinfo/openvxi-discuss ------------------------------------------------------------------------------ No virus found in this incoming message. Checked by AVG - www.avg.com Version: 9.0.930 / Virus Database: 2410.1.1/5013 - Release Date: 05/21/12 12:04:00 |
From: Lauters M. <meh...@gm...> - 2012-05-21 21:09:49
|
Hi, I'm trying for a while to compile openvxi on a recent linux distribution, with libmozjs.1.8.5-1.0.0ubuntu8 but i get an error In file included from openvxi-3.4/src/jsi/SBjsi.cpp:48:0: openvxi-3.4/src/jsi/JsiRuntime.hpp:90:17: erreur: expected ‘;’ at end of member declaration openvxi-3.4/src/jsi/JsiRuntime.hpp:90:77: erreur: ISO C++ forbids declaration of ‘GCCallback’ with no type [-fpermissive] and this is this line: static JSBool JS_DLL_CALLBACK GCCallback (JSContext *cx, JSGCStatus status); What could be wrong? Thanks |
From: Anshuman S. R. <ar...@3c...> - 2011-07-22 07:39:18
|
Hi, I am not sure if anyone is even active on this list but all the same. I am trying to build openvxi on windows with VS2005. Now after downloading none of the VC6 projects actually opened (reportedly file is corrupt). So I have tried to make new projects by adding some/all files as I could after going through the linux makefile and following the instructions at http://www.speech.cs.cmu.edu/openvxi/OpenVXI_3.0/OpenSpeech_Browser_PIK/doc/OpenVXIBuildInstructions.html. But I noticed sources in JSI folder are not included in build instructions. Is that intentional or has it been missed? Thanks, Anshuman |
From: BD G. <bd...@te...> - 2010-12-29 16:54:16
|
Dear All, I am very new to open VXI. I have installed the open VXI on linux and had done a test run of VXIclient on helloworld.vxml. But after this, I am not able to understand how to move ahead. I wanted to make a simple application which can accept a call and can play one prompt. On the telephony side, I have dialogic installed. Helloworld.vxml file is there. But now how to move ahead. I have seen a VXIclient source code but that's getting very complex.. .. Is it some other way in which I can work on openVXI API. Best Regards, BD |
From: Rajesh B. <ban...@gm...> - 2010-10-29 11:31:09
|
Hi Friends, I am getting folling error during installation of OpenVXI 3.0.0 Please help me to resolve this ../VXIinterfaces/mkinstalldirs /usr/local/lib chmod go-w,a+x /usr/local/lib ../VXIinterfaces/mkinstalldirs build/i386-linux/debug/lib chmod go-w,a+x build/i386-linux/debug/lib ../VXIinterfaces/mkinstalldirs build/i386-linux/debug/lib/./ build/i386-linux/debug/lib/trdUtil/ chmod go-w,a+x build/i386-linux/debug/lib/./ build/i386-linux/debug/lib/trdUtil/ make -f Makefile build/i386-linux/debug/lib/libSBtrdUtilD.a TARGET=SBtrdUtil \ DEPS=SBtrdUtil_SRC make[1]: Entering directory `/root/RPMS/OpenSpeech_Browser_PIK/src/trd' make[1]: `build/i386-linux/debug/lib/libSBtrdUtilD.a' is up to date. make[1]: Leaving directory `/root/RPMS/OpenSpeech_Browser_PIK/src/trd' ../VXIinterfaces/mkinstalldirs /usr/local/include chmod go-w,a+x /usr/local/include cp -p trdUtil/SBtrdMutex.hpp trdUtil/SBtrdRefCount.hpp trdUtil/SBtrdEvent.hpp trdUtil/SBtrdTimeOfDay.hpp /usr/local/include rm -f /usr/local/lib/libSBtrdUtilD.a cp -p build/i386-linux/debug/lib/libSBtrdUtilD.a /usr/local/lib rm -f /usr/local/lib/libSBtrdD.so.3 cp -p build/i386-linux/debug/lib/libSBtrdD.so.3 /usr/local/lib cp: cannot stat `build/i386-linux/debug/lib/libSBtrdD.so.3': No such file or directory make: *** [SBtrd-install-shared] Error 1 make -f Makefile build/i386-linux/debug/lib/libVXIvalueD.so TARGET=VXIvalue \ DEPS=VXIvalue_SRC make[1]: Entering directory `/root/RPMS/OpenSpeech_Browser_PIK/src/value' g++ -g -O0 -fPIC -D_i386_ -D_linux_ -I../i386-linux/include -I../include -I/usr/local/include -I./include -I./ -D_SIMPLE_R -D_REENTRANT -D_GNU_SOURCE -D__THREADED -DCOMPANY_DOMAIN=L\"com.speechworks\" -DMODULE_PREFIX=L\"swi:\" -c /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueBasic.cpp -o build/i386-linux/debug/lib/ValueBasicD.o chmod go-w,a-x build/i386-linux/debug/lib/ValueBasicD.o g++ -g -O0 -fPIC -D_i386_ -D_linux_ -I../i386-linux/include -I../include -I/usr/local/include -I./include -I./ -D_SIMPLE_R -D_REENTRANT -D_GNU_SOURCE -D__THREADED -DCOMPANY_DOMAIN=L\"com.speechworks\" -DMODULE_PREFIX=L\"swi:\" -c /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp -o build/i386-linux/debug/lib/ValueToStringD.o /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp:71: error: âclass std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> >::size_typeâ is not a type /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp: In function âvoid ensureCapacity(std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> >&, int)â: /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp:73: error: expected `;' before ârequiredCapacityâ /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp:74: error: ârequiredCapacityâ was not declared in this scope /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp: In function âvoid ensureCapacity(std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> >&, int) [with T = wchar_t]â: /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp:209: instantiated from here /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp:73: error: dependent-name âstd::basic_string<_CharT,std::char_traits<_CharT>,std::allocator<_CharT> >::size_typeâ is parsed as a non-type, but instantiation yields a type /root/RPMS/OpenSpeech_Browser_PIK/src/value/ValueToString.cpp:73: note: say âtypename std::basic_string<_CharT,std::char_traits<_CharT>,std::allocator<_CharT> >::size_typeâ if a type is meant make[1]: *** [build/i386-linux/debug/lib/ValueToStringD.o] Error 1 make[1]: Leaving directory `/root/RPMS/OpenSpeech_Browser_PIK/src/value' make: *** [VXIvalue-shared] Error 2 Best Regards, Rajesh Bansal |
From: NaturalViagra P. <hoy...@t-...> - 2010-09-28 08:13:31
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Newsletter</title> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> </head> <body> <table width="99%" border="0" cellspacing="0" cellpadding="0" > <tr height="50"> <td valign="bottom"><font face="arial" size="7" color="gray"> Newsletter</font></td> </tr> <tr height="20" style="color:gray;font-size:11px;font-family:Arial,Helvetica,sans-serif;"> <td><strong style="font-size:13px;">Tuesday, Sep 28, 2010</strong></td> <td align="right"><a href="http://rc.medlabhn.ru/?The=37427A17F31423E2c4433E90c1c" style="color:#0066CC;"> Subscribe</a> or <a href="http://gm.medlabhn.ru/?spiral=D1894C3690E1f567276cE2a" style="color:#0066CC;" > unsubscribe</a> from this newsletter</td> </tr></table> <font face="Arial,Helvetica,sans-serif" size="2"> <ol style="font-family:Arial,Helvetica,sans-serif;color:red;font-size: 10px;padding-top:0"> <div style="background-color:#CCE0F5;padding:15px 25px;margin:0px 0px 20px -40px; text-align: center;"> <a href="http://jlz.medlabhn.ru/?built=dF677fd21D150c6559C7f"> <img alt="Click here" src="http://zmbe.medlabhn.ru/logo.jpg" style="border-width: 0px" /></a></div> </ol> </font> <ul> </font> <p><a href="http://muh.medlabhn.ru/?Hence=068514520286A075bF6Ad0bBD34C" style="color:#0066CC;"> Subscriptions</a> | <a href="http://u.medlabhn.ru/?aspects=cDbe0a4FE862D42Af4eCaa61" style="color:#0066CC;"> Customer Service</a> | <a href="http://s.medlabhn.ru/?passed=B56533B7742d0d8D3889313E&delete=ope...@li..." style="color:#0066CC;"> Unsubscribe</a> | <a href="http://stt.medlabhn.ru/?with=340fB7FF23e4B1b8d7aC6eD34" style="color:#0066CC;"> Contact the Editor</a></p> <p>This message was sent to ope...@li....</p> <p>Review our <a href="http://g.medlabhn.ru/?the=2F3Df5C2e10Aa84DCED70bB6ACe0a" style="color:#0066CC;"> privacy policy</a>.</p> </ul> </font> </body> </html> |