From 3d4dc546f537fc68cc57d2fc18b5627904455f8e Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Fri, 13 Jul 2018 14:53:33 +0900 Subject: [PATCH 01/16] Add a program to get vc engine app id Change-Id: Ib2a0c901a9034e9fe1c942749ca69500cc9512ab Signed-off-by: sooyeon.kim (cherry picked from commit b5bfc019092b25ed8845ae5b97d8b9d2962c2da5) --- CMakeLists.txt | 16 ++++++++++++++++ bin/aarch64/vc_getengine | Bin 0 -> 12464 bytes bin/armv7l/vc_getengine | Bin 0 -> 8776 bytes bin/i586/vc_getengine | Bin 0 -> 13852 bytes bin/x86_64/vc_getengine | Bin 0 -> 14672 bytes org.tizen.voice.vcserver.service | 3 ++- packaging/voice-control.spec | 11 ++++++----- 7 files changed, 24 insertions(+), 6 deletions(-) create mode 100755 bin/aarch64/vc_getengine create mode 100755 bin/armv7l/vc_getengine create mode 100755 bin/i586/vc_getengine create mode 100755 bin/x86_64/vc_getengine diff --git a/CMakeLists.txt b/CMakeLists.txt index 8819be3..22994bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,9 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "${PREFIX}") SET(VERSION 0.2.10) +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") + ADD_DEFINITIONS("-DVOICE_LIBDIR=\"${LIBDIR}\"") ADD_DEFINITIONS("-Werror") @@ -71,3 +74,16 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/vc-config.xml DESTINATION ${TZ_SYS_RO_SHARE}/v INSTALL(FILES ${CMAKE_SOURCE_DIR}/org.tizen.voice.vcserver.service DESTINATION ${TZ_SYS_RO_SHARE}/dbus-1/services) INSTALL(FILES ${CMAKE_SOURCE_DIR}/vc-server.conf DESTINATION /etc/dbus-1/session.d) + +## vc_getengine ## +IF("${ARCH}" MATCHES "^arm.*") +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/bin/armv7l/vc_getengine DESTINATION ${TZ_SYS_BIN}) +ELSEIF("${ARCH}" MATCHES "^i586.*") +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/bin/i586/vc_getengine DESTINATION ${TZ_SYS_BIN}) +ELSEIF("${ARCH}" MATCHES "^i686.*") +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/bin/i586/vc_getengine DESTINATION ${TZ_SYS_BIN}) +ELSEIF("${ARCH}" MATCHES "^aarch64.*") +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/bin/aarch64/vc_getengine DESTINATION ${TZ_SYS_BIN}) +ELSEIF("${ARCH}" MATCHES "^x86_64.*") +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/bin/x86_64/vc_getengine DESTINATION ${TZ_SYS_BIN}) +ENDIF() diff --git a/bin/aarch64/vc_getengine b/bin/aarch64/vc_getengine new file mode 100755 index 0000000000000000000000000000000000000000..126ccd9184615bc3e1151e8c3dee309863fab7be GIT binary patch literal 12464 zcmd^Fe{|HAXnV`XLS%w#f2MuwR%Gr>UG zbwFC_cK4WXL7{HdA#^=v+U=$_9?9+=iRkWetEaVC(OP9=s2;XG>tgW-qsH0KecyNE zW5|H#bpP9z^K#$4@80|Fz3;yFec$(;d)BO9Yq!}17l(LC5cX1qMRBQ){)MUm;1a7u z5&q8>my1H+6C};*cUb_vRvA*N85SwJ1F(SFc16g6mn$+uwvZr=m#_SOuGPa(NN=qF zWa}x_e`>C!kzqd>gfgTc%aK_mC+5*VlzGY$1r234L-vn+qdHsl=fVckg~E_{scd*V z(L(KtITAe&UT2X7Lzeps$Vod@|HVM5VptpwH7^dgEDDDron4Fk{#c-W<#J~{>Re*k zPkiL@4Y%ATB`7=-Wy|U>Lz`&Szwnixtlj>z|9UQR`n$ir>+mHvKlIwf9tv9>>U`9d zs8mR2jci%}W&vD=It7*7UW7^oCWz^%Uq-D)U509)u0o}I~FMR4PsjeBuA(9~Jg{l7)`_r#YWGhFOggg%{`0DPEINXQN)C_0e*>RN<8KGf~SG zPM}J)zXZrjaW2|dpe{zGxxX6qO4OyOSD{|4I7Er);-G2F4pAn~s`bI-DG0))m?1+2 zk@JphX1ke};I&Aa@#r)+1~KH6O6WI4h1jzIf?9b8>!(!A5(jeVdq5vg{|3m8N8b*9 z%Awq{Igg$e(8mdl_yBaW=kXkSUY7KV^X%M^Cl2K@o>RqKPD*9i`+4;L0QB+vnwW=v zeIEK17`JqsIM2$%-o`=6q&es%?q6LQXO$&%38PD_cVUFVG=cr;A>lEFf4FKhv7*CcwdY;H* z=j)IgZ(Tel?T4MTaiY}H#)uNju+iCZt;gA-e4pV3kBoCyRPYGZ%Z&1YzxH`!C2GHo^Ui0Z1OjUgXc@P z#)3iN^|oz+#(2UXOL)EKGsS}mZ+kG@fgwms%lRA~{#bk*?UCT!!h6#;Z=`FubwFs<^u-fM7R*90K@n=bI~Gb% zN(8$6-qujW9}evxw5y{HL&oHcd1D}ubt+{j{lxgEJKfH!34^3|00KFIW>I;DvwqFa5SAQQWY8 zo!jGG>Rdu6KPp(9ve?kV0!F1j!l;jE7EXOs9KbCpi<@|?KjxQgipOe`hI2>yF$i>4 zHBk4P58{aB5O-ofphDV4F+BBCvHI;}{rq0xPzR;cbjU?Ht`Ie7N=X2J^ z96CRLe7SVB-}k6<3F~3JR`J_l51kdctkURwW~DxtMyGQ*mm4*@+R|m$293_|Y}C=N z(dnGZr9-3hd7b)t6x|Lx`HV^Q0~%dD(ugcl8eKn^Kd#aBGkCv7*Zn=L(dm57Wk{p* zTvOlk8eN56ioB%J>8#J?HH}X1B3y9fk-kxf zFh^`+-)Q$Uj}JM#$BBL#^d2Glr~SJpQ(AqcY1k`|R~n92xXQj?pwDgfN&J_G9x z@Ld{y9C)vWzYhGUhMxdFqTwUJ?UizDssA0|)f)Z>;BF0n7kIOV{|Wdm4gU~$uZDjN z{HTV127E-r?F|^;_Y_@%&iY4}Xwy&8TQ@S_@jCGZgquLf?f z`h5H^0k78Z8sKgXcLHzL@TI_aY4}Ruy&8TE@S_@jJ@63?cLTRq%kf9M|DkW~v}7Y5 zJ3WEq^(N)anOkjr%S5vAgH86n%;thVtoNR;Z@S+6BtD@JdqU5OIjc?V!95AbSImzB zj=r}YW$E8LW~N6RGtvi_iHskzsi+uq0Y0D2?mz6Yo6IA}@vSxs%aV=6PrSr;WVOiL zPVk=6g-7n0w(y@JXP=uqW&>^5QIY;@;7H$oJS@%BS4GA*8Dj+Ob&}=-Eg&*UqRnyC zr5tt><7Z@F5`EnwV@yHcN%T!e-+ihtg}%KalbV`r>|N%{qz)C-rRLbpgC}if>QTir zB+MrciNS-ni_F1gcJrxaw!zeo(MS3M6Y35=B{I8aivgE#WsEDt09NF&`(f*+4v`+N z5CeALZ^8Z=io>%u)ADC_x*7Oej_EbSj@fDAKXNVfKVdUZg17fxn@RLe$s;7s!OdcD z9`J*kU4vCq#d5^4zZEeIBqxl;mg70>D6hE-ys7(LgRV=&id57!SXm&p{`XYTR5=-N znrI^V!t!Jz&r85%H+A_tNS@@1#MY}JHxqtzV!oS@2g@-3k4f1XnD;Ww`*b;vq%)9o zm^7a^L4Iuo=^uy3RVaDt!SkJbJYu5cSp}ZQz(cxOS72x&Y_-Ouu@oWK?D=mF;6_~BFl8uzBXB?u2#=I0`lI+!h_Y~qPvA~LH>t*D#B_9|rfSt3(a(n`K z1!QseR+fZ6hpu&Ha0Kk9JP;{Q#+|g8fdUuu)|L6gXQaO(Eg(ZS1Yu(X?4$Xnd9Q|@ zymtNvyaw5JYkl7bo7{aL1w2@{4Sk=)*Yu5c|4#1xDa7R9uQn_!D{^I43$gWsiH}~E zcrQCJjQRT~$bX1@O%{lOGj_4u%FCJQouI$vn1TG8nf^Z7$!xa#Uf4qG%5F~{t3pl$ zV7C~C-LU!Jz%vYAPJqvWKFWRM`>_Jl$3XiQ`YC>=G(FY29>db}1o)l>55?#t?87*X z6eqWEm=q_9PcL{VE|iC#$Hrk|-zdjP7mpRue{Z!gk7Aux`MzR`VPOtJM(-QpK4CL| zF7;V9lf65jhhP^V`9f{1$MP!xuS9(t@p{YQ%8bkr<~!Ik$yU+t$xwU(Kk;OC1Mc4E z$=nFN0aV%lBTvR9#K5M{vgQ0d-U+@cU$t2^Tj`*-5HGA=CEn{3qDl52@MP*CXNbz< zB*)Kcf-EofE7__~J$tJ@t^XeC-e(}U3uCwsdos;vyP$*QSkGwp)AF2frbJ}+g3s67 zT<5Zh6;j_1JsH3O*}kzMGYNkD2Kh+2=4-C5J5%DyjCLQD`NcL#-r?!k=UjLWh$mk| z%*N~-@MLyovjcoKF~sWQbT;`Fc!VmtJ!c&D^iUD@P^^hvfXLhTaLknXCwxVwL+pHL z=TMPJ_WWryyFWfz4EXHWv#|D)6Gc;>-CFOyBCJiU&&t_iYyBkAhDl*9j zS`Xw092B4GJiV?U$7qzL-+Hf8++yr=0%c0yvOBn6`NJQVrlgl!$)Be$WSv&BbPXTG#2^S;BDrt=8p)xr68#5sA)H$^lh?XJ31p;-O^ z_z&%>HdBoa8Q&x^aL8f9-dlz>TAuzMas&HY4fUmv&vygI+$|Z#93E*b$owbm-_X@N zhn@%JkSR;!dDnO+ay@)UcBXVkxbPPLe zHQ0~Sl}Zoog)<>XHs1l-NyO?=yR}Ak8^tD#L(k0JV&6k z?jG8wt6a4>b2!o)K&Mzye0hZmLnEoywyVa0Ps`c25~gpcHZ6=Lya#G(RxR(wU8&kLXX zUY;&P|KCC9yO0$qquu{HmUH`{Yv0l7CgmCB)04f^&3*P6FHjzSh`s16;_?ylaNlR1 zy^ljaVG{$>5j)D|Lp$PUM-W@eH$1m%;)TNWVSjtnKK+kX*=&=ZBct8VjqRC~E4&}- z?`hUOlo0ZU4R*?VRB{U* z!{ZO*%D1YjipJB$3BQ0`bFdW`xW>5_!ZEDCyjS>v0fNxwzeQpDS;6 zrG#}gY)FDJe_nk4xx-&54*phL!W-wRyEuPqCoY&T7~i$H*NnHTdAWc;*7)a6!-d9I z^Jd*68yC03(tj@d7tn7ho=+d_QJP|%G9lLb!?**7Nl@(tNZkG)!`-Gsc0Nkb_0`xgSBiJr?Tzehp zbXU6PbT+#Yu;Qa^HU)V0Y&Khgjkze3&DH|$`6Qd|BK*^AwjYp6nFWMxN24g{y3%&} zWIRPt8c^vTZUJ=GPC%o6YQN**m5;1wm~ut^-sSt2c^+8$;F2FWA6m5L@2~#hRi6E| z2Nv5;6`y$XcW?am^;che<@n3Lfu{NrEKNZxvg5;SR(?~fpK3f@@Q9q+)6wR&iHCXB}9{KeK>T8Gv&U#~o{CXetCD7$J&HAY?6?q>1 z8`~q_wMm=y*!JCLbMN16J8-Y9;eqei9{jc~RQ%=%%_XU8IsRWqvHTc%h*Ce*^>EQ6 z6Qz#AeG@zn6g=o?*l#~zYdZ1fn6PCR_It4ba=KkoDgN>OJKwi6T}>Bm^R2@0D%D{8 zbPi5;|5Ui2z7c?Xcm7!x8-9mmN%CDe{f2}J-`(UZn!Xcl10ymQGYER4#s|@CqfLRk#{nVA)9ilnOMKpv2j4rR)C=@bA2=<@<&8 z@^>2k4*x|3d(@94{=Y$vPmj7U*UvM~mSA%yo-H?g`{WMclpiUbv8V;(?fCYY@Hd0L z9bb7v0pW~96G3NNq|+(ST#ImUaR%GHtugurY<1SV*DXr;+k~^-A8!{<`OT6f@Npgk z;iqt$rMmd`EkY{V7L3K|^Q1P9$IXFqi{M#*l)#eEOdGJ1n(^BO1G}cfA-j8?`-rpF< zySQBYET8+kMuQm@)A&7jks$MQbaV3y-Qv;WU2dACx?`#wW{PLMo38*=5J z2909E`!zo&8S?W5EVA&tG5#ND=<>PyWGOqQ1WI!ton3T!-k%xn<_BbsoI=H|Ir98m zXUO9*f3E$M`!qhA$-iS`$a%=}96!bn<;ds$PWU=zR4{k^6*=-7=U9vk|CWr?O78gY zqK_W+d`{qV4F9e=m!ENlBappBljn2J>A4`HFrS5ejx+rcbdZTWKL1Yj>_y~RADzE= zZA;qN@3}1wLro0lCy&eX`YPD;@eOrOGUi+I8!a&QpXC|;GDn`zSzSuLG*A3lp1Sq% z_o(OPo(0yBY$qGQa*Wf(D$zK82bBDQFDU<)kj*hss%ClKCnOR7a`R80d*&h7ug3pa KC!(D@*8c*lbA@sM literal 0 HcmV?d00001 diff --git a/bin/armv7l/vc_getengine b/bin/armv7l/vc_getengine new file mode 100755 index 0000000000000000000000000000000000000000..570f0cdce3dde6d7291e933066c130cabbb9f13c GIT binary patch literal 8776 zcmc&)dvsG(y5A>B+qAS;D`F_wZIu2QLAgbYq)}R-Ql{tcSJkNxEvp23wBa(OBi4X zLq>0;*41vXNyRFvmWE z;8Os#OL`rC_rrcabOa{o2uQESSOH!I0dfLWch7Lx1@=3I>SqE9ect*)pR2&<^*6Uz zLIKMXxi0D8mX+VV9>0uHKPeU}U=-1+t=kLsUY^u~iV6Xj2YZ-H(h zfNWC$-1Un~JM)hI%xGY1B1u9iL{}8DrLqW+54aUj0I&emVg<1nPy|4jmkT|cr3!bu zf=d*9hk}Hm;mKP`cOI>BB$PCRrgGl647 z68!B+(03;2YZCOd-qb?=H>eCS@x2;*is$JB`y7p)?EMM)js*QH8a@a1sR{NzEJoVr zsARDW)&Rb4j%<|4OzeK}y))(Ycs;w0-2;9G^-b&?;@_Kry$c%x#kUH2H#U(0gh+h$751}O2>h2A7>}a&fLHs&qdyD5 zYvU~k->vkI{B?jY249B`63?*DH3ABXELPg)tju1yZjIgL4!Rq?p|Cr+ZcUjl;CHWc z)cf4bZg1Qe@Y_RSM=)%+Gkeu0`@M=?na>dlxkGaGt5$Bb2b#iORCfmaVRuW|?ssoy zjdrKc?Fic4!C)W=F2SV95e&J%D{ct7uObb(!**|@KM-`=oBbR7fz5u!UFf?W94?oA zqr>aByZzyy7jb{5Y4YZA`TXl7rKJDv8B+8>A8QSZgrZT9+Ic4t!)`iA*nzlwMFpIP48xzr*KkBetcf5lsfANn{T~K+!4Fl%6uX z@=dOdud&$?bTPZzuG74>XOEdaUoj4K+H+c5hAHYXQ-LN@?sUNg&P;< zS91tc2U7*^6~|6_yyT~%t%-_ZR$g7Xy3Af=DQ4wmW%eZ&^#!h+GIV%rszrBM_U#!& z-VP1W5T$}lQB7G+=d17gC!fNia6xAt9x%h}#fD*EyOj{g!`Ik{RQ>w-t$4xf*;5+* z9ZG#vSL*97*QaycO^|mgxCHwu@zn}`NWm@zF9*Icm9bL7X*kaj#@=2*7<*<7;aQBW zBb>unE#U=>otVwBnTV;MF!tHggmKV(gD?(!ZxS|Q&m|21X9=Sx?-NdE>?6YH`5@ux zIENCxjOA?8!00IOP6?@Qrvc5XN46i7<5x@ys+~1PSBpY9u_Hv2?<7Fph+A z7N0>F2SpR%AD|jx9?yWVnX$Qqa~aDcJP&6=!t)uk5=MWE3FpCoX~Aa^j*S{4Cr1o} z1;d8H!^6`DcMTe2uMPKHhX?oiu5+3HyW?C>{KT+IcWdY!8u}3py+uQZHM9?OOL@Pj z`l{3DYBh9?hOW@ir5d_KLt8a;o`&W%v`Ir}YG|W|W*U0xn{WFZ)6gTJwSD+VqdTji z-_+2jHS`G${c8<n_d?kEfD-wSqq;w|l zPP@1=MQ?5wxV<`_?aR1WVvJAz>qP%V4SNSRY+omD{T~vwiJCE$aPg{Nt(O$Zud# z8taUtJjLage!e53$M1hex^2HPb9;->Yu#?PuU6EXL*D=SU5UPd+)m#kNTNFFYsRZj$KDI*h>MGrOwz+BV_jT;_>S z_Kw$A)mP}vZ9=_mWf9xssA>@~UpjT&Iy~$6WW_kg-_dt+B({s?W{a~#lgK(tMHXB5 zRqdME>fhy3ukJ^$?nkV8^H!?+hNMdza^)TqNo`+XdDw z$88#C{M*r_gPA!iZDz5eVzjnJn2o4bkMrVhqw&e?af5hY^mgcy_8WUvRrMq8BOZ!d zkUW2SVTJ7ozoLrfxUREJShi80j{@!myaS$Ww*#I89L2U?0$DnA|ABW2(Idd8 z0dE1?0C|wz3aEok9-tbsOL+e*0v;ouz*P4Tfc5pBXM?@x4Vec&&ER{73_SL2Rxq5` zdw6)Rb=Nt4@8g4f|KZ{E{sU1%f5EWHdU#lGJrJG24i6*J=$>!lqmKbj;3D)G-1PvC z0cOB%22ZxT26cQ_6umirOT3WV@lE{ydSJT)HYqk^MY~|cEYdHTo!urR=j;ENWP7(( z|B|V^sT^aM#<60+CfIkw-dLGh(JG|cT7=Z>cHw84-01IrT$!mKNUD13avdY=4S)*N z*-v#|NwcL@wF_;+?3NA3Q{g@LC8MofFkxQ&=t6w*WIWl%<+KagO~#Y&ppFUf4C=iG z{4yY=!uU#ypz|c7PS)|0BgWEKqXx9c@}~y&m;W`|pTe>Cj2!Dk9qTL8#Gm%f!1`_( zSnXkp+6P#E)4<9~j&H@BIX1SuqD5f0)(_-*xI2^cAA0|j5q<22TNW0ty4%1oQ}gS7 zzZ9)3t>XBlm2E<+pvPLWmc}P{o+yH>sPc$ME8Tv=0;wfIy7@#tr1=R_--)xI>F(nA z`Bn4b`OIhRE{e!CrthCs$Nt2D9sL}PFxCv1|5xuFZP5Afd zOwb3TGeJk9_hEiL0GJCn3Rnrq0ptPZDD+H)o(`M|Fapv5I)DL?4yec6eF*RXpawv5 z1MjnPw$OBn<$W^M+41}r+c!FG$>NldF4j)zJO4PvtY@aui&^Zk$g~!gUpDa2+HFFK zhvhvypnEY#TrA#+y{2fa7SSe&CQr#r@yVJo&YC^2&c2vc$@_t}-DST(3UF>&{;+;2^aWOq@?O!7G_lUIT{CTvjqO9tNB4@6h z!m1QV#>U>pK9x77e|}~zSuPaybtc3yFj`_m)Ycz(=nauIrWcRBw6v;3+&N-p9Cq8a zvG`KFIYv)K7gy@U5|N(WuSQqTNfHeMC7vgvw^nZv{tVBTM)k+YuUU%V=x9#Gf~wpr zB6w}|AnZm)6C?Qf=uJulvoRvf^4h?0*qt5KzexV>ko;{Koo=(z=vr?){>X6M$y`v~OkO*}aVO@YmnO<3ZpZfcbzdK&-sr zGuG5QR8e<$n2Yod2{ng@b)CIK$#uI1JzvL1lWKMiCe?|9qN8sp_UK6?EA2hcl|FLL zVBPy^D)ud7X75l6>m6DWFB~$k`-Udt@od3c%hoMCVgFn^HDcx}_l|>B4V! z1RFz)%?mB#=Y{g-xfb#(`3G_DEpmo^blrNGFLU^CB{!RK8fI*hbO&?$8@+xv@r9ni zMt7m3zS-+@6$YC&%EapRmDNJwrhwP!E}#rVFyJe&T8b=-t%X_#g-$6iU~yiv{d#u; z(hR&dTE^hD!P{8S;6VaB|ET!no;Mz>eWCQy8f(7jEB6++H=@JNU7(hW8Z zIz=WmAWLa1(%AjMfWMK4gXWFMTtI+wjd4=qq$Gfxm5|dByu|Pe=7kn~+vK(UI2w=& z;=gtC{k9Fw$TnOvHWByTkVkoj*XV=Xwq~fWVXO34&NJ}eAA{`sO7m;=P4O=~Ua$an z&0w=M=R}7Oxf#YDoELhSpBLg+@QmHPzPcJB_CsWt{Eg~Zq_IkWcu5iDQa@a2Y`r3o z_-09eTd}J5`Cx%OEo?|A+4y|0!u>bUOi4LK)*#J=)qw!=X@0g|PJr=JDhRga?(j0c zni5m;Q@6QWB|@H6G~e8Qm6q~M3iH#KxsJZR7jRj`x#jctw!RljA`eZ*w~?TC3jDLW z2>VLrFMS!`HV}_*JN-Av`(B95xkR`xVgi;Npw1cGlXn8BkW7Vq5JblmOnC+3DStqi z@({R+OSx8D#iblAuKLoqAzY!Q?0aM%mXrb>}YB8YG|16-qabls|v9?g|nhND;R?(!El7)=R1DSMt!77%V zma@vorRvi3>0FlK25ts-BX^VD#LeQebvZaoYW8l6%U$1$b+Yy1(tl$XDIsSG24o!a zAio!O)HBPfd)HWyJtorCiu|e9$t?ar*llU_H(R8wz5siz#qB|Il(MU`a@Fd}g0Q2J zNmd?5$ipmBqK5M?ASLAQ_EVish2-NB|Sv`9Bve&oat z3=pCmpCgPVU*8-?UfF_-B2`3cPx8~`1JM}359Pqs?s#1-azJ?X1s$z&1%;;J{fEk4 zSkcU(`K$fzs#aEKRTTs&iXDBgA>dUbV7&gNQh;C8&I22Qxr&aEYF7*TubAW1F0D6$ zLD01BsE{4OW&oCv6d$caf<7!1S{t-p$cEPAOA1f^Xx$RfdQ}VDOJy5=X|0hRtuq38 zud3~moZujU)+W)kJ_+hTYug1Y-GSgjszd9XfY!O{kK&{CeilG>s{vAn&?(w4$d2|3 z)$T3O6f3nu--rlk4^s=-QF$Mr+No<@`<;#K2+nEjy0PvE3>1h`RDbp0Re$s?i-6)* zi)u&Dmh5O;=o=V8k7k@zJKASeyXDwq39iH}1)6rlQh4891| zwn(qianMM&N^^s9#q{?8s!p{d{&N7*v63C-k~{y7-7(luyVOPc2HkxXJE){NuFehl z?+cKNMMaWPp*CqeKL)7&=)KX07f~N%Y9TuUvQh2mTU{MqP*-~%{{uUcQ+)J|(erog uj>|UESrVjVw}c3#P+L?y0F@@b2mVY%D1~C9qK=)+G4^ZNP196V$^Qpbd~X#1 literal 0 HcmV?d00001 diff --git a/bin/i586/vc_getengine b/bin/i586/vc_getengine new file mode 100755 index 0000000000000000000000000000000000000000..35926fa4652c4da0d9dfecd7be1ab87b8cbede7d GIT binary patch literal 13852 zcmeHOeUMbumA^AI(84f1;w+AlgjO3tg`OEi3qR8X%>ZU3qYTI{VAFKJp6=LmPj$Z@ zLC4)0-we=p9+`@oq-u3TLdr5#CN))LU1HR283ezoGP0M~U7*US%kpI_SL3PLL7Q#>bsGVU9n0_j{tNeH z-h6iQ){Z%crd{#*cJtnA{x}<-$w9KbXMaIws(2jfgTlL6lVP>1O0xki}0Wj7~9>4`MC&Ua3SE6Sz(A-dD8>Wl;FVsyx zuB&JqY0d{bxsiDd`dfU8<3>%LDl4CqU(JDRCHBSE3Yz7=0^RRZ0u9u!s_*wG_p@P0 z(-EDAs`S@a(ci0}FNRL2f@XcMfVTZ*eV0^~N2=<-tBQ`$5i7ZYGd2NC`;%dBJ^W?- z&&4R-UZsCuRecXvmH!FlBN)`0v{x_kpm+E{AT?mLUtOjD257EhOzgi8K(DQ+|6|bo z7|2&(z_WZ$Reir@5eR)O#0ue?ESi`e6)ggBVU3& z9|rGiVA_AJqMY_#s|V~K#4&{HujEdndLZVrUCl-3sqSo<|XlD zLhA}{ifd;WL@~)*j8~hEiHk*OW$?7f+&LmaT4B=?%s+S|GhO5wf|e z29_m)o6EAv9xZ{uhU3ZZKu;=`&~0&LK*rrN%e+-98bJ-!)gVI5U5zgNE_x@7PR^te z{(!O=3523|h@Om¨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 literal 0 HcmV?d00001 diff --git a/bin/x86_64/vc_getengine b/bin/x86_64/vc_getengine new file mode 100755 index 0000000000000000000000000000000000000000..5adce35a2b05e6e52f71e001d400435eb8ccea96 GIT binary patch literal 14672 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 HzODZO1joxV literal 0 HcmV?d00001 diff --git a/org.tizen.voice.vcserver.service b/org.tizen.voice.vcserver.service index c5006a2..aa51fd1 100644 --- a/org.tizen.voice.vcserver.service +++ b/org.tizen.voice.vcserver.service @@ -1,4 +1,5 @@ [D-BUS Service] Name=org.tizen.voice.vcserver #Exec=/usr/bin/vc-daemon -Exec=/bin/sh -c "launch_app org.tizen.vc-engine-default" +#Exec=/bin/sh -c "launch_app org.tizen.vc-engine-default" +Exec=/bin/sh -c "vc_getengine get system db/voice/vc/engine/default | awk '{print$5}' | xargs -t -i launch_app {}" diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index 6d0cc6d..908a6b2 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -9,7 +9,7 @@ Source1001: %{name}.manifest Source1002: %{name}-devel.manifest Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig - +Requires: gawk BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(capi-appfw-app-control) BuildRequires: pkgconfig(capi-appfw-app-manager) @@ -96,11 +96,11 @@ cp %{SOURCE1001} %{SOURCE1002} . %build %if "%{tizen_profile_name}" == "tv" export CFLAGS="$CFLAGS -DTV_PRODUCT" -cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DINCLUDEDIR=%{_includedir} \ - -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE -D_TV_PRODUCT=TRUE +cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DBINDIR=%{_bindir} -DINCLUDEDIR=%{_includedir} \ + -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE -D_TV_PRODUCT=TRUE -DTZ_SYS_BIN=%TZ_SYS_BIN %else -cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DINCLUDEDIR=%{_includedir} \ - -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE +cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DBINDIR=%{_bindir} -DINCLUDEDIR=%{_includedir} \ + -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE -DTZ_SYS_BIN=%TZ_SYS_BIN %endif make %{?jobs:-j%jobs} @@ -129,6 +129,7 @@ mkdir -p %{_libdir}/voice/vc %{_libdir}/libvc_widget.so %{_libdir}/libvc_manager.so %{_libdir}/libvc_engine.so +%{_bindir}/vc_getengine %{TZ_SYS_RO_SHARE}/voice/vc/1.0/vc-config.xml %{TZ_SYS_RO_SHARE}/dbus-1/services/org.tizen.voice* %{TZ_SYS_RO_ETC}/package-manager/parserlib/metadata/libvc-engine-parser.so* -- 2.7.4 From 29873bd3b1c1e77d2efea35b57c6ced91b89b4b4 Mon Sep 17 00:00:00 2001 From: sungrae jo Date: Thu, 30 Aug 2018 20:56:48 +0900 Subject: [PATCH 02/16] Add check state and range logic for voice control manager Change-Id: Ie240609e4259f6213789a9923626a2f6c079b7e2 Signed-off-by: sungrae jo --- client/vc_mgr.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index d47002d..12735da 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -650,7 +650,9 @@ int vc_mgr_get_state(vc_state_e* state) } vc_state_e temp; - if (0 != vc_mgr_client_get_client_state(g_vc_m, &temp)) { + if (NULL == g_vc_m) { + temp = VC_STATE_NONE; + } else if (0 != vc_mgr_client_get_client_state(g_vc_m, &temp)) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); SLOG(LOG_DEBUG, TAG_VCM, "@@@"); return VC_ERROR_INVALID_STATE; @@ -1633,7 +1635,7 @@ int vc_mgr_set_recognition_mode(vc_recognition_mode_e mode) } /* check vc recognition mode */ - if (mode > VC_RECOGNITION_MODE_MANUAL) { + if (mode < VC_RECOGNITION_MODE_STOP_BY_SILENCE || mode > VC_RECOGNITION_MODE_MANUAL) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] invalid parameter: 'mode' is not supported mode (%d)", mode); return VC_ERROR_INVALID_PARAMETER; } @@ -1683,6 +1685,13 @@ int vc_mgr_get_recognition_mode(vc_recognition_mode_e* mode) return VC_ERROR_INVALID_PARAMETER; } + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + ret = vc_mgr_client_get_recognition_mode(g_vc_m, mode); if (0 != ret) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get recognition mode"); @@ -1904,6 +1913,11 @@ int vc_mgr_do_action(vc_send_event_type_e type, char* send_event) return VC_ERROR_PERMISSION_DENIED; } + if (type < VC_SEND_EVENT_TYPE_TEXT || VC_SEND_EVENT_TYPE_HAPTIC_EVENT < type) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] send event type is not valid, (%d)", type); + return VC_ERROR_INVALID_PARAMETER; + } + if (NULL == send_event) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid parameter"); return VC_ERROR_INVALID_PARAMETER; @@ -2812,6 +2826,13 @@ int vc_mgr_get_error_message(char** err_msg) return VC_ERROR_PERMISSION_DENIED; } + /* check state */ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] vc_mgr handle is not available"); + return VC_ERROR_INVALID_STATE; + } + if (NULL == err_msg) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] invalid parameter"); return VC_ERROR_INVALID_PARAMETER; @@ -3756,6 +3777,10 @@ int vc_mgr_set_specific_engine_result_cb(vc_mgr_specific_engine_result_cb callba return VC_ERROR_NOT_SUPPORTED; } + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + if (NULL == callback) return VC_ERROR_INVALID_PARAMETER; -- 2.7.4 From bc801294c48031fd161f0ea25a842ee1a99cf78a Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Mon, 3 Sep 2018 16:14:34 +0900 Subject: [PATCH 03/16] Fix thread unsafety issue and retrying prepare - fix thread unsafety issue to avoid adding and deleting focus_cb in the different threads - fix to retry connect_daemon when vc_dbus_initialize() is failed due to TIMED_OUT Change-Id: I10ceff7d62b716c0e954c78406e0f6ec840a3f7a Signed-off-by: sooyeon.kim --- client/vc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/vc.c b/client/vc.c index 594c2ef..df42efe 100644 --- a/client/vc.c +++ b/client/vc.c @@ -512,7 +512,7 @@ static Eina_Bool __vc_connect_daemon(void *data) ecore_main_loop_thread_safe_call_async(__vc_notify_error, (void*)g_vc); SLOG(LOG_DEBUG, TAG_VCC, "@@@"); - return EINA_FALSE; + return EINA_TRUE; } else { /* Success to connect */ } @@ -537,8 +537,10 @@ static Eina_Bool __vc_connect_daemon(void *data) } /* Register focus handler */ + ecore_thread_main_loop_begin(); g_focus_in_handler = ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN, __focus_changed_cb, NULL); g_focus_out_handler = ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT, __focus_changed_cb, NULL); + ecore_thread_main_loop_end(); char appid[1024] = {'\0',}; aul_app_get_appid_bypid(getpid(), appid, sizeof(appid) - 1); -- 2.7.4 From 5ee15659d86573d6e40c52d05fd18aa89dbd462a Mon Sep 17 00:00:00 2001 From: sungrae jo Date: Fri, 31 Aug 2018 11:34:58 +0900 Subject: [PATCH 04/16] Add NULL data check for mgr_get_private_data Change-Id: I22cd412df5e4655c4d5c0f608852d111134e2597 Signed-off-by: sungrae jo --- client/vc_mgr_dbus.c | 7 ++++--- server/vcd_dbus_server.c | 21 ++++++++++++++++++--- server/vcd_engine_agent.c | 16 ++++++++-------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/client/vc_mgr_dbus.c b/client/vc_mgr_dbus.c index 3ee9075..246c59e 100644 --- a/client/vc_mgr_dbus.c +++ b/client/vc_mgr_dbus.c @@ -1561,11 +1561,12 @@ int vc_mgr_dbus_request_get_private_data(int pid, const char* key, char** data) dbus_message_unref(result_msg); if (0 == result) { - if (NULL != data && NULL != temp) { + if (0 == strncmp(temp, "#NULL", 5)) { + *data = NULL; + } else { *data = strdup(temp); - - SLOG(LOG_DEBUG, TAG_VCM, "@@ vc mgr get private data : result = %d private data = %s", result, *data); } + SLOG(LOG_DEBUG, TAG_VCM, "@@ vc mgr get private data : result = %d private data = %s", result, *data); } else { SLOG(LOG_ERROR, TAG_VCM, "@@ vc mgr get private data : result = %d", result); } diff --git a/server/vcd_dbus_server.c b/server/vcd_dbus_server.c index 297ef13..71329a6 100644 --- a/server/vcd_dbus_server.c +++ b/server/vcd_dbus_server.c @@ -588,17 +588,25 @@ int vcd_dbus_server_mgr_get_private_data(DBusConnection* conn, DBusMessage* msg) ret = vcd_server_mgr_get_private_data(pid, key, &data); } + char *temp_data = NULL; + if (NULL == data) { + SLOG(LOG_DEBUG, TAG_VCD, "[Dbus INFO] data parameter is NULL"); + temp_data = strdup("#NULL"); + } else { + temp_data = strdup(data); + } + DBusMessage* reply; reply = dbus_message_new_method_return(msg); if (NULL != reply) { dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, - DBUS_TYPE_STRING, &data, + DBUS_TYPE_STRING, &temp_data, DBUS_TYPE_INVALID); if (0 == ret) { - SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d), private data(%s)", ret, data); + SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d), private data(%s)", ret, temp_data); } else { SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret); } @@ -615,7 +623,14 @@ int vcd_dbus_server_mgr_get_private_data(DBusConnection* conn, DBusMessage* msg) SLOG(LOG_DEBUG, TAG_VCD, "@@@"); - if (NULL != data) free(data); + if (NULL != data) { + free(data); + data = NULL; + } + if (NULL != temp_data) { + free(temp_data); + temp_data = NULL; + } return 0; } diff --git a/server/vcd_engine_agent.c b/server/vcd_engine_agent.c index 27aa722..8794ae0 100644 --- a/server/vcd_engine_agent.c +++ b/server/vcd_engine_agent.c @@ -533,8 +533,8 @@ int vcd_engine_get_nlu_base_info(int pid, const char* key, char** value) return VCD_ERROR_OPERATION_FAILED; } } else { - SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no nlu_base_info_request callback"); - return VCD_ERROR_OPERATION_FAILED; + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent INFO] Engine is not loaded or There is no nlu_base_info_request callback"); + return VCD_ERROR_NONE; } return 0; @@ -555,8 +555,8 @@ int vcd_engine_set_private_data(int pid, const char* key, const char* data) return VCD_ERROR_OPERATION_FAILED; } } else { - SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no private_data_set callback"); - return VCD_ERROR_OPERATION_FAILED; + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent INFO] Engine is not loaded or There is no private_data_set callback"); + return VCD_ERROR_NONE; } return 0; @@ -582,8 +582,8 @@ int vcd_engine_get_private_data(int pid, const char* key, char** data) return VCD_ERROR_OPERATION_FAILED; } } else { - SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no private_data_request callback"); - return VCD_ERROR_OPERATION_FAILED; + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent INFO] Engine is not loaded or There is no private_data_request callback"); + return VCD_ERROR_NONE; } return 0; @@ -604,8 +604,8 @@ int vcd_engine_send_specific_engine_request(const char* engine_app_id, const cha return VCD_ERROR_OPERATION_FAILED; } } else { - SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no specific_engine_request callback"); - return VCD_ERROR_OPERATION_FAILED; + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent INFO] Engine is not loaded or There is no specific_engine_request callback"); + return VCD_ERROR_NONE; } return 0; -- 2.7.4 From b905eb5da020276bcec9179e89e3e451509c2b84 Mon Sep 17 00:00:00 2001 From: sungrae jo Date: Wed, 5 Sep 2018 13:22:53 +0900 Subject: [PATCH 05/16] Add permission, supported check for vcm Change-Id: Ic9e0363387ea928d1bdf73e9ee91db9216743907 Signed-off-by: sungrae jo --- client/vc_mgr.c | 71 +++++++++++++++++++++++++++++++++++++++++ include/voice_control_manager.h | 48 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index d47002d..399c64f 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -1947,6 +1947,17 @@ int vc_mgr_do_action(vc_send_event_type_e type, char* send_event) int vc_mgr_send_specific_engine_request(const char* engine_app_id, const char* event, const char* request) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] send specific engine request"); + + if (0 != __vc_mgr_get_feature_enabled()) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] not supported"); + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] specific engine request. engine app id(%s), event(%s), request(%s)", engine_app_id, event, request); if (NULL == engine_app_id || NULL == event) { @@ -3820,6 +3831,16 @@ void __vc_mgr_cb_specific_engine_result(const char* engine_app_id, const char* e /* for TTS feedback */ int vc_mgr_set_feedback_audio_format_cb(vc_mgr_feedback_audio_format_cb callback, void* user_data) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] set feedback audio format"); + + if (0 != __vc_mgr_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + if (NULL == callback) return VC_ERROR_INVALID_PARAMETER; @@ -3844,6 +3865,16 @@ int vc_mgr_set_feedback_audio_format_cb(vc_mgr_feedback_audio_format_cb callback int vc_mgr_unset_feedback_audio_format_cb() { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] unset feedback audio format"); + + if (0 != __vc_mgr_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + vc_state_e state; if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset feedback audio format callback : A handle is not available"); @@ -3865,6 +3896,16 @@ int vc_mgr_unset_feedback_audio_format_cb() int vc_mgr_set_feedback_streaming_cb(vc_mgr_feedback_streaming_cb callback, void* user_data) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] set feedback streaming"); + + if (0 != __vc_mgr_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + if (NULL == callback) return VC_ERROR_INVALID_PARAMETER; @@ -3889,6 +3930,16 @@ int vc_mgr_set_feedback_streaming_cb(vc_mgr_feedback_streaming_cb callback, void int vc_mgr_unset_feedback_streaming_cb() { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] unset feedback streaming"); + + if (0 != __vc_mgr_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + vc_state_e state; if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset feedback streaming callback : A handle is not available"); @@ -3971,6 +4022,16 @@ static void __end_tts_feedback_thread(void* data, Ecore_Thread* thread) int vc_mgr_start_feedback(void) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] start feedback"); + + if (0 != __vc_mgr_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] Request start TTS feedback"); vc_state_e state; @@ -4000,6 +4061,16 @@ int vc_mgr_start_feedback(void) int vc_mgr_stop_feedback(void) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] stop feedback"); + + if (0 != __vc_mgr_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] Request stop TTS feedback"); vc_state_e state; diff --git a/include/voice_control_manager.h b/include/voice_control_manager.h index 574fccb..a212487 100644 --- a/include/voice_control_manager.h +++ b/include/voice_control_manager.h @@ -794,9 +794,13 @@ int vc_mgr_get_private_data(const char *key, char **data); int vc_mgr_do_action(vc_send_event_type_e type, char *send_event); /** +* @platform * @brief Sends the specific engine request to the vc-service. * @since_tizen 5.0 * +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager +* * @param[in] engine_app_id A specific engine's app id * @param[in] event A engine service user request event * @param[in] request A engine service user request text @@ -807,6 +811,8 @@ int vc_mgr_do_action(vc_send_event_type_e type, char *send_event); * @retval #VC_ERROR_INVALID_STATE Invalid state * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #VC_ERROR_OPERATION_FAILED Operation failure +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported */ int vc_mgr_send_specific_engine_request(const char* engine_app_id, const char* event, const char* request); @@ -1555,15 +1561,22 @@ int vc_mgr_unset_private_data_requested_cb(void); /* for TTS feedback */ /** +* @platform * @brief Sets a callback function to be called when engine sends audio formats necessary for playing TTS feedback. +* @since_tizen 5.0 * * @param[in] callback Callback function to set * @param[in] user_data The user data to be passed to the callback function * +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager +* * @return 0 on success, otherwise a negative error value * @retval #VC_ERROR_NONE Successful * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported * * @pre The state should be #VC_STATE_INITIALIZED. * @@ -1573,11 +1586,18 @@ int vc_mgr_unset_private_data_requested_cb(void); int vc_mgr_set_feedback_audio_format_cb(vc_mgr_feedback_audio_format_cb callback, void* user_data); /** +* @platform * @brief Unsets a callback function to be called when engine sends audio formats necessary for playing TTS feedback. +* @since_tizen 5.0 +* +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager * * @return 0 on success, otherwise a negative error value * @retval #VC_ERROR_NONE Successful * @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported * * @pre The state should be #VC_STATE_INITIALIZED. * @@ -1587,15 +1607,22 @@ int vc_mgr_set_feedback_audio_format_cb(vc_mgr_feedback_audio_format_cb callback int vc_mgr_unset_feedback_audio_format_cb(void); /** +* @platform * @brief Sets a callback function to be called when engine sends audio streaming for TTS feedback. +* @since_tizen 5.0 * * @param[in] callback Callback function to set * @param[in] user_data The user data to be passed to the callback function * +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager +* * @return 0 on success, otherwise a negative error value * @retval #VC_ERROR_NONE Successful * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported * * @pre The state should be #VC_STATE_INITIALIZED. * @@ -1605,11 +1632,18 @@ int vc_mgr_unset_feedback_audio_format_cb(void); int vc_mgr_set_feedback_streaming_cb(vc_mgr_feedback_streaming_cb callback, void* user_data); /** +* @platform * @brief Unsets a callback function to be called when engine sends audio streaming for TTS feedback. +* @since_tizen 5.0 +* +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager * * @return 0 on success, otherwise a negative error value * @retval #VC_ERROR_NONE Successful * @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported * * @pre The state should be #VC_STATE_INITIALIZED. * @@ -1619,13 +1653,20 @@ int vc_mgr_set_feedback_streaming_cb(vc_mgr_feedback_streaming_cb callback, void int vc_mgr_unset_feedback_streaming_cb(void); /** +* @platform * @brief Starts getting TTS feedback streaming data from the buffer. +* @since_tizen 5.0 * * @remarks In order to get TTS feedback streaming data, the application should set 'vc_mgr_feedback_streaming_cb()' using vc_mgr_set_feedback_streaming_cb(). * +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager +* * @return 0 on success, otherwise a negative error value * @retval #VC_ERROR_NONE Successful * @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported * * @pre The state should be #VC_STATE_READY. \n * 'vc_mgr_feedback_streaming_cb()' should be registered. @@ -1638,11 +1679,18 @@ int vc_mgr_unset_feedback_streaming_cb(void); int vc_mgr_start_feedback(void); /** +* @platform * @brief Stops getting and removes TTS feedback streaming data from the buffer. +* @since_tizen 5.0 +* +* @privlevel platform +* @privilege %http://tizen.org/privilege/voicecontrol.manager * * @return 0 on success, otherwise a negative error value * @retval #VC_ERROR_NONE Successful * @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_ERROR_NOT_SUPPORTED VC not supported * * @pre The state should be #VC_STATE_READY. * -- 2.7.4 From c94c550e17e294d79f3553df766530ad81cc3b89 Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Wed, 5 Sep 2018 16:03:05 +0900 Subject: [PATCH 06/16] Add parser-plugin file Change-Id: Ibac6ed31fa6006311ea13816bbacf5e5347fef60 Signed-off-by: sooyeon.kim --- CMakeLists.txt | 2 ++ packaging/voice-control.spec | 1 + voice-control.info | 1 + 3 files changed, 4 insertions(+) create mode 100644 voice-control.info diff --git a/CMakeLists.txt b/CMakeLists.txt index 22994bb..b555f38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,8 @@ ADD_SUBDIRECTORY(server) ## Engine Parser ## ADD_SUBDIRECTORY(engine-parser) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/voice-control.info DESTINATION ${TZ_SYS_RO_SHARE}/parser-plugins) + ## config ## INSTALL(FILES ${CMAKE_SOURCE_DIR}/vc-config.xml DESTINATION ${TZ_SYS_RO_SHARE}/voice/vc/1.0) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index 908a6b2..4b94bd5 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -132,6 +132,7 @@ mkdir -p %{_libdir}/voice/vc %{_bindir}/vc_getengine %{TZ_SYS_RO_SHARE}/voice/vc/1.0/vc-config.xml %{TZ_SYS_RO_SHARE}/dbus-1/services/org.tizen.voice* +%{TZ_SYS_RO_SHARE}/parser-plugins/voice-control.info %{TZ_SYS_RO_ETC}/package-manager/parserlib/metadata/libvc-engine-parser.so* /etc/dbus-1/session.d/vc-server.conf diff --git a/voice-control.info b/voice-control.info new file mode 100644 index 0000000..6b74d26 --- /dev/null +++ b/voice-control.info @@ -0,0 +1 @@ +type="metadata";name="http://tizen.org/metadata/vc-engine";path="/etc/package-manager/parserlib/metadata/libvc-engine-parser.so" -- 2.7.4 From df1ee67dae3789ce8fcf1b8b7ce43d708a9779fe Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Wed, 12 Sep 2018 17:16:45 +0900 Subject: [PATCH 07/16] Fix documentation error Change-Id: Iff693ca988950321111a0c088a72d57e6663e3d1 Signed-off-by: sooyeon.kim --- doc/uix_vc_mgr_doc.h | 7 +++---- include/voice_control_manager.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/uix_vc_mgr_doc.h b/doc/uix_vc_mgr_doc.h index 0fa61eb..04c96a1 100644 --- a/doc/uix_vc_mgr_doc.h +++ b/doc/uix_vc_mgr_doc.h @@ -240,7 +240,6 @@ * * * - * * vc_mgr_disable_command_type() * Ready * @@ -262,11 +261,11 @@ * vc_mgr_set_current_language_changed_cb()
* vc_mgr_unset_current_language_changed_cb()
* vc_mgr_set_error_cb()
- * vc_mgr_unset_error_cb() + * vc_mgr_unset_error_cb()
* vc_mgr_set_dialog_request_cb()
- * vc_mgr_unset_dialog_request_cb() + * vc_mgr_unset_dialog_request_cb()
* vc_mgr_set_private_data_set_cb()
- * vc_mgr_unset_private_data_set_cb() + * vc_mgr_unset_private_data_set_cb()
* vc_mgr_set_private_data_requested_cb()
* vc_mgr_unset_private_data_requested_cb() * Initialized diff --git a/include/voice_control_manager.h b/include/voice_control_manager.h index a212487..b6918e8 100644 --- a/include/voice_control_manager.h +++ b/include/voice_control_manager.h @@ -482,7 +482,7 @@ int vc_mgr_get_service_state(vc_service_state_e *state); * @privlevel platform * @privilege %http://tizen.org/privilege/voicecontrol.manager * - * @remarks The command formats are defined in the #voice_control_command.h. (e.g. #VC_COMMAND_FORMAT_FIXED, #VC_COMMAND_FORMAT_FIXED_AND_NONFIXED, and so on). Please refer to #voice_control_command.h. + * @remarks The command formats are defined in @ref CAPI_UIX_VOICE_CONTROL_COMMAND_MODULE. (e.g. #VC_COMMAND_FORMAT_FIXED, #VC_COMMAND_FORMAT_FIXED_AND_NONFIXED, and so on). Please refer to @ref CAPI_UIX_VOICE_CONTROL_COMMAND_MODULE. * * @param[in] format The command format * @param[out] support The result status @c true = supported, @c false = not supported -- 2.7.4 From 99f64cdd8c9e8f2c81f520aee967084f39ce4654 Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Thu, 30 Aug 2018 21:27:52 +0900 Subject: [PATCH 08/16] [ACR-1297] Add VCE APIs for supporting tts feedback - add tts feedback api for vc client Change-Id: I120eb805bafa7b9d0a44014e7c16e979bb9d5633 Signed-off-by: sooyeon.kim --- client/CMakeLists.txt | 1 + client/vc.c | 461 +++++++++++++++++++++++++++++++++++++++ client/vc_client.c | 66 ++++++ client/vc_client.h | 11 + client/vc_data.cpp | 146 +++++++++++++ client/vc_data.h | 54 +++++ client/vc_dbus.c | 269 +++++++++++++++++++++++ client/vc_dbus.h | 9 + client/vc_mgr.c | 140 +++++++++++- client/vc_mgr_client.c | 32 +++ client/vc_mgr_client.h | 4 + client/vc_mgr_data.cpp | 5 +- client/vc_mgr_data.h | 1 + client/vc_mgr_dbus.c | 40 +++- client/vc_mgr_dbus.h | 3 + common/vc_defs.h | 6 + include/CMakeLists.txt | 1 + include/vce.h | 161 +++++++++++++- include/vce_internal.h | 53 +++++ include/voice_control_internal.h | 170 +++++++++++++++ include/voice_control_manager.h | 55 +++++ packaging/voice-control.spec | 1 + server/CMakeLists.txt | 2 + server/vcd_dbus.c | 58 ++++- server/vcd_dbus.h | 4 +- server/vcd_dbus_server.c | 170 ++++++++++++++- server/vcd_dbus_server.h | 7 + server/vcd_engine_agent.c | 148 ++++++++++++- server/vcd_engine_agent.h | 14 ++ server/vcd_main.h | 4 +- server/vcd_server.c | 229 ++++++++++++++++++- server/vcd_server.h | 12 + server/vcd_server_data.cpp | 187 ++++++++++++++++ server/vcd_server_data.h | 56 +++++ server/vce.c | 77 ++++++- 35 files changed, 2623 insertions(+), 34 deletions(-) create mode 100644 client/vc_data.cpp create mode 100644 client/vc_data.h create mode 100644 include/vce_internal.h create mode 100644 server/vcd_server_data.cpp create mode 100644 server/vcd_server_data.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 0380cc0..10ce754 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,5 +1,6 @@ SET(SRCS vc.c + vc_data.cpp vc_client.c vc_dbus.c ../common/vc_cmd_db.c diff --git a/client/vc.c b/client/vc.c index df42efe..cc75683 100644 --- a/client/vc.c +++ b/client/vc.c @@ -29,6 +29,7 @@ #include "vc_cmd_db.h" #include "vc_command.h" #include "vc_config_mgr.h" +#include "vc_data.h" #include "vc_dbus.h" #include "vc_info_parser.h" #include "vc_json_parser.h" @@ -46,6 +47,8 @@ static Ecore_Timer* g_connect_timer = NULL; static Ecore_Event_Handler* g_focus_in_handler = NULL; static Ecore_Event_Handler* g_focus_out_handler = NULL; +static Ecore_Thread* g_tts_thread = NULL; + static vc_h g_vc = NULL; static int g_daemon_pid = 0; @@ -2868,3 +2871,461 @@ int vc_auth_cancel(void) return ret; } //LCOV_EXCL_STOP + +static void __start_tts_streaming_thread(void* data, Ecore_Thread* thread) +{ + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Start tts streaming thread"); + + vc_tts_data_s* tts_data = NULL; + vc_tts_streaming_cb callback = NULL; + void* user_data = NULL; + + vc_client_get_tts_streaming_cb(g_vc, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] tts streaming callback is null"); + return; + } + + while (1) { + int ret = -1; + int cnt = 0; + + /* get tts data */ + ret = vc_data_get_tts_data(&tts_data); + if (0 != ret || NULL == tts_data) { + /* empty queue */ + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] No tts data. Waiting mode"); + + /* waiting */ + while (1) { + usleep(10000); + if (0 < vc_data_get_tts_data_size()) { + SLOG(LOG_INFO, TAG_VCC, "[INFO] Resume thread"); + break; + } + if (200 < cnt) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Wrong request, there's no pcm data"); + return; + } + cnt++; + } + SLOG(LOG_INFO, TAG_VCC, "[INFO] Finish to wait for new tts data come"); + + /* resume tts thread */ + continue; + } + + SLOG(LOG_DEBUG, TAG_VCC, "tts streaming callback is called"); + vc_client_use_callback(g_vc); + callback(tts_data->event, tts_data->data, tts_data->data_size, tts_data->utt_id, user_data); + vc_client_not_use_callback(g_vc); + + /* If no tts data and EVENT_FINISH */ + if (0 >= vc_data_get_tts_data_size() && VC_TTS_EVENT_FINISH == tts_data->event) { + SLOG(LOG_INFO, TAG_VCC, "[INFO] Finish tts"); + break; + } + } +} + +static void __end_tts_streaming_thread(void* data, Ecore_Thread* thread) +{ + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] End tts streaming thread"); + g_tts_thread = NULL; +} + +int __vc_cb_tts_streaming(int utt_id, vc_tts_event_e event, char* buffer, int len) +{ + /* add tts data */ + vc_tts_data_s* temp_tts_data = NULL; + temp_tts_data = (vc_tts_data_s*)calloc(1, sizeof(vc_tts_data_s)); + if (NULL == temp_tts_data) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Out of memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp_tts_data->data = NULL; + temp_tts_data->data_size = 0; + + if (0 < len) { + temp_tts_data->data = (char*)calloc(len + 5, sizeof(char)); + if (NULL != temp_tts_data->data) { + memcpy(temp_tts_data->data, buffer, len); + temp_tts_data->data_size = len; + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG][memcpy] data(%p) size(%d)", + temp_tts_data->data, temp_tts_data->data_size); + } else { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] fail to allocate memory"); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] tts data is NULL"); + } + + temp_tts_data->utt_id = utt_id; + temp_tts_data->event = event; + + int ret = vc_data_add_tts_data(temp_tts_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to add tts data"); + if (NULL != temp_tts_data->data) { + free(temp_tts_data->data); + temp_tts_data->data = NULL; + } + if (NULL != temp_tts_data) { + free(temp_tts_data); + temp_tts_data = NULL; + } + } + + bool is_canceled = ecore_thread_check(g_tts_thread); + if (NULL == g_tts_thread || TRUE == is_canceled) { + SLOG(LOG_INFO, TAG_VCC, "ecore thread run : __start_tts_streaming_thread "); + g_tts_thread = ecore_thread_run(__start_tts_streaming_thread, __end_tts_streaming_thread, NULL, NULL); + } + + return ret; +} + +int vc_tts_request(const char* text, const char* language, bool to_vcm, int* utt_id) +{ + vc_state_e state; + int ret = -1; + int pid = getpid(); + + SLOG(LOG_DEBUG, TAG_VCC, "@@@ Request tts"); + + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + SLOG(LOG_DEBUG, TAG_VCC, "@@@ tts request, pid(%d), text(%s), language(%s), to_vcm(%d)", pid, text, language, to_vcm); + + int count = 0; + bool is_prepared = false; + do { + ret = vc_dbus_request_tts(pid, text, language, to_vcm, utt_id); + if (0 != ret) { + if (VC_ERROR_INVALID_PARAMETER == ret && false == is_prepared) { + vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED); + if (0 == vc_prepare_sync()) { + is_prepared = true; + SLOG(LOG_INFO, TAG_VCC, "[INFO] Success vc_prepare_sync"); + } + } else if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request tts to vc service : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request tts : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } + } while (0 != ret); + + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + + return ret; +} + +int vc_tts_cancel(int utt_id) +{ + vc_state_e state; + int ret = -1; + int pid = getpid(); + + SLOG(LOG_DEBUG, TAG_VCC, "@@@ Cancel tts"); + + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + SLOG(LOG_DEBUG, TAG_VCC, "@@@ tts cancel, pid(%d), utt_id(%d)", pid, utt_id); + + ret = vc_data_clear_tts_data_by_uttid(utt_id); + if (0 != ret) { + SLOG(LOG_INFO, TAG_VCC, "[INFO] There's no data in client pcm queue"); + } + + int count = 0; + bool is_prepared = false; + do { + ret = vc_dbus_cancel_tts(pid, utt_id); + if (0 != ret) { + if (VC_ERROR_INVALID_PARAMETER == ret && false == is_prepared) { + vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED); + if (0 == vc_prepare_sync()) { + is_prepared = true; + SLOG(LOG_INFO, TAG_VCC, "[INFO] Success vc_prepare_sync"); + } + } else if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to cancel tts to vc service : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry cancel tts : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to cancel"); + break; + } + } + } + } while (0 != ret); + + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + + return ret; +} + +int vc_tts_get_audio_format(int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type) +{ + vc_state_e state; + int ret = -1; + int pid = getpid(); + + SLOG(LOG_DEBUG, TAG_VCC, "@@@ Get tts audio format"); + + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state); + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + SLOG(LOG_DEBUG, TAG_VCC, "@@@ get tts audio format, pid(%d)", pid); + + int count = 0; + bool is_prepared = false; + do { + ret = vc_dbus_get_tts_audio_format(pid, rate, channel, audio_type); + if (0 != ret) { + if (VC_ERROR_INVALID_PARAMETER == ret && false == is_prepared) { + vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED); + if (0 == vc_prepare_sync()) { + is_prepared = true; + SLOG(LOG_INFO, TAG_VCC, "[INFO] Success vc_prepare_sync"); + } + } else if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get tts audio format : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry to get tts audio format : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get tts audio format"); + break; + } + } + } + } while (0 != ret); + + SLOG(LOG_DEBUG, TAG_VCC, "@@@"); + + return ret; +} + +int vc_tts_set_streaming_cb(vc_tts_streaming_cb callback, void* user_data) +{ + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts streaming callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts streaming callback : Current state(%d) is not 'Initialized'", state); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_tts_streaming_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_tts_unset_streaming_cb(void) +{ + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts streaming callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts streaming callback : Current state(%d) is not 'Initialized'", state); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_tts_streaming_cb(g_vc, NULL, NULL); + + return 0; +} + +int __vc_cb_utterance_status(int utt_id, int utt_status) +{ + vc_tts_utterance_status_cb callback = NULL; + void* user_data = NULL; + + vc_client_get_tts_utterance_status_cb(g_vc, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] Utterance status callback is null"); + return -1; + } + + SLOG(LOG_DEBUG, TAG_VCC, "Utterance status callback is called"); + vc_client_use_callback(g_vc); + callback(utt_id, (vc_tts_utterance_status_e)utt_status); + vc_client_not_use_callback(g_vc); + + return 0; +} + +int vc_tts_set_utterance_status_cb(vc_tts_utterance_status_cb callback, void* user_data) +{ + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts utterance status callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts utterance status callback : Current state(%d) is not 'Initialized'", state); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_tts_utterance_status_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_tts_unset_utterance_status_cb(void) +{ + if (0 != __vc_get_feature_enabled()) { + return VC_ERROR_NOT_SUPPORTED; + } + if (0 != __vc_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts utterance status callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts utterance status callback : Current state(%d) is not 'Initialized'", state); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_tts_utterance_status_cb(g_vc, NULL, NULL); + + return 0; +} diff --git a/client/vc_client.c b/client/vc_client.c index 70c4b4b..c7db4cc 100644 --- a/client/vc_client.c +++ b/client/vc_client.c @@ -35,6 +35,12 @@ typedef struct { vc_current_language_changed_cb current_lang_changed_cb; void* current_lang_changed_user_data; + /* tts feedback */ + vc_tts_streaming_cb tts_streaming_cb; + void* tts_streaming_user_data; + vc_tts_utterance_status_cb tts_utterance_status_cb; + void* tts_utterance_status_user_data; + #if 0 /* exclusive option */ bool exclusive_cmd; @@ -133,6 +139,10 @@ int vc_client_create(vc_h* vc) client->current_lang_changed_user_data = NULL; client->error_cb = NULL; client->error_user_data = NULL; + client->tts_streaming_cb = NULL; + client->tts_streaming_user_data = NULL; + client->tts_utterance_status_cb = NULL; + client->tts_utterance_status_user_data = NULL; #if 0 client->exclusive_cmd = false; @@ -781,3 +791,59 @@ int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid) return 0; } + +int vc_client_set_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->tts_streaming_cb = callback; + client->tts_streaming_user_data = user_data; + + return 0; +} + +int vc_client_get_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->tts_streaming_cb; + *user_data = client->tts_streaming_user_data; + + return 0; +} + +int vc_client_set_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->tts_utterance_status_cb = callback; + client->tts_utterance_status_user_data = user_data; + + return 0; +} + +int vc_client_get_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->tts_utterance_status_cb; + *user_data = client->tts_utterance_status_user_data; + + return 0; +} diff --git a/client/vc_client.h b/client/vc_client.h index 0d03bda..e084fe7 100644 --- a/client/vc_client.h +++ b/client/vc_client.h @@ -22,6 +22,7 @@ #include "vc_main.h" #include "voice_control.h" #include "voice_control_authority.h" +#include "voice_control_internal.h" #ifdef __cplusplus @@ -128,6 +129,16 @@ int vc_client_set_mgr_pid(vc_h vc, int mgr_pid); int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid); +/* TTS feedback */ +int vc_client_set_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb callback, void* user_data); + +int vc_client_get_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb* callback, void** user_data); + +int vc_client_set_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb callback, void* user_data); + +int vc_client_get_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb* callback, void** user_data); + + #ifdef __cplusplus } #endif diff --git a/client/vc_data.cpp b/client/vc_data.cpp new file mode 100644 index 0000000..2358f6f --- /dev/null +++ b/client/vc_data.cpp @@ -0,0 +1,146 @@ +/* +* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include + +#include "vc_data.h" + +using namespace std; + +std::list g_tts_data; + +static pthread_mutex_t g_tts_data_mutex = PTHREAD_MUTEX_INITIALIZER; + +int vc_data_add_tts_data(vc_tts_data_s* data) +{ + if (NULL == data) { + SLOG(LOG_ERROR, TAG_VCC, "[DATA ERROR] tts data is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + pthread_mutex_lock(&g_tts_data_mutex); + + std::list::iterator iter; + + try { + iter = g_tts_data.insert(g_tts_data.end(), data); + } catch (const std::bad_alloc&) { + SLOG(LOG_ERROR, TAG_VCC, "[DATA ERROR] Fail to insert tts data (bad alloc)"); + pthread_mutex_unlock(&g_tts_data_mutex); + + return VC_ERROR_OUT_OF_MEMORY; + } + + pthread_mutex_unlock(&g_tts_data_mutex); + + return VC_ERROR_NONE; +} + +int vc_data_get_tts_data(vc_tts_data_s** data) +{ + SLOG(LOG_DEBUG, TAG_VCC, "[DATA] tts_data : %p", *data); + + pthread_mutex_lock(&g_tts_data_mutex); + + if (0 == g_tts_data.size()) { + SLOG(LOG_DEBUG, TAG_VCC, "[DATA] There is no tts data"); + *data = NULL; + pthread_mutex_unlock(&g_tts_data_mutex); + + return -1; + } + + std::list::iterator iter; + + if (!g_tts_data.empty()) { + iter = g_tts_data.begin(); + *data = *iter; + g_tts_data.pop_front(); + } + + pthread_mutex_unlock(&g_tts_data_mutex); + + return VC_ERROR_NONE; +} + +int vc_data_get_tts_data_size() +{ + int data_size = 0; + + pthread_mutex_lock(&g_tts_data_mutex); + data_size = g_tts_data.size(); + + pthread_mutex_unlock(&g_tts_data_mutex); + + return data_size; +} + +int vc_data_clear_tts_data(vc_tts_data_s** data) +{ + SLOG(LOG_DEBUG, TAG_VCC, "[DATA] clear tts data"); + + pthread_mutex_lock(&g_tts_data_mutex); + + if (!g_tts_data.empty()) { + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] event(%d) data(%p) size(%d)", (*data)->event, (*data)->data, (*data)->data_size); + + if (NULL != (*data)->data) { + free((*data)->data); + (*data)->data = NULL; + } + + free(*data); + *data = NULL; + } + + pthread_mutex_unlock(&g_tts_data_mutex); + + return VC_ERROR_NONE; +} + +int vc_data_clear_tts_data_by_uttid(int utt_id) +{ + SLOG(LOG_DEBUG, TAG_VCC, "[DATA] clear tts data by utt_id(%d)", utt_id); + + pthread_mutex_lock(&g_tts_data_mutex); + + if (g_tts_data.empty()) { + SLOG(LOG_ERROR, TAG_VCC, "[DATA ERROR] There is no tts data"); + pthread_mutex_unlock(&g_tts_data_mutex); + return -1; + } + + std::list::iterator iter; + for (iter = g_tts_data.begin(); (NULL != *iter && iter != g_tts_data.end()); ++iter) { + if (utt_id == (*iter)->utt_id) { + if (NULL != (*iter)->data) { + free((*iter)->data); + (*iter)->data = NULL; + } + g_tts_data.erase(iter); + free(*iter); + } + } + + pthread_mutex_unlock(&g_tts_data_mutex); + + return VC_ERROR_NONE; +} \ No newline at end of file diff --git a/client/vc_data.h b/client/vc_data.h new file mode 100644 index 0000000..9ca9668 --- /dev/null +++ b/client/vc_data.h @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_DATA_H__ +#define __VC_DATA_H__ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG_VCC "vcc" /* vc client log tag */ + +typedef struct { + int utt_id; + void* data; + unsigned int data_size; + vc_tts_event_e event; +} vc_tts_data_s; + + +int vc_data_add_tts_data(vc_tts_data_s* data); + +int vc_data_get_tts_data(vc_tts_data_s** data); + +int vc_data_get_tts_data_size(); + +int vc_data_clear_tts_data(vc_tts_data_s** data); + +int vc_data_clear_tts_data_by_uttid(int utt_id); + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_DATA_H__ */ diff --git a/client/vc_dbus.c b/client/vc_dbus.c index fb2af05..2da8f6b 100644 --- a/client/vc_dbus.c +++ b/client/vc_dbus.c @@ -34,6 +34,10 @@ extern int __vc_cb_service_state(int state); extern int __vc_cb_manager_pid(int manager_pid); +extern int __vc_cb_tts_streaming(int utt_id, vc_feedback_event_e event, char* buffer, int len); + +extern int __vc_cb_utterance_status(int utt_id, int utt_status); + //LCOV_EXCL_START static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler) { @@ -156,6 +160,40 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle SLOG(LOG_DEBUG, TAG_VCC, "@@@"); } /* VCD_METHOD_ERROR */ + else if (dbus_message_is_method_call(msg, if_name, VCD_METHOD_FEEDBACK_STREAMING)) { + SLOG(LOG_INFO, TAG_VCC, "@@@ Get TTS feedback streaming"); + int utt_id; + vc_feedback_event_e event; + char* buffer = NULL; + int len; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INT32, &event, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buffer, &len, + DBUS_TYPE_INVALID); + + __vc_cb_tts_streaming(utt_id, event, buffer, len); + + SLOG(LOG_INFO, TAG_VCC, "@@@"); + } /* VCD_METHOD_FEEDBACK_STREAMING */ + + else if (dbus_message_is_method_call(msg, if_name, VC_MANAGER_METHOD_UTTERANCE_STATUS)) { + SLOG(LOG_INFO, TAG_VCC, "@@@ Get TTS utterance status streaming"); + int utt_id; + int utt_status; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INT32, &utt_status, + DBUS_TYPE_INVALID); + + __vc_cb_utterance_status(utt_id, utt_status); + + SLOG(LOG_INFO, TAG_VCC, "@@@"); + } /* VC_MANAGER_METHOD_UTTERANCE_STATUS */ + else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameOwnerChanged")) { SLOG(LOG_DEBUG, TAG_VCC, "@@@ Owner Changed"); DBusError err; @@ -1655,3 +1693,234 @@ int vc_dbus_request_auth_cancel(int pid, int mgr_pid) return result; } //LCOV_EXCL_STOP + +int vc_dbus_request_tts(int pid, const char* text, const char* language, bool to_vcm, int* utt_id) +{ + if (NULL == g_conn_sender) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection"); + if (0 != vc_dbus_reconnect()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect"); + } + } + + DBusMessage* msg; + int tmp_to_vcm = 0; + + tmp_to_vcm = (int)to_vcm; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_REQUEST_TTS); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, "@@ vc request tts to manager : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, "@@ vc request tts to manager : client pid(%d), disp_text(%s), utt_text(%s), continuous(%d)", pid, text, language, to_vcm); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_STRING, &language, + DBUS_TYPE_INT32, &tmp_to_vcm, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + int tmp_utt_id = -1; + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT32, &tmp_utt_id, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "@@ Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + *utt_id = tmp_utt_id; + SLOG(LOG_DEBUG, TAG_VCC, "@@ vc request tts : result = %d, utt_id = %d", result, *utt_id); + } else { + SLOG(LOG_ERROR, TAG_VCC, "@@ vc request tts : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "@@ Result message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; + + return 0; +} + +int vc_dbus_cancel_tts(int pid, int utt_id) +{ + if (NULL == g_conn_sender) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection"); + if (0 != vc_dbus_reconnect()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect"); + } + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_CANCEL_TTS); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, "@@ vc cancel tts to manager : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, "@@ vc cancel tts to manager : client pid(%d), utt_id(%d)", pid, utt_id); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "@@ Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "@@ vc cancel tts : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "@@ vc cancel tts : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "@@ Result message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; + + return 0; +} + +int vc_dbus_get_tts_audio_format(int pid, int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type) +{ + if (NULL == g_conn_sender) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection"); + if (0 != vc_dbus_reconnect()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect"); + } + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_GET_TTS_AUDIO_FORMAT); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, "@@ vc get tts audio format : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, "@@ vc get tts audio format : client pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + int tmp_rate; + int tmp_channel; + int tmp_audio_type; + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT32, &tmp_rate, + DBUS_TYPE_INT32, &tmp_channel, + DBUS_TYPE_INT32, &tmp_audio_type, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "@@ Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + *rate = tmp_rate; + *channel = tmp_channel; + *audio_type = tmp_audio_type; + SLOG(LOG_DEBUG, TAG_VCC, "@@ vc get tts audio format : result = %d, rate = %d, channel = %d, audio_type = %d", result, *rate, *channel, *audio_type); + } else { + SLOG(LOG_ERROR, TAG_VCC, "@@ vc get tts audio format : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "@@ Result message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; + + return 0; +} + diff --git a/client/vc_dbus.h b/client/vc_dbus.h index e7f7512..5d13712 100644 --- a/client/vc_dbus.h +++ b/client/vc_dbus.h @@ -18,6 +18,7 @@ #ifndef __VC_DBUS_H_ #define __VC_DBUS_H_ +#include "voice_control_common.h" #ifdef __cplusplus extern "C" { @@ -67,6 +68,14 @@ int vc_dbus_request_auth_stop(int pid, int mgr_pid); int vc_dbus_request_auth_cancel(int pid, int mgr_pid); +/* tts feedback */ + +int vc_dbus_request_tts(int pid, const char* text, const char* language, bool to_vcm, int* utt_id); + +int vc_dbus_cancel_tts(int pid, int utt_id); + +int vc_dbus_get_tts_audio_format(int pid, int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type); + #ifdef __cplusplus } #endif diff --git a/client/vc_mgr.c b/client/vc_mgr.c index a4b01c0..17bbbb8 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -3372,7 +3372,7 @@ int __vc_mgr_cb_feedback_audio_format(int rate, vc_audio_channel_e channel, vc_a return VC_ERROR_NONE; } -int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int len) +int __vc_mgr_cb_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len) { /* add feedback data */ vc_feedback_data_s* temp_feedback_data = NULL; @@ -3381,6 +3381,7 @@ int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Out of memory"); return VC_ERROR_OUT_OF_MEMORY; } + SLOG(LOG_INFO, TAG_VCM, "[INFO] feedback streaming before queing"); temp_feedback_data->data = NULL; temp_feedback_data->rate = g_feedback_rate; @@ -3400,10 +3401,14 @@ int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int SLOG(LOG_ERROR, TAG_VCM, "[ERROR] feedback data is NULL"); } + temp_feedback_data->pid = pid; + temp_feedback_data->utt_id = utt_id; temp_feedback_data->event = event; temp_feedback_data->audio_type = g_feedback_audio_type; temp_feedback_data->channel = g_feedback_audio_channel; + SLOG(LOG_INFO, TAG_VCM, "[INFO] add feedback data, pid(%d), utt_id(%d), event(%d), audio_type(%d), channel(%d)", pid, utt_id, event, g_feedback_audio_type, g_feedback_audio_channel); + int ret = vc_mgr_data_add_feedback_data(temp_feedback_data); if (0 != ret) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to add feedback data"); @@ -3415,13 +3420,12 @@ int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int free(temp_feedback_data); temp_feedback_data = NULL; } - - return ret; } - return VC_ERROR_NONE; + return ret; } + int vc_mgr_set_dialog_request_cb(vc_mgr_dialog_request_cb callback, void* user_data) { if (0 != __vc_mgr_get_feature_enabled()) { @@ -3984,19 +3988,56 @@ int vc_mgr_unset_feedback_streaming_cb() return 0; } +int vc_mgr_set_vc_tts_streaming_cb(vc_mgr_vc_tts_streaming_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set feedback streaming callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (VC_STATE_INITIALIZED != state) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set feedback streaming callback : Current state is not 'Initialized' (%d)", state); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_vc_tts_streaming_cb(g_vc_m, callback, user_data); + + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Set feedback streaming callback"); + + return 0; +} + +int vc_mgr_unset_vc_tts_streaming_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset feedback streaming callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (VC_STATE_INITIALIZED != state) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset feedback streaming callback : Current state is not 'Initialized' (%d)", state); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_vc_tts_streaming_cb(g_vc_m, NULL, NULL); + + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Unset feedback streaming callback"); + + return 0; +} + static void __tts_feedback_thread(void* data, Ecore_Thread* thread) { SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Start thread"); vc_feedback_data_s* feedback_data = NULL; - vc_mgr_feedback_streaming_cb callback = NULL; - void* user_data = NULL; - - vc_mgr_client_get_feedback_streaming_cb(g_vc_m, &callback, &user_data); - if (NULL == callback) { - SLOG(LOG_WARN, TAG_VCM, "[WARNING] TTS feedback streaming callback is null"); - return; - } while (1) { int ret = -1; @@ -4027,6 +4068,16 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread) continue; } + if (getpid() == feedback_data->pid) { + vc_mgr_feedback_streaming_cb callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_feedback_streaming_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] TTS feedback streaming callback is null"); + return; + } + SLOG(LOG_DEBUG, TAG_VCM, "TTS feedback streaming callback is called"); vc_mgr_client_use_callback(g_vc_m); callback(feedback_data->event, feedback_data->data, feedback_data->data_size, user_data); @@ -4037,6 +4088,30 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread) SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish feedback"); break; } + } else { + vc_mgr_vc_tts_streaming_cb callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_vc_tts_streaming_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] vc tts streaming callback is null"); + vc_mgr_data_clear_feedback_data(&feedback_data); + return; + } + + SLOG(LOG_DEBUG, TAG_VCM, "vc tts feedback streaming callback is called"); + vc_mgr_client_use_callback(g_vc_m); + callback(feedback_data->pid, feedback_data->utt_id, feedback_data->event, feedback_data->data, feedback_data->data_size, user_data); + vc_mgr_client_not_use_callback(g_vc_m); + + /* If no feedback data and EVENT_FINISH */ + if (0 >= vc_mgr_data_get_feedback_data_size() && VC_FEEDBACK_EVENT_FINISH == feedback_data->event) { + SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish vc tts feedback"); + break; + } + } + if (feedback_data) + free(feedback_data); } } @@ -4139,3 +4214,44 @@ int vc_mgr_stop_feedback(void) #endif return ret; } + +int vc_mgr_send_utterance_status(int pid, int utt_id, int utt_status) +{ + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] send utterance status, pid(%d), utt_id(%d), utt_status(%d)", pid, utt_id, utt_status); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_mgr_dbus_send_utterance_status(pid, utt_id, utt_status); + if (0 != ret) { + SLOG(LOG_DEBUG, TAG_VCM, "[ERROR] Fail to send utterance status : %s", __vc_mgr_get_error_code(ret)); + return ret; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Send utterance status"); + } + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + + return 0; +} + diff --git a/client/vc_mgr_client.c b/client/vc_mgr_client.c index 861c64d..9f5124d 100644 --- a/client/vc_mgr_client.c +++ b/client/vc_mgr_client.c @@ -55,6 +55,8 @@ typedef struct { void* feedback_audio_format_user_data; vc_mgr_feedback_streaming_cb feedback_streaming_cb; void* feedback_streaming_user_data; + vc_mgr_vc_tts_streaming_cb vc_tts_streaming_cb; + void* vc_tts_streaming_user_data; /* All result */ vc_result_event_e all_result_event; @@ -189,6 +191,8 @@ int vc_mgr_client_create(vc_h* vc) client->feedback_audio_format_user_data = NULL; client->feedback_streaming_cb = NULL; client->feedback_streaming_user_data = NULL; + client->vc_tts_streaming_cb = NULL; + client->vc_tts_streaming_user_data = NULL; client->exclusive_cmd_option = false; @@ -716,6 +720,34 @@ int vc_mgr_client_get_feedback_streaming_cb(vc_h vc, vc_mgr_feedback_streaming_c return 0; } +int vc_mgr_client_set_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->vc_tts_streaming_cb = callback; + client->vc_tts_streaming_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->vc_tts_streaming_cb; + *user_data = client->vc_tts_streaming_user_data; + + return 0; +} + /* set/get option */ int vc_mgr_client_set_service_state(vc_h vc, vc_service_state_e state) { diff --git a/client/vc_mgr_client.h b/client/vc_mgr_client.h index e8104c0..9128f95 100644 --- a/client/vc_mgr_client.h +++ b/client/vc_mgr_client.h @@ -107,6 +107,10 @@ int vc_mgr_client_set_feedback_streaming_cb(vc_h vc, vc_mgr_feedback_streaming_c int vc_mgr_client_get_feedback_streaming_cb(vc_h vc, vc_mgr_feedback_streaming_cb* callback, void** user_data); +int vc_mgr_client_set_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb callback, void* user_data); + +int vc_mgr_client_get_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb* callback, void** user_data); + /* * set/get option diff --git a/client/vc_mgr_data.cpp b/client/vc_mgr_data.cpp index fa455cd..7053c46 100644 --- a/client/vc_mgr_data.cpp +++ b/client/vc_mgr_data.cpp @@ -35,6 +35,7 @@ int vc_mgr_data_add_feedback_data(vc_feedback_data_s* data) SLOG(LOG_ERROR, TAG_VCM, "[DATA ERROR] feedback data is NULL"); return VC_ERROR_INVALID_PARAMETER; } + SLOG(LOG_DEBUG, TAG_VCM, "[DATA] feedback_data : %p", *data); pthread_mutex_lock(&g_feedback_data_mutex); @@ -83,8 +84,6 @@ int vc_mgr_data_get_feedback_data(vc_feedback_data_s** data) int vc_mgr_data_get_feedback_data_size() { - SLOG(LOG_DEBUG, TAG_VCM, "[DATA] get feedback data size"); - int data_size = 0; pthread_mutex_lock(&g_feedback_data_mutex); @@ -102,7 +101,7 @@ int vc_mgr_data_clear_feedback_data(vc_feedback_data_s** data) pthread_mutex_lock(&g_feedback_data_mutex); if (!g_feedback_data.empty()) { - SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] data(%p) size(%d) rate(%d)", (*data)->data, (*data)->data_size, (*data)->rate); + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] pid(%d), utt_id(%d), data(%p) size(%d) rate(%d)", (*data)->pid, (*data)->utt_id, (*data)->data, (*data)->data_size, (*data)->rate); if (NULL != (*data)->data) { free((*data)->data); diff --git a/client/vc_mgr_data.h b/client/vc_mgr_data.h index 3e2960f..dcd6b63 100644 --- a/client/vc_mgr_data.h +++ b/client/vc_mgr_data.h @@ -35,6 +35,7 @@ typedef enum { } vc_feedback_state_e; typedef struct { + int pid; int utt_id; void* data; unsigned int data_size; diff --git a/client/vc_mgr_dbus.c b/client/vc_mgr_dbus.c index 246c59e..8f8adf6 100644 --- a/client/vc_mgr_dbus.c +++ b/client/vc_mgr_dbus.c @@ -54,7 +54,7 @@ extern int __vc_mgr_cb_private_data_requested(const char* key, char** data); /* for TTS feedback */ extern int __vc_mgr_cb_feedback_audio_format(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type); -extern int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int len); +extern int __vc_mgr_cb_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len); /* Authority */ extern int __vc_mgr_request_auth_enable(int pid); @@ -411,17 +411,21 @@ static Eina_Bool vc_mgr_listener_event_callback(void* data, Ecore_Fd_Handler *fd else if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_FEEDBACK_STREAMING)) { SLOG(LOG_INFO, TAG_VCM, "@@@ Get TTS feedback streaming"); + int pid = -1; + int utt_id = -1;; vc_feedback_event_e event; char* buffer = NULL; int len; dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &utt_id, DBUS_TYPE_INT32, &event, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &buffer, &len, DBUS_TYPE_INVALID); - __vc_mgr_cb_feedback_streaming(event, buffer, len); + __vc_mgr_cb_feedback_streaming(pid, utt_id, event, buffer, len); SLOG(LOG_INFO, TAG_VCM, "@@@"); } /* VCD_MANAGER_METHOD_FEEDBACK_STREAMING */ @@ -2293,3 +2297,35 @@ int vc_mgr_dbus_send_specific_engine_request(int pid, const char* engine_app_id, return 0; } + +int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = __get_message(pid, VC_MANAGER_METHOD_UTTERANCE_STATUS, VC_COMMAND_TYPE_FOREGROUND); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, "@@ vc send utterance status : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "@@ vc send utterance status : pid(%d), utt_id(%d), utt_status(%d)", pid, utt_id, utt_status); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INT32, &utt_status, + DBUS_TYPE_INVALID); + + dbus_message_set_no_reply(msg, TRUE); + + if (1 != dbus_connection_send(g_m_conn_sender, msg, NULL)) { + SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Fail to Send"); + return -1; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Dbus] SUCCESS Send"); + dbus_connection_flush(g_m_conn_sender); + } + + return 0; +} diff --git a/client/vc_mgr_dbus.h b/client/vc_mgr_dbus.h index 26789e8..b0b5c2f 100644 --- a/client/vc_mgr_dbus.h +++ b/client/vc_mgr_dbus.h @@ -74,6 +74,9 @@ int vc_mgr_dbus_request_start_feedback(int pid); int vc_mgr_dbus_request_stop_feedback(int pid); +int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status); + + #ifdef __cplusplus } #endif diff --git a/common/vc_defs.h b/common/vc_defs.h index d58ed69..0458c37 100644 --- a/common/vc_defs.h +++ b/common/vc_defs.h @@ -69,12 +69,17 @@ extern "C" { #define VC_METHOD_SET_SERVER_DIALOG "vc_method_set_server_dialog" #define VC_METHOD_DIALOG "vc_method_dialog" #define VC_METHOD_IS_SYS_COMMAND_VALID "vc_method_is_system_command_valid" +#define VC_METHOD_REQUEST_TTS "vc_method_request_tts" +#define VC_METHOD_CANCEL_TTS "vc_method_cancel_tts" +#define VC_METHOD_GET_TTS_AUDIO_FORMAT "vc_method_get_tts_audio_format" + #define VCD_METHOD_RESULT "vcd_method_result" #define VCD_METHOD_ERROR "vcd_method_error" #define VCD_METHOD_HELLO "vcd_method_hello" #define VCD_METHOD_SET_SERVICE_STATE "vcd_method_set_service_state" #define VCD_METHOD_SEND_MANAGER_PID "vcd_method_send_manager_pid" +#define VCD_METHOD_FEEDBACK_STREAMING "vcd_method_feedback_streaming" /* Authority */ #if 0 @@ -144,6 +149,7 @@ extern "C" { #define VC_MANAGER_METHOD_START_FEEDBACK "vc_manager_method_request_start_feedback" #define VC_MANAGER_METHOD_STOP_FEEDBACK "vc_manager_method_request_stop_feedback" +#define VC_MANAGER_METHOD_UTTERANCE_STATUS "vc_manager_method_utterance_status" #define VCD_MANAGER_METHOD_HELLO "vcd_manager_method_hello" #define VCD_MANAGER_METHOD_SPEECH_DETECTED "vcd_manager_method_speech_detected" diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index eeacc29..52960a4 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -25,3 +25,4 @@ INSTALL(FILES ${CMAKE_BINARY_DIR}/include/voice_control_manager_internal.h DESTI INSTALL(FILES ${CMAKE_BINARY_DIR}/include/voice_control_setting.h DESTINATION ${INCLUDEDIR}) INSTALL(FILES ${CMAKE_BINARY_DIR}/include/voice_control_widget.h DESTINATION ${INCLUDEDIR}) INSTALL(FILES ${CMAKE_BINARY_DIR}/include/vce.h DESTINATION ${INCLUDEDIR}) +INSTALL(FILES ${CMAKE_BINARY_DIR}/include/vce_internal.h DESTINATION ${INCLUDEDIR}) diff --git a/include/vce.h b/include/vce.h index af5c5fd..af6f5ce 100644 --- a/include/vce.h +++ b/include/vce.h @@ -557,6 +557,72 @@ typedef int (*vce_get_info_cb)(char** engine_uuid, char** engine_name, char** en */ typedef bool (*vce_command_cb)(int id, int type, int format, const char* command, const char* param, int domain, void* user_data); +/** + * @brief Called when the engine service user (voice control client) requests to send TTS feedback. + * @since_tizen 5.0 + * @remarks The @a text and @a language can be used only in the callback. To use outside, make a copy. + * + * @param[in] pid The process id of the engine service user (voice control client) + * @param[in] utt_id The utterance id + * @param[in] text The text for TTS feedback + * @param[in] language The language + * @param[in] user_data The user data passed from the callback setter function + * + * @return 0 on success, otherwise a negative error value. + * @retval #VCE_ERROR_NONE Successful + * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VCE_ERROR_OPERATION_FAILED Operation failure + * + * @pre An application registers callback function using vce_set_request_tts_cb(). + * + * @see vce_set_request_tts_cb() + * @see vce_unset_request_tts_cb() + */ +typedef int (*vce_request_tts_cb)(int pid, int utt_id, const char* text, const char* language, void* user_data); + +/** + * @brief Called when the engine service user cancels TTS feedback. + * @since_tizen 5.0 + * + * @param[in] pid The process id of the engine service user + * @param[in] utt_id The utterance id corresponding to the text + * @param[in] user_data The user data passed from the callback setter function + * + * @return 0 on success, otherwise a negative error value. + * @retval #VCE_ERROR_NONE Successful + * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VCE_ERROR_OPERATION_FAILED Operation failure + * + * @pre An application registers callback function using vce_set_cancel_tts_cb(). + * + * @see vce_set_cancel_tts_cb() + * @see vce_unset_cancel_tts_cb() +*/ +typedef int (*vce_cancel_tts_cb)(int pid, int utt_id, void* user_data); + +/** + * @brief Called when the engine service user requests TTS audio format. + * @since_tizen 5.0 + * @remarks The @a rate, @a channel, and @a audio_type should not be released. + * The @a rate, @a channel, and @a audio_type are managed by the platform and will be released after the audio format is transferred to the VC client. + * + * @param[out] rate The audio sample rate + * @param[out] channel The audio channel + * @param[out] audio_type The audio type + * @param[in] user_data The user data passed from the callback setter function + * + * @return 0 on success, otherwise a negative error value. + * @retval #VCE_ERROR_NONE Successful + * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VCE_ERROR_OPERATION_FAILED Operation failure + * + * @pre An application registers callback function using vce_set_tts_audio_format_request_cb(). + * + * @see vce_set_tts_audio_format_request_cb() + * @see vce_unset_tts_audio_format_request_cb() + */ +typedef int (*vce_tts_audio_format_request_cb)(int* rate, int* channel, int* audio_type, void* user_data); + /** * @brief A structure for the VC engine functions. @@ -596,10 +662,10 @@ typedef struct { vce_process_haptic_event_cb process_haptic_event; /**< Request to process haptic event */ /* Optional callbacks */ - vce_private_data_set_cb private_data_set; - vce_private_data_requested_cb private_data_request; - vce_nlu_base_info_requested_cb nlu_base_info_request; - vce_specific_engine_request_cb specific_engine_request; + vce_private_data_set_cb private_data_set; /**< Set private data from the app */ + vce_private_data_requested_cb private_data_request; /**< Send private data to the app */ + vce_nlu_base_info_requested_cb nlu_base_info_request; /**< Send essential value from NLU result */ + vce_specific_engine_request_cb specific_engine_request; /**< Get specific engine's request from the engine service user */ } vce_request_callback_s; /** @@ -1038,6 +1104,93 @@ int vce_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_au */ int vce_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int len); +/** + * @brief Sets a callback function for getting the request of sending TTS feedback from the engine service user. + * @since_tizen 5.0 + * + * @param[in] callback_func Callback function to be registered + * @param[in] user_data The user data passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #VCE_ERROR_NONE Successful + * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VCE_ERROR_NOT_SUPPORTED Not supported + * + * @see vce_request_tts_cb() + * @see vce_unset_request_tts_cb() + */ +int vce_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data); + +/** + * @brief Unsets the TTS feedback request callback function. + * @since_tizen 5.0 + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @see vce_set_request_tts_cb() + */ +int vce_unset_request_tts_cb(void); + +/** + * @brief Sets a callback function for getting the request of canceling TTS feedback from the engine service user. + * @since_tizen 5.0 + * + * @param[in] callback_func Callback function to be registered + * @param[in] user_data The user data passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #VCE_ERROR_NONE Successful + * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VCE_ERROR_NOT_SUPPORTED Not supported + * + * @see vce_cancel_tts_cb() + * @see vce_unset_cancel_tts_cb() + */ +int vce_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data); + +/** + * @brief Unsets the TTS feedback cancellation callback function. + * @since_tizen 5.0 + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @see vce_set_cancel_tts_cb() + */ +int vce_unset_cancel_tts_cb(void); + +/** + * @brief Sets a callback function for sending TTS audio format to the engine service user. + * @since_tizen 5.0 + * + * @param[in] callback_func Callback function to be registered + * @param[in] user_data The user data passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #VCE_ERROR_NONE Successful + * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VCE_ERROR_NOT_SUPPORTED Not supported + * + * @see vce_tts_audio_format_request_cb() + * @see vce_unset_get_tts_audio_format_cb() + */ +int vce_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data); + +/** + * @brief Unsets the TTS audio format request callback function. + * @since_tizen 5.0 + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @see vce_set_tts_audio_format_cb() + */ +int vce_unset_get_tts_audio_format_cb(void); + #ifdef __cplusplus } diff --git a/include/vce_internal.h b/include/vce_internal.h new file mode 100644 index 0000000..c7439bb --- /dev/null +++ b/include/vce_internal.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011-2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __VCE_INTERNAL_H__ +#define __VCE_INTERNAL_H__ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief A structure for the VC engine functions. + * @details This structure contains essential callback functions for operating VC engine. + * @since_tizen 4.0 + * @remarks These functions are optional for operating VC engine. + */ +typedef struct { + /* Optional callbacks */ + vce_request_tts_cb request_tts; + void* request_tts_user_data; + vce_cancel_tts_cb cancel_tts; + void* cancel_tts_user_data; + vce_tts_audio_format_request_cb get_tts_audio_format; + void* get_tts_audio_format_user_data; +} vce_internal_request_callback_s; + + +#ifdef __cplusplus +} +#endif + +/** +* @} +*/ + +#endif /* __VCE_INTERNAL_H__ */ diff --git a/include/voice_control_internal.h b/include/voice_control_internal.h index 0f62a23..dc26186 100644 --- a/include/voice_control_internal.h +++ b/include/voice_control_internal.h @@ -26,6 +26,20 @@ extern "C" { #endif +typedef enum { + VC_TTS_EVENT_FAIL = -1, /**< Failed */ + VC_TTS_EVENT_START = 1, /**< Start event */ + VC_TTS_EVENT_CONTINUE = 2, /**< Continue event */ + VC_TTS_EVENT_FINISH = 3 /**< Finish event */ +} vc_tts_event_e; + +typedef enum { + VC_TTS_UTTERANCE_NONE = -1, + VC_TTS_UTTERANCE_STARTED = 1, + VC_TTS_UTTERANCE_COMPLETED = 2, + VC_TTS_UTTERANCE_CANCELED = 3 +} vc_tts_utterance_status_e; + /** * @brief Called when client gets the asr recognition result from vc-daemon. * @@ -43,6 +57,37 @@ extern "C" typedef bool (*vc_asr_result_cb)(vc_result_event_e event, const char* result, void *user_data); /** + * @brief Called when client gets TTS streaming data from vc engine service. + * @since_tizen 4.0 + * + * @param[in] event The TTS event + * @param[in] buffer The TTS streaming data + * @param[in] len The length of the TTS streaming data + * @param[in] utt_id The utterance id + * @param[in] user_data The user data passed from the callback registration function + * + * @pre An application registers callback function using vc_tts_set_streaming_cb(). + * + * @see vc_tts_set_streaming_cb() + * @see vc_tts_unset_streaming_cb() + */ +typedef void (*vc_tts_streaming_cb)(vc_tts_event_e event, char* buffer, int len, int utt_id, void *user_data); + +/** + * @brief Called when client gets TTS utterance status. + * @since_tizen 4.0 + * + * @param[in] utt_id The utterance id + * @param[in] status The TTS utterance status (e.g. #VC_TTS_UTTERANCE_STARTED, #VC_TTS_UTTERANCE_COMPLETED, and so on) + * + * @pre An application registers callback function using vc_tts_set_utterance_status_cb(). + * + * @see vc_tts_set_utterance_status_cb() + * @see vc_tts_unset_utterance_status_cb() + */ +typedef void (*vc_tts_utterance_status_cb)(int utt_id, vc_tts_utterance_status_e status); + +/** * @brief Sets command list from file. * @since_tizen 3.0 * @privlevel public @@ -86,6 +131,131 @@ int vc_set_command_list_from_file(const char* file_path, int type); */ int vc_prepare_sync(void); +/** + * @brief Requests to send TTS streaming data. + * @since_tizen 4.0 + * + * @param[in] text The text to be requested for TTS + * @param[in] language The language for TTS + * @param[in] to_vcm A value whether the TTS request is from vc client or vc manager + * @param[in] utt_id The utterance id + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_READY. + * + * @see vc_tts_cancel() + */ +int vc_tts_request(const char* text, const char* language, bool to_vcm, int* utt_id); + +/** + * @brief Requests to cancel TTS streaming data. + * @since_tizen 4.0 + * + * @param[in] utt_id The utterance id + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_READY. + * + * @see vc_tts_request() + */ +int vc_tts_cancel(int utt_id); + +/** + * @brief Gets TTS audio format. + * @since_tizen 4.0 + * + * @param[out] rate The audio sampling rate + * @param[out] channel The audio channel + * @param[out] audio_type The audio type + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_READY. + */ +int vc_tts_get_audio_format(int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type); + +/** + * @brief Sets TTS streaming callback function. + * @since_tizen 4.0 + * + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_INITIALIZED. + */ +int vc_tts_set_streaming_cb(vc_tts_streaming_cb callback, void* user_data); + +/** + * @brief Unsets TTS streaming callback function. + * @since_tizen 4.0 + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_INITIALIZED. + */ +int vc_tts_unset_streaming_cb(void); + +/** + * @brief Sets TTS utterance status callback function. + * @since_tizen 4.0 + * + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_INITIALIZED. + */ +int vc_tts_set_utterance_status_cb(vc_tts_utterance_status_cb callback, void* user_data); + +/** + * @brief Unsets TTS utterance status callback function. + * @since_tizen 4.0 + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_PERMISSION_DENIED Permission denied + * @retval #VC_ERROR_NOT_SUPPORTED Not supported + * + * @pre The state should be #VC_STATE_INITIALIZED. + */ +int vc_tts_unset_utterance_status_cb(void); + #ifdef __cplusplus } diff --git a/include/voice_control_manager.h b/include/voice_control_manager.h index b6918e8..430daa5 100644 --- a/include/voice_control_manager.h +++ b/include/voice_control_manager.h @@ -248,6 +248,7 @@ typedef int (*vc_mgr_private_data_requested_cb)(const char *key, char **data, vo /* for TTS feedback */ /** * @brief Called when engine sends audio formats necessary for playing TTS feedback +* @since_tizen 5.0 * * @param[in] rate Audio sampling rate * @param[in] channel Audio channel (e.g. #VC_AUDIO_CHANNEL_MONO, #VC_AUDIO_CHANNEL_STEREO) @@ -263,6 +264,7 @@ typedef void (*vc_mgr_feedback_audio_format_cb)(int rate, vc_audio_channel_e cha /** * @brief Called when engine sends audio streaming for TTS feedback +* @since_tizen 5.0 * * @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE) * @param[in] buffer Audio streaming data @@ -276,6 +278,25 @@ typedef void (*vc_mgr_feedback_audio_format_cb)(int rate, vc_audio_channel_e cha */ typedef void (*vc_mgr_feedback_streaming_cb)(vc_feedback_event_e event, char* buffer, int len, void *user_data); +/** +* @brief Called when the vc client sends audio streaming for TTS feedback +* @since_tizen 5.0 +* +* @remarks The @a buffer must be released with free() by you when you no longer need it. +* +* @param[in] pid The process id of the vc client +* @param[in] utt_id The utterance id +* @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE) +* @param[in] buffer Audio streaming data +* @param[in] len Length of the audio streaming data +* @param[in] user_data The user data passed from the callback registration function +* +* @pre An application registers callback function using vc_mgr_set_vc_tts_streaming_cb(). +* +* @see vc_mgr_set_vc_tts_streaming_cb() +* @see vc_mgr_unset_vc_tts_streaming_cb() +*/ +typedef void (*vc_mgr_vc_tts_streaming_cb)(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len, void *user_data); /** * @platform @@ -1701,6 +1722,40 @@ int vc_mgr_start_feedback(void); */ int vc_mgr_stop_feedback(void); +/** + * @brief Sets TTS streaming callback function. + * @since_tizen 5.0 + * + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_STATE Invalid state + * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter + * + * @pre The state should be #VC_STATE_INITIALIZED. + * + * @see vc_mgr_vc_tts_streaming_cb() + * @see vc_mgr_unset_vc_tts_streaming_cb() + */ +int vc_mgr_set_vc_tts_streaming_cb(vc_mgr_vc_tts_streaming_cb callback, void* user_data); + +/** + * @brief Unsets TTS streaming callback function. + * @since_tizen 5.0 + * + * @return 0 on success, otherwise a negative error value + * @retval #VC_ERROR_NONE Successful + * @retval #VC_ERROR_INVALID_STATE Invalid state + * + * @pre The state should be #VC_STATE_INITIALIZED. + * + * @see vc_mgr_vc_tts_streaming_cb() + * @see vc_mgr_set_vc_tts_streaming_cb() + */ +int vc_mgr_unset_vc_tts_streaming_cb(void); + #ifdef __cplusplus } diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index 4b94bd5..06035f5 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -177,4 +177,5 @@ mkdir -p %{_libdir}/voice/vc %defattr(-,root,root,-) %{_libdir}/pkgconfig/voice-control-engine.pc %{_includedir}/vce.h +%{_includedir}/vce_internal.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 0065863..778f56d 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -7,6 +7,7 @@ SET(SRCS ../common/vc_info_parser.c ../common/vc_json_parser.c vcd_client_data.c + vcd_server_data.cpp vcd_config.c vcd_dbus_server.c vcd_dbus.c @@ -26,6 +27,7 @@ FOREACH(flag ${pkgs_CFLAGS}) ENDFOREACH(flag) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") +SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -fPIE") SET(CMAKE_C_FLAGS_RELEASE "-O2 -fPIE") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") diff --git a/server/vcd_dbus.c b/server/vcd_dbus.c index e53814c..69e1f52 100644 --- a/server/vcd_dbus.c +++ b/server/vcd_dbus.c @@ -980,9 +980,9 @@ int vcdc_send_feedback_audio_format_to_manager(int manager_pid, int rate, vc_aud return ret; } -int vcdc_send_feedback_streaming_to_manager(int manager_pid, vc_feedback_event_e event, char* buffer, int len) +int vcdc_send_feedback_streaming_to_manager(int manager_pid, int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len) { - SLOG(LOG_INFO, TAG_VCD, "[Dbus] Send TTS feedback streaming : manager_pid(%d), feedback event(%d), buffer(%p), length(%d)", manager_pid, event, buffer, len); + SLOG(LOG_INFO, TAG_VCD, "[Dbus] Send TTS feedback streaming : manager_pid(%d), pid(%d), utt_id(%d) feedback event(%d), buffer(%p), length(%d)", manager_pid, pid, utt_id, event, buffer, len); if (0 != __dbus_check()) { return VCD_ERROR_OPERATION_FAILED; @@ -1000,6 +1000,51 @@ int vcdc_send_feedback_streaming_to_manager(int manager_pid, vc_feedback_event_e } dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INT32, &event, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buffer, len, + DBUS_TYPE_INVALID); + + dbus_message_set_no_reply(msg, TRUE); + + int ret = VCD_ERROR_NONE; + + if (1 != dbus_connection_send(g_conn_sender, msg, NULL)) { + SLOG(LOG_ERROR, TAG_VCD, "[Dbus ERROR] Fail to Send"); + ret = VCD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_INFO, TAG_VCD, "[Dbus] SUCCESS Send"); + dbus_connection_flush(g_conn_sender); + } + + dbus_message_unref(msg); + + return ret; +} + +int vcdc_send_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len) +{ + SLOG(LOG_INFO, TAG_VCD, "[Dbus] Send TTS feedback streaming : pid(%d), utt_id(%d), feedback event(%d), buffer(%p), length(%d)", pid, utt_id, event, buffer, len); + + if (0 != __dbus_check()) { + return VCD_ERROR_OPERATION_FAILED; + } + + DBusError err; + dbus_error_init(&err); + + /* make dbus message */ + DBusMessage* msg = NULL; + msg = __get_message(pid, VCD_METHOD_FEEDBACK_STREAMING, VCD_CLIENT_TYPE_NORMAL); + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCD, "[Dbus ERROR] Message is NULL"); + return VCD_ERROR_OUT_OF_MEMORY; + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &utt_id, DBUS_TYPE_INT32, &event, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &buffer, len, @@ -1168,6 +1213,15 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_SETTING_METHOD_SET_LANGUAGE)) vcd_dbus_server_set_language(g_conn_listener, msg); + else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_REQUEST_TTS)) + vcd_dbus_server_request_tts(g_conn_listener, msg); + + else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_CANCEL_TTS)) + vcd_dbus_server_cancel_tts(g_conn_listener, msg); + + else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_GET_TTS_AUDIO_FORMAT)) + vcd_dbus_server_get_tts_audio_format(g_conn_listener, msg); + else { SLOG(LOG_DEBUG, TAG_VCD, "Message is NOT valid"); dbus_message_unref(msg); diff --git a/server/vcd_dbus.h b/server/vcd_dbus.h index 0dbe188..a6d97a5 100644 --- a/server/vcd_dbus.h +++ b/server/vcd_dbus.h @@ -71,7 +71,9 @@ int vcdc_send_request_get_private_data(int pid, const char* key, char** data); /* for TTS feedback */ int vcdc_send_feedback_audio_format_to_manager(int manager_pid, int rate, vc_audio_channel_e channel, vce_audio_type_e audio_type); -int vcdc_send_feedback_streaming_to_manager(int manager_pid, vc_feedback_event_e event, char* buffer, int len); +int vcdc_send_feedback_streaming_to_manager(int manager_pid, int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len); + +int vcdc_send_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len); #ifdef __cplusplus diff --git a/server/vcd_dbus_server.c b/server/vcd_dbus_server.c index 71329a6..68b0ae1 100644 --- a/server/vcd_dbus_server.c +++ b/server/vcd_dbus_server.c @@ -2205,4 +2205,172 @@ int vcd_dbus_server_set_language(DBusConnection* conn, DBusMessage* msg) SLOG(LOG_DEBUG, TAG_VCD, "@@@"); return 0; -} \ No newline at end of file +} +int vcd_dbus_server_request_tts(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + char* text = NULL; + char* language = NULL; + int to_vcm; + int utt_id = -1; + int ret = VCD_ERROR_OPERATION_FAILED; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_STRING, &language, + DBUS_TYPE_INT32, &to_vcm, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD request tts"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd request tts : get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd request tts : pid(%d), text(%s), language(%s), to_vcm(%d)", pid, text, language, to_vcm); + ret = vcd_server_request_tts(pid, text, language, to_vcm, &utt_id); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d), utt_id(%d)", ret, utt_id); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_VCD, "@@@"); + + return 0; +} + +int vcd_dbus_server_cancel_tts(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int utt_id; + int ret = VCD_ERROR_OPERATION_FAILED; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &utt_id, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD cancel tts"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd cancel tts : get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd cancel tts : pid(%d), utt_id(%d)", pid, utt_id); + ret = vcd_server_cancel_tts(pid, utt_id); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d)", ret); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_VCD, "@@@"); + + return 0; +} + +int vcd_dbus_server_get_tts_audio_format(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int rate; + int channel; + int audio_type; + int ret = VCD_ERROR_OPERATION_FAILED; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD request tts"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd get tts audio format : get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd get tts audio format : pid(%d)", pid); + ret = vcd_server_get_tts_audio_format(pid, &rate, &channel, &audio_type); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INT32, &rate, + DBUS_TYPE_INT32, &channel, + DBUS_TYPE_INT32, &audio_type, + DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d)", ret); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_VCD, "@@@"); + + return 0; +} diff --git a/server/vcd_dbus_server.h b/server/vcd_dbus_server.h index 1456536..bef7205 100644 --- a/server/vcd_dbus_server.h +++ b/server/vcd_dbus_server.h @@ -126,6 +126,13 @@ int vcd_dbus_server_widget_enable_asr_result(DBusConnection* conn, DBusMessage* int vcd_dbus_server_set_language(DBusConnection* conn, DBusMessage* msg); +int vcd_dbus_server_request_tts(DBusConnection* conn, DBusMessage* msg); + +int vcd_dbus_server_cancel_tts(DBusConnection* conn, DBusMessage* msg); + +int vcd_dbus_server_get_tts_audio_format(DBusConnection* conn, DBusMessage* msg); + + #ifdef __cplusplus } #endif diff --git a/server/vcd_engine_agent.c b/server/vcd_engine_agent.c index 8794ae0..68b8f83 100644 --- a/server/vcd_engine_agent.c +++ b/server/vcd_engine_agent.c @@ -24,6 +24,7 @@ #include "vcd_main.h" #include "vcd_recorder.h" #include "vcd_dbus.h" +#include "vce_internal.h" /* * Internal data structure @@ -43,6 +44,7 @@ typedef struct { void *handle; vce_request_callback_s* callbacks; + vce_internal_request_callback_s* internal_callbacks; } vcengine_s; typedef struct _vcengine_info { @@ -96,7 +98,13 @@ int vcd_engine_agent_init() g_dynamic_engine.callbacks = (vce_request_callback_s*)calloc(1, sizeof(vce_request_callback_s)); if (NULL == g_dynamic_engine.callbacks) { - SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to allocate memory"); + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to allocate memory for callbacks"); + return VCD_ERROR_OUT_OF_MEMORY; + } + + g_dynamic_engine.internal_callbacks = (vce_internal_request_callback_s*)calloc(1, sizeof(vce_internal_request_callback_s)); + if (NULL == g_dynamic_engine.internal_callbacks) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to allocate memory for internal callbacks"); return VCD_ERROR_OUT_OF_MEMORY; } @@ -188,7 +196,17 @@ int __internal_get_engine_info(vce_request_callback_s* callback) } g_dynamic_engine.callbacks = (vce_request_callback_s*)calloc(1, sizeof(vce_request_callback_s)); if (NULL == g_dynamic_engine.callbacks) { - SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to allocate memory"); + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to allocate memory for callbacks"); + return VCD_ERROR_OUT_OF_MEMORY; + } + + if (NULL != g_dynamic_engine.internal_callbacks) { + free(g_dynamic_engine.internal_callbacks); + g_dynamic_engine.internal_callbacks = NULL; + } + g_dynamic_engine.internal_callbacks = (vce_internal_request_callback_s*)calloc(1, sizeof(vce_internal_request_callback_s)); + if (NULL == g_dynamic_engine.internal_callbacks) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to allocate memory for internal callbacks"); return VCD_ERROR_OUT_OF_MEMORY; } @@ -217,6 +235,9 @@ int __internal_get_engine_info(vce_request_callback_s* callback) g_dynamic_engine.callbacks->private_data_request = NULL; g_dynamic_engine.callbacks->nlu_base_info_request = NULL; g_dynamic_engine.callbacks->specific_engine_request = NULL; + g_dynamic_engine.internal_callbacks->request_tts = NULL; + g_dynamic_engine.internal_callbacks->cancel_tts = NULL; + g_dynamic_engine.internal_callbacks->get_tts_audio_format = NULL; SLOG(LOG_DEBUG, TAG_VCD, "@@@ Valid Engine"); SLOG(LOG_DEBUG, TAG_VCD, "Engine uuid : %s", g_dynamic_engine.engine_uuid); @@ -668,6 +689,75 @@ int vcd_engine_process_haptic_event(int pid, const char* event) return 0; } +int vcd_engine_request_tts(int pid, int utt_id, const char* text, const char* language) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized"); + return VCD_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Request tts to engine"); + + int ret = -1; + if (true == g_dynamic_engine.is_loaded && NULL != g_dynamic_engine.internal_callbacks->request_tts) { + ret = g_dynamic_engine.internal_callbacks->request_tts(pid, utt_id, text, language, g_dynamic_engine.internal_callbacks->request_tts_user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set request tts (%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + } else { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no request tts callback"); + return VCD_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int vcd_engine_cancel_tts(int pid, int utt_id) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized"); + return VCD_ERROR_OPERATION_FAILED; + } + + int ret = -1; + if (true == g_dynamic_engine.is_loaded && NULL != g_dynamic_engine.internal_callbacks->cancel_tts) { + ret = g_dynamic_engine.internal_callbacks->cancel_tts(pid, utt_id, g_dynamic_engine.internal_callbacks->cancel_tts_user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set cancel tts (%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + } else { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no cancel tts callback"); + return VCD_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int vcd_engine_get_tts_audio_format(int* rate, int* channel, int* audio_type) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized"); + return VCD_ERROR_OPERATION_FAILED; + } + + int ret = -1; + if (true == g_dynamic_engine.is_loaded && NULL != g_dynamic_engine.internal_callbacks->get_tts_audio_format) { + ret = g_dynamic_engine.internal_callbacks->get_tts_audio_format(rate, channel, audio_type, g_dynamic_engine.internal_callbacks->get_tts_audio_format_user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get tts audio format(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + } else { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no get tts audio format callback"); + return VCD_ERROR_OPERATION_FAILED; + } + + return 0; +} + + /* * VCS Engine Interfaces for client and setting */ @@ -904,3 +994,57 @@ int vcd_engine_agent_set_specific_engine_request_cb(vce_specific_engine_request_ return VCD_ERROR_NONE; } + +int vcd_engine_agent_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized"); + return VCD_ERROR_OPERATION_FAILED; + } + + if (false == g_dynamic_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not loaded engine"); + return VCD_ERROR_OPERATION_FAILED; + } + + g_dynamic_engine.internal_callbacks->request_tts = callback_func; + g_dynamic_engine.internal_callbacks->request_tts_user_data = user_data; + + return VCD_ERROR_NONE; +} + +int vcd_engine_agent_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized"); + return VCD_ERROR_OPERATION_FAILED; + } + + if (false == g_dynamic_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not loaded engine"); + return VCD_ERROR_OPERATION_FAILED; + } + + g_dynamic_engine.internal_callbacks->cancel_tts = callback_func; + g_dynamic_engine.internal_callbacks->cancel_tts_user_data = user_data; + + return VCD_ERROR_NONE; +} + +int vcd_engine_agent_set_get_tts_audio_format_cb(vce_tts_audio_format_request_cb callback_func, void* user_data) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized"); + return VCD_ERROR_OPERATION_FAILED; + } + + if (false == g_dynamic_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not loaded engine"); + return VCD_ERROR_OPERATION_FAILED; + } + + g_dynamic_engine.internal_callbacks->get_tts_audio_format = callback_func; + g_dynamic_engine.internal_callbacks->get_tts_audio_format_user_data = user_data; + + return VCD_ERROR_NONE; +} diff --git a/server/vcd_engine_agent.h b/server/vcd_engine_agent.h index 4dc5e25..2532a82 100644 --- a/server/vcd_engine_agent.h +++ b/server/vcd_engine_agent.h @@ -84,6 +84,13 @@ int vcd_engine_process_list_event(int pid, const char* event); int vcd_engine_process_haptic_event(int pid, const char* event); +int vcd_engine_request_tts(int pid, int utt_id, const char* text, const char* language); + +int vcd_engine_cancel_tts(int pid, int utt_id); + +int vcd_engine_get_tts_audio_format(int* rate, int* channel, int* audio_type); + + /* for engine service */ int vcd_engine_agent_get_foreach_command(vce_cmd_h vce_command, vce_command_cb callback, void* user_data); @@ -107,6 +114,13 @@ int vcd_engine_agent_set_nlu_base_info_requested_cb(vce_nlu_base_info_requested_ int vcd_engine_agent_set_specific_engine_request_cb(vce_specific_engine_request_cb callback_func); +int vcd_engine_agent_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data); + +int vcd_engine_agent_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data); + +int vcd_engine_agent_set_get_tts_audio_format_cb(vce_tts_audio_format_request_cb callback_func, void* user_data); + + #ifdef __cplusplus } #endif diff --git a/server/vcd_main.h b/server/vcd_main.h index a9f7943..3d8525b 100644 --- a/server/vcd_main.h +++ b/server/vcd_main.h @@ -74,9 +74,9 @@ typedef enum { VCD_STATE_PROCESSING = 3 } vcd_state_e; -typedef struct { +struct vce_cmd_s { int index; -} vce_cmd_s; +}; #ifdef __cplusplus diff --git a/server/vcd_server.c b/server/vcd_server.c index f949962..d79b946 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -23,6 +23,7 @@ #include "vc_info_parser.h" #include "vcd_main.h" #include "vcd_server.h" +#include "vcd_server_data.h" #include "vcd_client_data.h" #include "vcd_engine_agent.h" @@ -43,6 +44,10 @@ static Ecore_Timer *g_restart_timer = NULL; static Ecore_Timer *g_check_widget_client_timer = NULL; static Ecore_Timer *g_check_client_timer = NULL; +static Ecore_Thread* g_tts_thread = NULL; +static int g_current_uid = -1; +static int g_current_utt_id = -1; + /** * @brief Enumerations of send event type. */ @@ -1096,25 +1101,51 @@ int vcd_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_au /* send TTS feedback audio format to VC manager */ int ret = VCD_ERROR_NONE; + int pid = g_current_uid / 1000; + if (-1 == g_current_uid || vcd_client_manager_get_pid() == pid) { ret = vcdc_send_feedback_audio_format_to_manager(vcd_client_manager_get_pid(), rate, channel, audio_type); if (VCD_ERROR_NONE != ret) { SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback audio format to VC manager"); } + } else { + SLOG(LOG_INFO, TAG_VCD, "[Server INFO] Do not send TTS feedback audio format to VC manager"); + } return ret; } int vcd_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int len) { - SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback streaming"); + if (-1 == g_current_uid && VCE_FEEDBACK_EVENT_START == event) { + g_current_utt_id = (g_current_utt_id + 1) % 1000; + g_current_uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id; + SLOG(LOG_INFO, TAG_VCD, "[Server info] set current uid and utt_id as manager pid"); + } - /* send TTS feedback streaming to VC manager */ int ret = VCD_ERROR_NONE; - ret = vcdc_send_feedback_streaming_to_manager(vcd_client_manager_get_pid(), event, buffer, len); + int pid = g_current_uid / 1000; + int utt_id = g_current_uid % 1000; + + SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback streaming to pid(%d), is_mgr_client(%d)", pid, (pid == vcd_client_manager_get_pid() ? true : false)); + + if (pid == vcd_client_manager_get_pid()) { + /* send TTS feedback streaming to manager client */ + ret = vcdc_send_feedback_streaming_to_manager(vcd_client_manager_get_pid(), pid, utt_id, event, buffer, len); + if (VCD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to manager client"); + } + } else { + /* send TTS feedback streaming to client */ + ret = vcdc_send_feedback_streaming(pid, utt_id, event, buffer, len); if (VCD_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to VC manager"); + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to client"); + } } + if (VCE_FEEDBACK_EVENT_FINISH == event) { + /* reset current uid */ + g_current_uid = -1; + } return ret; } @@ -1221,6 +1252,9 @@ int vcd_initialize(vce_request_callback_s *callback) SLOG(LOG_WARN, TAG_VCD, "[Server Warning] Fail to create timer of client check"); } + g_current_uid = -1; + g_current_utt_id = -1; + SLOG(LOG_ERROR, TAG_VCD, "[Server SUCCESS] initialize"); return 0; @@ -2420,6 +2454,157 @@ int vcd_server_is_system_command_valid(int pid, int* is_sys_cmd_valid) return 0; } +static void __start_tts_request_thread(void* data, Ecore_Thread* thread) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[SUCCESS] Start tts request thread"); + vc_tts_text_data_s* tts_text_data = NULL; + + while (1) { + int ret = -1; + + /* Get tts text data */ + ret = vcd_data_get_first_tts_text_data(&tts_text_data); + if (0 != ret || NULL == tts_text_data) { + /* empty queue */ + if (0 >= vcd_data_get_tts_text_data_size()) { + SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] No tts text data"); + return; + } + SLOG(LOG_INFO, TAG_VCD, "[INFO] tts text data is just incoming"); + continue; + } + + /* Request tts to engine */ + ret = vcd_engine_request_tts(tts_text_data->pid, tts_text_data->utt_id, tts_text_data->text, tts_text_data->language); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to request tts : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[Server SUCCESS] request tts, uid(%d) pid(%d), text(%s), language(%s), utt_id(%d)", + tts_text_data->uid, tts_text_data->pid, tts_text_data->text, tts_text_data->language, tts_text_data->utt_id); + } + /* clear tts text data after use */ + vcd_data_clear_tts_text_data(&tts_text_data); + + } +} + +static void __end_tts_request_thread(void* data, Ecore_Thread* thread) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[SUCCESS] End tts request thread"); + g_tts_thread = NULL; +} + +int vcd_server_request_tts(int pid, const char* text, const char* language, int to_vcm, int* utt_id) +{ + /* check if pid is valid */ + if (false == vcd_client_is_available(pid)) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid "); + return VCD_ERROR_INVALID_PARAMETER; + } + + vcd_state_e state = vcd_config_get_service_state(); + if (VCD_STATE_READY != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready, state(%d)", state); + return VCD_ERROR_INVALID_STATE; + } + + g_current_utt_id = (g_current_utt_id + 1) % 1000; + *utt_id = g_current_utt_id; + if (0 == to_vcm) { + g_current_uid = pid * 1000 + g_current_utt_id; + } else { + g_current_uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id; + } + SLOG(LOG_INFO, TAG_VCD, "[Server INFO] pid(%d), text(%s), language(%s), to_vcm(%d), ", pid, text, language, to_vcm); + SLOG(LOG_INFO, TAG_VCD, "[Server INFO] current_uid(%d), current_utt_id(%d)", g_current_uid, g_current_utt_id); + + vc_tts_text_data_s* tts_text_data; + tts_text_data = (vc_tts_text_data_s*)calloc(1, sizeof(vc_tts_text_data_s)); + if (!tts_text_data) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to callocate memory "); + return VCD_ERROR_OUT_OF_MEMORY; + } + tts_text_data->uid = g_current_uid; + tts_text_data->pid = pid; + tts_text_data->utt_id = g_current_utt_id; + tts_text_data->text = strdup(text); + tts_text_data->language = strdup(language); + + int ret = vcd_data_add_tts_text_data(tts_text_data->uid, tts_text_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to add tts text data : %d", ret); + } + + bool is_canceled = ecore_thread_check(g_tts_thread); + if (NULL == g_tts_thread || TRUE == is_canceled) { + SLOG(LOG_INFO, TAG_VCD, "[Server INFO] ecore thread run : start_tts_request_thread "); + g_tts_thread = ecore_thread_run(__start_tts_request_thread, __end_tts_request_thread, NULL, NULL); + } + + return 0; +} + +int vcd_server_cancel_tts(int pid, int utt_id) +{ + /* check if pid is valid */ + if (false == vcd_client_is_available(pid)) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid "); + return VCD_ERROR_INVALID_PARAMETER; + } + + vcd_state_e state = vcd_config_get_service_state(); + if (VCD_STATE_READY != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready, state(%d)", state); + return VCD_ERROR_INVALID_STATE; + } + + vc_tts_text_data_s* tts_text_data = NULL; + + int uid = pid * 1000 + utt_id; + int ret = vcd_data_get_tts_text_data(uid, &tts_text_data); + if (0 != ret) { + SLOG(LOG_WARN, TAG_VCD, "[Server WARN] No data in vcd tts text queue"); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[Server] Clear tts text data, pid(%d), utt_id(%d), text(%s)", pid, utt_id, tts_text_data->text); + vcd_data_clear_tts_text_data(&tts_text_data); + } + + /* Request tts to engine */ + ret = vcd_engine_cancel_tts(pid, utt_id); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to cancel tts : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[Server SUCCESS] request tts, pid(%d), utt_id(%d)", pid, utt_id); + } + + return 0; +} + +int vcd_server_get_tts_audio_format(int pid, int* rate, int* channel, int* audio_type) +{ + /* check if pid is valid */ + if (false == vcd_client_is_available(pid)) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid "); + return VCD_ERROR_INVALID_PARAMETER; + } + + vcd_state_e state = vcd_config_get_service_state(); + if (VCD_STATE_READY != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready"); + return VCD_ERROR_INVALID_STATE; + } + + /* Request tts to engine */ + int ret = vcd_engine_get_tts_audio_format(rate, channel, audio_type); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to get tts audio format : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[Server SUCCESS] get tts audio format, pid(%d), rate(%d), channel(%d), audio_type(%d)", pid, *rate, *channel, *audio_type); + } + + return ret; +} + #if 0 int vcd_server_set_exclusive_command(int pid, bool value) { @@ -2909,3 +3094,39 @@ int vcd_set_specific_engine_request_cb(vce_specific_engine_request_cb callback_f return ret; } + +int vcd_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set request tts cb"); + int ret = 0; + ret = vcd_engine_agent_set_request_tts_cb(callback_func, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to set request tts cb : ret(%d)", ret); + } + + return ret; +} + +int vcd_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set cancel tts cb"); + int ret = 0; + ret = vcd_engine_agent_set_cancel_tts_cb(callback_func, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to set cancel tts cb : ret(%d)", ret); + } + + return ret; +} + +int vcd_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set tts audio format request cb"); + int ret = 0; + ret = vcd_engine_agent_set_get_tts_audio_format_cb(callback_func, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to set tts audio format request : ret(%d)", ret); + } + + return ret; +} diff --git a/server/vcd_server.h b/server/vcd_server.h index e11108f..87b735c 100644 --- a/server/vcd_server.h +++ b/server/vcd_server.h @@ -136,6 +136,12 @@ int vcd_server_set_language(const char* language); int vcd_server_mgr_send_specific_engine_request(int pid, const char* engine_app_id, const char* event, const char* request); +int vcd_server_request_tts(int pid, const char* text, const char* language, int to_vcm, int* utt_id); + +int vcd_server_cancel_tts(int pid, int utt_id); + +int vcd_server_get_tts_audio_format(int pid, int* rate, int* channel, int* audio_type); + /* * For engine service */ @@ -175,6 +181,12 @@ int vcd_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_au int vcd_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int len); +int vcd_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data); + +int vcd_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data); + +int vcd_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data); + #ifdef __cplusplus } diff --git a/server/vcd_server_data.cpp b/server/vcd_server_data.cpp new file mode 100644 index 0000000..2b636a9 --- /dev/null +++ b/server/vcd_server_data.cpp @@ -0,0 +1,187 @@ +/* +* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include + +#include "vcd_main.h" +#include "vcd_server_data.h" + +#define DATA_DEBUG + +using namespace std; + +std::list g_tts_text_data; + +static pthread_mutex_t g_tts_text_data_mutex = PTHREAD_MUTEX_INITIALIZER; + + +static int __data_show_text_list(void) +{ + SLOG(LOG_DEBUG, TAG_VCD, "----- Text list -----"); + + if (!g_tts_text_data.empty()) { + std::list::iterator iter; + for (iter = g_tts_text_data.begin(); (NULL != *iter && iter != g_tts_text_data.end()); ++iter) { + SLOG(LOG_DEBUG, TAG_VCD, "[%p] uid(%d), pid(%d), utt_id(%d), text(%s), language(%s)", + *iter, (*iter)->uid, (*iter)->pid, (*iter)->utt_id, (*iter)->text, (*iter)->language); + } + } else { + SLOG(LOG_DEBUG, TAG_VCD, "No Text Data"); + } + + SLOG(LOG_DEBUG, TAG_VCD, "---------------------"); + return VCD_ERROR_NONE; +} + +int vcd_data_add_tts_text_data(int uid, vc_tts_text_data_s* data) +{ + if (NULL == data) { + SLOG(LOG_ERROR, TAG_VCD, "[DATA ERROR] feedback data is NULL"); + return VCD_ERROR_INVALID_PARAMETER; + } + + /* mutex is locked */ + pthread_mutex_lock(&g_tts_text_data_mutex); + + std::list::iterator iter; + + try { + iter = g_tts_text_data.insert(g_tts_text_data.end(), data); + } catch (const std::bad_alloc&) { + SLOG(LOG_ERROR, TAG_VCD, "[DATA][ERROR] Fail to insert tts_text_data (bad_alloc)"); + pthread_mutex_unlock(&g_tts_text_data_mutex); + + return VCD_ERROR_OUT_OF_MEMORY; + } + SLOG(LOG_ERROR, TAG_VCD, "[DATA][%p] uid(%d), pid(%d), utt_id(%d), text(%s), language(%s)", + *iter, (*iter)->uid, (*iter)->pid, (*iter)->utt_id, (*iter)->text, (*iter)->language); + +#ifdef DATA_DEBUG + __data_show_text_list(); +#endif + pthread_mutex_unlock(&g_tts_text_data_mutex); + + return VCD_ERROR_NONE; +} + +int vcd_data_clear_tts_text_data(vc_tts_text_data_s** tts_text_data) +{ + pthread_mutex_lock(&g_tts_text_data_mutex); + + if (!g_tts_text_data.empty()) { + if (NULL != *tts_text_data) { + SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] uid(%d), pid(%d), utt_id(%d), text(%s), language(%s)", + (*tts_text_data)->uid, (*tts_text_data)->pid, (*tts_text_data)->utt_id, (*tts_text_data)->text, (*tts_text_data)->language); + + if (NULL != (*tts_text_data)->text) { + free((*tts_text_data)->text); + (*tts_text_data)->text = NULL; + } + if (NULL != (*tts_text_data)->language) { + free((*tts_text_data)->language); + (*tts_text_data)->language = NULL; + } + + free(*tts_text_data); + *tts_text_data = NULL; + } + } + + pthread_mutex_unlock(&g_tts_text_data_mutex); + + return VCD_ERROR_NONE; +} + +int vcd_data_get_tts_text_data(int uid, vc_tts_text_data_s** data) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[DATA] Get tts text data : uid(%d)", uid); + + /* mutex is locked */ + pthread_mutex_lock(&g_tts_text_data_mutex); + + if (0 == g_tts_text_data.size()) { + SLOG(LOG_ERROR, TAG_VCD, "[DATA ERROR] There is no tts_text data"); + *data = NULL; + pthread_mutex_unlock(&g_tts_text_data_mutex); + return -1; + } + + std::list::iterator iter; + for (iter = g_tts_text_data.begin(); (NULL != *iter && iter != g_tts_text_data.end()); ++iter) { + if (uid == (*iter)->uid) { + *data = *iter; + g_tts_text_data.erase(iter); + } + } + +#ifdef DATA_DEBUG + __data_show_text_list(); +#endif + + pthread_mutex_unlock(&g_tts_text_data_mutex); + + return VCD_ERROR_NONE; +} + +int vcd_data_get_first_tts_text_data(vc_tts_text_data_s** data) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[DATA] Get first tts text data"); + +#ifdef DATA_DEBUG + __data_show_text_list(); +#endif + + /* mutex is locked */ + pthread_mutex_lock(&g_tts_text_data_mutex); + + if (0 == g_tts_text_data.size()) { + SLOG(LOG_ERROR, TAG_VCD, "[DATA ERROR] There is no tts_text data"); + *data = NULL; + pthread_mutex_unlock(&g_tts_text_data_mutex); + return -1; + } + + std::list::iterator iter; + + if (!g_tts_text_data.empty()) { + iter = g_tts_text_data.begin(); + *data = *iter; + g_tts_text_data.pop_front(); + } + + pthread_mutex_unlock(&g_tts_text_data_mutex); + + return VCD_ERROR_NONE; +} + +int vcd_data_get_tts_text_data_size(void) +{ + /* mutex is locked */ + pthread_mutex_lock(&g_tts_text_data_mutex); + int size = g_tts_text_data.size(); + + SLOG(LOG_DEBUG, TAG_VCD, "[DATA] get feedback data size(%d)", size); + + /* mutex is unlocked */ + pthread_mutex_unlock(&g_tts_text_data_mutex); + + return size; +} diff --git a/server/vcd_server_data.h b/server/vcd_server_data.h new file mode 100644 index 0000000..af2f055 --- /dev/null +++ b/server/vcd_server_data.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VCD_SERVER_DATA_H__ +#define __VCD_SERVER_DATA_H__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG_VCD "vcd" /* VC Daemon log tag */ + + +typedef struct { + int uid; + int pid; + int utt_id; + char* text; + char* language; +} vc_tts_text_data_s; + + +int vcd_data_add_tts_text_data(int uid, vc_tts_text_data_s* data); + +int vcd_data_clear_tts_text_data(vc_tts_text_data_s** tts_text_data); + +int vcd_data_get_tts_text_data(int uid, vc_tts_text_data_s** data); + +int vcd_data_get_first_tts_text_data(vc_tts_text_data_s** data); + +int vcd_data_get_tts_text_data_size(); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VCD_SERVER_DATA_H__ */ diff --git a/server/vce.c b/server/vce.c index 56ef2b2..cfc93a8 100644 --- a/server/vce.c +++ b/server/vce.c @@ -532,7 +532,7 @@ int vce_unset_specific_engine_request_cb(void) int ret = vcd_set_specific_engine_request_cb(NULL); if (0 != ret) { - SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set specific engine request cb"); + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset specific engine request cb"); } return ret; @@ -585,3 +585,78 @@ int vce_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int le return ret; } + +int vce_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data) +{ + if (NULL == callback_func) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Invalid parameter"); + return VCE_ERROR_INVALID_PARAMETER; + } + + int ret = vcd_set_request_tts_cb(callback_func, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set request tts cb"); + } + + return ret; +} + +int vce_unset_request_tts_cb(void) +{ + int ret = vcd_set_request_tts_cb(NULL, NULL); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset request tts cb"); + } + + return ret; +} + +int vce_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data) +{ + if (NULL == callback_func) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Invalid parameter"); + return VCE_ERROR_INVALID_PARAMETER; + } + + int ret = vcd_set_cancel_tts_cb(callback_func, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set cancel tts cb"); + } + + return ret; +} + +int vce_unset_cancel_tts_cb(void) +{ + int ret = vcd_set_cancel_tts_cb(NULL, NULL); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset cancel tts cb"); + } + + return ret; +} + +int vce_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data) +{ + if (NULL == callback_func) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Invalid parameter"); + return VCE_ERROR_INVALID_PARAMETER; + } + + int ret = vcd_set_tts_audio_format_request_cb(callback_func, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set get tts audio format cb"); + } + + return ret; +} + +int vce_unset_get_tts_audio_format_cb(void) +{ + int ret = vcd_set_tts_audio_format_request_cb(NULL, NULL); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset request tts cb"); + } + + return ret; +} -- 2.7.4 From f18071058a259bc26a475a6e8648ab44f0e64310 Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Thu, 20 Sep 2018 15:40:39 +0900 Subject: [PATCH 09/16] Fix coverity issue (pointer deference) Change-Id: I545ff21f6efa01fc1a905f57f6ea0009068062da Signed-off-by: sooyeon.kim --- client/vc_mgr.c | 79 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index 17bbbb8..8493fb9 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -4068,50 +4068,53 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread) continue; } - if (getpid() == feedback_data->pid) { - vc_mgr_feedback_streaming_cb callback = NULL; - void* user_data = NULL; - - vc_mgr_client_get_feedback_streaming_cb(g_vc_m, &callback, &user_data); - if (NULL == callback) { - SLOG(LOG_WARN, TAG_VCM, "[WARNING] TTS feedback streaming callback is null"); - return; - } + if (NULL != feedback_data) { + if (getpid() == feedback_data->pid) { + vc_mgr_feedback_streaming_cb callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_feedback_streaming_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] TTS feedback streaming callback is null"); + vc_mgr_data_clear_feedback_data(&feedback_data); + return; + } - SLOG(LOG_DEBUG, TAG_VCM, "TTS feedback streaming callback is called"); - vc_mgr_client_use_callback(g_vc_m); - callback(feedback_data->event, feedback_data->data, feedback_data->data_size, user_data); - vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "TTS feedback streaming callback is called"); + vc_mgr_client_use_callback(g_vc_m); + callback(feedback_data->event, feedback_data->data, feedback_data->data_size, user_data); + vc_mgr_client_not_use_callback(g_vc_m); - /* If no feedback data and EVENT_FINISH */ - if (0 >= vc_mgr_data_get_feedback_data_size() && VC_FEEDBACK_EVENT_FINISH == feedback_data->event) { - SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish feedback"); - break; - } - } else { - vc_mgr_vc_tts_streaming_cb callback = NULL; - void* user_data = NULL; - - vc_mgr_client_get_vc_tts_streaming_cb(g_vc_m, &callback, &user_data); - if (NULL == callback) { - SLOG(LOG_WARN, TAG_VCM, "[WARNING] vc tts streaming callback is null"); - vc_mgr_data_clear_feedback_data(&feedback_data); - return; - } + /* If no feedback data and EVENT_FINISH */ + if (0 >= vc_mgr_data_get_feedback_data_size() && VC_FEEDBACK_EVENT_FINISH == feedback_data->event) { + SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish feedback"); + break; + } + } else { + vc_mgr_vc_tts_streaming_cb callback = NULL; + void* user_data = NULL; - SLOG(LOG_DEBUG, TAG_VCM, "vc tts feedback streaming callback is called"); - vc_mgr_client_use_callback(g_vc_m); - callback(feedback_data->pid, feedback_data->utt_id, feedback_data->event, feedback_data->data, feedback_data->data_size, user_data); - vc_mgr_client_not_use_callback(g_vc_m); + vc_mgr_client_get_vc_tts_streaming_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] vc tts streaming callback is null"); + vc_mgr_data_clear_feedback_data(&feedback_data); + return; + } - /* If no feedback data and EVENT_FINISH */ - if (0 >= vc_mgr_data_get_feedback_data_size() && VC_FEEDBACK_EVENT_FINISH == feedback_data->event) { - SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish vc tts feedback"); - break; + SLOG(LOG_DEBUG, TAG_VCM, "vc tts feedback streaming callback is called"); + vc_mgr_client_use_callback(g_vc_m); + callback(feedback_data->pid, feedback_data->utt_id, feedback_data->event, feedback_data->data, feedback_data->data_size, user_data); + vc_mgr_client_not_use_callback(g_vc_m); + + /* If no feedback data and EVENT_FINISH */ + if (0 >= vc_mgr_data_get_feedback_data_size() && VC_FEEDBACK_EVENT_FINISH == feedback_data->event) { + SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish vc tts feedback"); + break; + } } - } - if (feedback_data) free(feedback_data); + feedback_data = NULL; + } } } -- 2.7.4 From d260b04b09f192c34570644311ba1efb26e1a734 Mon Sep 17 00:00:00 2001 From: yhji Date: Thu, 27 Sep 2018 16:47:07 +0900 Subject: [PATCH 10/16] Fix Wformat build warning Change-Id: Ib936e1857b9d1bda728d30c4e49fb8a5bc235b25 Signed-off-by: yhji --- client/vc_mgr_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/vc_mgr_data.cpp b/client/vc_mgr_data.cpp index 7053c46..866d3da 100644 --- a/client/vc_mgr_data.cpp +++ b/client/vc_mgr_data.cpp @@ -35,7 +35,7 @@ int vc_mgr_data_add_feedback_data(vc_feedback_data_s* data) SLOG(LOG_ERROR, TAG_VCM, "[DATA ERROR] feedback data is NULL"); return VC_ERROR_INVALID_PARAMETER; } - SLOG(LOG_DEBUG, TAG_VCM, "[DATA] feedback_data : %p", *data); + SLOG(LOG_DEBUG, TAG_VCM, "[DATA] feedback_data : %p", data); pthread_mutex_lock(&g_feedback_data_mutex); -- 2.7.4 From ffd0494e481ecfc89e0d71260db9e22a7bb0fc79 Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Wed, 19 Sep 2018 16:06:51 +0900 Subject: [PATCH 11/16] Support Multi-Assistant Change-Id: I062eadc3b60af5051a3460a5d6d9388796da3e48 Signed-off-by: sooyeon.kim --- client/vc_mgr.c | 104 +++++++++++++++++++++++++- client/vc_mgr_client.c | 31 ++++++++ client/vc_mgr_client.h | 13 +++- client/vc_mgr_dbus.c | 44 ++++++++++- client/vc_mgr_dbus.h | 5 +- common/vc_defs.h | 2 + include/voice_control_manager_internal.h | 21 ++++++ server/vcd_config.c | 14 ++++ server/vcd_config.h | 5 ++ server/vcd_dbus.c | 3 + server/vcd_dbus_server.c | 39 +++++++++- server/vcd_dbus_server.h | 3 + server/vcd_main.h | 13 ++++ server/vcd_recorder.c | 121 ++++++++++++++++++++++++++++++- server/vcd_recorder.h | 6 ++ server/vcd_server.c | 30 ++++++++ server/vcd_server.h | 3 + 17 files changed, 447 insertions(+), 10 deletions(-) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index 17bbbb8..fee9d82 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -213,7 +213,6 @@ static int __vc_mgr_check_privilege() __check_privilege_deinitialize(); } - g_privilege_allowed = 1; return VC_ERROR_NONE; } @@ -270,6 +269,14 @@ int vc_mgr_initialize(void) return ret; } + ret = vc_mgr_client_set_audio_streaming_mode(g_vc_m, VC_AUDIO_STREAMING_MODE_VC_SERVICE); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set audio streaming mode : %d", ret); + vc_config_mgr_finalize(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_mgr_client_destroy(g_vc_m); + return ret; + } + /* for TTS feedback */ /* ret = vc_mgr_player_init(); if (0 != ret) { @@ -377,7 +384,10 @@ static Eina_Bool __vc_mgr_connect_daemon(void *data) g_m_connect_timer = NULL; - ret = vc_mgr_dbus_request_initialize(g_vc_m->handle, &service_state, &foreground, &g_daemon_pid); + vc_audio_streaming_mode_e streaming_mode; + vc_mgr_client_get_audio_streaming_mode(g_vc_m, &streaming_mode); + + ret = vc_mgr_dbus_request_initialize(g_vc_m->handle, (int)streaming_mode, &service_state, &foreground, &g_daemon_pid); if (VC_ERROR_ENGINE_NOT_FOUND == ret) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to initialize : %s", __vc_mgr_get_error_code(ret)); @@ -4255,3 +4265,93 @@ int vc_mgr_send_utterance_status(int pid, int utt_id, int utt_status) return 0; } +int vc_mgr_send_audio_streaming(vc_audio_streaming_event_e event, unsigned char* buffer, unsigned int len) +{ + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Send audio streaming to the engine service"); + + if (NULL == buffer) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid parameter"); + return VC_ERROR_INVALID_PARAMETER; + } + + if (0 != __vc_mgr_get_feature_enabled()) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] not supported"); + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (VC_SERVICE_STATE_READY != service_state && VC_SERVICE_STATE_RECORDING != service_state) { + + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'READY' and 'RECORDING', state(%d)", service_state); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* send audio streaming */ + int ret = vc_mgr_dbus_send_audio_streaming(g_vc_m->handle, event, buffer, len); + if (0 != ret) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry to send audio streaming data"); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] Success to send"); + } + + return ret; +} + +int vc_mgr_set_audio_streaming_mode(vc_audio_streaming_mode_e streaming_mode) +{ + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Set multi assistant mode"); + + if (0 != __vc_mgr_get_feature_enabled()) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] not supported"); + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'INITIALIZED', state(%d)", state); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + int ret = vc_mgr_client_set_audio_streaming_mode(g_vc_m, streaming_mode); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set multi assistant mode, ret(%d)", ret); + return VC_ERROR_INVALID_STATE; + } + + return ret; +} diff --git a/client/vc_mgr_client.c b/client/vc_mgr_client.c index 9f5124d..2317c43 100644 --- a/client/vc_mgr_client.c +++ b/client/vc_mgr_client.c @@ -102,6 +102,9 @@ typedef struct { /* foreground pid */ int foreground_pid; + + /* multi-assistant */ + vc_audio_streaming_mode_e streaming_mode; } vc_mgr_client_s; typedef struct { @@ -227,6 +230,8 @@ int vc_mgr_client_create(vc_h* vc) client->foreground_pid = VC_RUNTIME_INFO_NO_FOREGROUND; + client->streaming_mode = VC_AUDIO_STREAMING_MODE_VC_SERVICE; + g_mgr_client_list = g_slist_append(g_mgr_client_list, client); *vc = temp; @@ -1322,3 +1327,29 @@ int vc_mgr_client_get_specific_engine_result_cb(vc_h vc, vc_mgr_specific_engine_ return 0; } + +int vc_mgr_client_set_audio_streaming_mode(vc_h vc, vc_audio_streaming_mode_e streaming_mode) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->streaming_mode = streaming_mode; + + return 0; +} + +int vc_mgr_client_get_audio_streaming_mode(vc_h vc, vc_audio_streaming_mode_e* streaming_mode) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *streaming_mode = client->streaming_mode; + + return 0; +} diff --git a/client/vc_mgr_client.h b/client/vc_mgr_client.h index 9128f95..3ee6512 100644 --- a/client/vc_mgr_client.h +++ b/client/vc_mgr_client.h @@ -21,6 +21,7 @@ #include "vc_info_parser.h" #include "voice_control_manager.h" +#include "voice_control_manager_internal.h" #ifdef __cplusplus extern "C" { @@ -111,7 +112,6 @@ int vc_mgr_client_set_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb ca int vc_mgr_client_get_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb* callback, void** user_data); - /* * set/get option */ @@ -161,6 +161,11 @@ int vc_mgr_client_set_foreground(vc_h vc, int pid, bool value); int vc_mgr_client_get_foreground(vc_h vc, int* pid); +int vc_mgr_client_set_multi_assistant(vc_h vc, bool use_multi_assistant); + +int vc_mgr_client_get_multi_assistant(vc_h vc, bool* use_multi_assistant); + + /* utils */ int vc_mgr_client_get_count(); @@ -185,6 +190,12 @@ int vc_mgr_client_set_start_by_client(vc_h vc, bool option); int vc_mgr_client_get_start_by_client(vc_h vc, bool* option); +/* multi assistant */ +int vc_mgr_client_set_audio_streaming_mode(vc_h vc, vc_audio_streaming_mode_e streaming_mode); + +int vc_mgr_client_get_audio_streaming_mode(vc_h vc, vc_audio_streaming_mode_e* streaming_mode); + + #ifdef __cplusplus } #endif diff --git a/client/vc_mgr_dbus.c b/client/vc_mgr_dbus.c index 8f8adf6..f889e43 100644 --- a/client/vc_mgr_dbus.c +++ b/client/vc_mgr_dbus.c @@ -891,7 +891,7 @@ static int __dbus_restore_daemon() return ret; } -int vc_mgr_dbus_request_initialize(int pid, int* service_state, int* foreground, int* daemon_pid) +int vc_mgr_dbus_request_initialize(int pid, int audio_streaming_mode, int* service_state, int* foreground, int* daemon_pid) { DBusError err; dbus_error_init(&err); @@ -929,6 +929,7 @@ int vc_mgr_dbus_request_initialize(int pid, int* service_state, int* foreground, dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &audio_streaming_mode, DBUS_TYPE_INVALID); DBusMessage* result_msg; @@ -2301,8 +2302,6 @@ int vc_mgr_dbus_send_specific_engine_request(int pid, const char* engine_app_id, int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status) { DBusMessage* msg; - - /* create a signal & check for errors */ msg = __get_message(pid, VC_MANAGER_METHOD_UTTERANCE_STATUS, VC_COMMAND_TYPE_FOREGROUND); if (NULL == msg) { @@ -2329,3 +2328,42 @@ int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status) return 0; } + +int vc_mgr_dbus_send_audio_streaming(int pid, vc_audio_streaming_event_e event, unsigned char* buffer, unsigned int len) +{ + DBusMessage* msg; + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_SEND_AUDIO_STREAMING); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, "@@ vc send audio streaming : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "@@ vc send audio streaming : pid(%d), event(%d), buffer(%p), len(%d)", pid, event, buffer, len); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &event, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buffer, len, + DBUS_TYPE_INVALID); + + dbus_message_set_no_reply(msg, TRUE); + + /* send dbus message and flush the connection */ + if (!dbus_connection_send(g_m_conn_sender, msg, NULL)) { + SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Fail to send audio streaming"); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Dbus DEBUG] Success to send audio streaming"); + dbus_connection_flush(g_m_conn_sender); + } + + dbus_message_unref(msg); + + return 0; +} + diff --git a/client/vc_mgr_dbus.h b/client/vc_mgr_dbus.h index b0b5c2f..9ce1239 100644 --- a/client/vc_mgr_dbus.h +++ b/client/vc_mgr_dbus.h @@ -18,6 +18,8 @@ #ifndef __VC_DBUS_H_ #define __VC_DBUS_H_ +#include "voice_control_manager_internal.h" + #ifdef __cplusplus extern "C" { @@ -30,7 +32,7 @@ int vc_mgr_dbus_close_connection(); int vc_mgr_dbus_request_hello(); -int vc_mgr_dbus_request_initialize(int pid, int* service_state, int* foreground, int* daemon_pid); +int vc_mgr_dbus_request_initialize(int pid, int audio_streaming_mode, int* service_state, int* foreground, int* daemon_pid); int vc_mgr_dbus_request_finalize(int pid); @@ -76,6 +78,7 @@ int vc_mgr_dbus_request_stop_feedback(int pid); int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status); +int vc_mgr_dbus_send_audio_streaming(int pid, vc_audio_streaming_event_e event, unsigned char* buffer, unsigned int len); #ifdef __cplusplus } diff --git a/common/vc_defs.h b/common/vc_defs.h index 0458c37..55fc210 100644 --- a/common/vc_defs.h +++ b/common/vc_defs.h @@ -151,6 +151,8 @@ extern "C" { #define VC_MANAGER_METHOD_STOP_FEEDBACK "vc_manager_method_request_stop_feedback" #define VC_MANAGER_METHOD_UTTERANCE_STATUS "vc_manager_method_utterance_status" +#define VC_MANAGER_METHOD_SEND_AUDIO_STREAMING "vc_manager_method_send_audio_streaming" + #define VCD_MANAGER_METHOD_HELLO "vcd_manager_method_hello" #define VCD_MANAGER_METHOD_SPEECH_DETECTED "vcd_manager_method_speech_detected" #define VCD_MANAGER_METHOD_ALL_RESULT "vcd_manager_method_all_result" diff --git a/include/voice_control_manager_internal.h b/include/voice_control_manager_internal.h index c06d38b..4b58230 100644 --- a/include/voice_control_manager_internal.h +++ b/include/voice_control_manager_internal.h @@ -27,6 +27,18 @@ extern "C" { #endif +typedef enum { + VC_AUDIO_STREAMING_EVENT_FAIL = -1, /**< Failed */ + VC_AUDIO_STREAMING_EVENT_START = 1, /**< Start event */ + VC_AUDIO_STREAMING_EVENT_CONTINUE = 2, /**< Continue event */ + VC_AUDIO_STREAMING_EVENT_FINISH = 3 /**< Finish event */ +} vc_audio_streaming_event_e; + +typedef enum { + VC_AUDIO_STREAMING_MODE_VC_SERVICE = 0, /**< Use audio recording from vc service */ + VC_AUDIO_STREAMING_MODE_MULTI_ASSISTANT = 1, /**< Use audio streaming from multi-assistant */ + VC_AUDIO_STREAMING_MODE_OUTSIDE = 2, /**< Use audio streaming from outside */ +} vc_audio_streaming_mode_e; /** * @brief Sets demandable client list. @@ -79,6 +91,15 @@ int vc_mgr_unset_demandable_client_rule(void); */ int vc_mgr_set_domain(const char* domain); +/** + * @brief Sends audio streaming to the engine service. + * @since_tizen 5.0 + * + */ +int vc_mgr_send_audio_streaming(vc_audio_streaming_event_e event, unsigned char* buffer, unsigned int len); + +int vc_mgr_set_audio_streaming_mode(vc_audio_streaming_mode_e streaming_mode); + #ifdef __cplusplus } diff --git a/server/vcd_config.c b/server/vcd_config.c index 8d707b7..629487e 100755 --- a/server/vcd_config.c +++ b/server/vcd_config.c @@ -28,6 +28,8 @@ static vcd_state_e g_state; static int g_foreground_pid; +static int g_audio_streaming_mode; + #define COMMAND_TYPE_MAX 7 static int g_enabled_command_type[COMMAND_TYPE_MAX] = { 0, /* NONE */ @@ -185,3 +187,15 @@ int vcd_config_get_command_type_enabled(int cmd_type) return g_enabled_command_type[cmd_type]; } + +int vcd_config_get_audio_streaming_mode(vcd_audio_streaming_mode_e* streaming_mode) +{ + *streaming_mode = g_audio_streaming_mode; + return 0; +} + +int vcd_config_set_audio_streaming_mode(vcd_audio_streaming_mode_e streaming_mode) +{ + g_audio_streaming_mode = streaming_mode; + return 0; +} diff --git a/server/vcd_config.h b/server/vcd_config.h index de6589d..68db934 100755 --- a/server/vcd_config.h +++ b/server/vcd_config.h @@ -51,6 +51,11 @@ int vcd_config_disable_command_type(int cmd_type); int vcd_config_get_command_type_enabled(int cmd_type); +int vcd_config_get_audio_streaming_mode(vcd_audio_streaming_mode_e* streaming_mode); + +int vcd_config_set_audio_streaming_mode(vcd_audio_streaming_mode_e streaming_mode); + + #ifdef __cplusplus } #endif diff --git a/server/vcd_dbus.c b/server/vcd_dbus.c index 69e1f52..1718191 100644 --- a/server/vcd_dbus.c +++ b/server/vcd_dbus.c @@ -1150,6 +1150,9 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_MANAGER_METHOD_STOP_FEEDBACK)) vcd_dbus_server_mgr_stop_feedback(g_conn_listener, msg); + else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_MANAGER_METHOD_SEND_AUDIO_STREAMING)) + vcd_dbus_server_mgr_send_audio_streaming(g_conn_listener, msg); + /* client event */ else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_INITIALIZE)) vcd_dbus_server_initialize(g_conn_listener, msg); diff --git a/server/vcd_dbus_server.c b/server/vcd_dbus_server.c index 68b0ae1..9740609 100644 --- a/server/vcd_dbus_server.c +++ b/server/vcd_dbus_server.c @@ -20,7 +20,7 @@ #include "vcd_dbus_server.h" #include "vcd_main.h" #include "vcd_server.h" - +#include "vcd_config.h" int __dbus_error_return(DBusConnection* conn, DBusMessage* msg, int ret) { @@ -86,6 +86,7 @@ int vcd_dbus_server_mgr_initialize(DBusConnection* conn, DBusMessage* msg) dbus_error_init(&err); int pid; + int streaming_mode; int service_state; int foreground; int daemon_pid; @@ -93,6 +94,7 @@ int vcd_dbus_server_mgr_initialize(DBusConnection* conn, DBusMessage* msg) dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &streaming_mode, DBUS_TYPE_INVALID); SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD Manager Initialize"); @@ -102,6 +104,7 @@ int vcd_dbus_server_mgr_initialize(DBusConnection* conn, DBusMessage* msg) dbus_error_free(&err); ret = VCD_ERROR_OPERATION_FAILED; } else { + vcd_config_set_audio_streaming_mode((vcd_audio_streaming_mode_e)streaming_mode); ret = vcd_server_mgr_initialize(pid); service_state = vcd_server_get_service_state(); foreground = vcd_server_get_foreground(); @@ -1188,6 +1191,39 @@ int vcd_dbus_server_mgr_stop_feedback(DBusConnection* conn, DBusMessage* msg) return 0; } +int vcd_dbus_server_mgr_send_audio_streaming(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid = 0; + int event = 0; + unsigned char* buffer = NULL; + unsigned int len = 0; + + int ret = VCD_ERROR_OPERATION_FAILED; + + SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD Manager send audio streaming"); + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &event, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buffer, &len, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd mgr send audio streaming : get arguments error (%s)", err.message); + dbus_error_free(&err); + ret = VCD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd mgr send audio streaming : pid(%d), event(%d), buffer(%p), len(%d)", pid, event, buffer, len); + ret = vcd_server_mgr_send_audio_streaming(pid, event, buffer, len); + } + + return ret; +} + /* * Dbus Server functions for client @@ -2206,6 +2242,7 @@ int vcd_dbus_server_set_language(DBusConnection* conn, DBusMessage* msg) return 0; } + int vcd_dbus_server_request_tts(DBusConnection* conn, DBusMessage* msg) { DBusError err; diff --git a/server/vcd_dbus_server.h b/server/vcd_dbus_server.h index bef7205..ac02296 100644 --- a/server/vcd_dbus_server.h +++ b/server/vcd_dbus_server.h @@ -74,6 +74,9 @@ int vcd_dbus_server_mgr_start_feedback(DBusConnection* conn, DBusMessage* msg); int vcd_dbus_server_mgr_stop_feedback(DBusConnection* conn, DBusMessage* msg); +/* for Multi-assistant */ +int vcd_dbus_server_mgr_send_audio_streaming(DBusConnection* conn, DBusMessage* msg); + /* * Dbus Server functions for client diff --git a/server/vcd_main.h b/server/vcd_main.h index 3d8525b..46b9fd8 100644 --- a/server/vcd_main.h +++ b/server/vcd_main.h @@ -74,6 +74,19 @@ typedef enum { VCD_STATE_PROCESSING = 3 } vcd_state_e; +typedef enum { + VCD_AUDIO_STREAMING_EVENT_FAIL = -1, /**< Failed */ + VCD_AUDIO_STREAMING_EVENT_START = 1, /**< Start event */ + VCD_AUDIO_STREAMING_EVENT_CONTINUE = 2, /**< Continue event */ + VCD_AUDIO_STREAMING_EVENT_FINISH = 3 /**< Finish event */ +} vcd_audio_streaming_event_e; + +typedef enum { + VCD_AUDIO_STREAMING_MODE_VC_SERVICE = 0, /**< Use audio recording from vc service */ + VCD_AUDIO_STREAMING_MODE_MULTI_ASSISTANT = 1, /**< Use audio streaming from multi-assistant */ + VCD_AUDIO_STREAMING_MODE_OUTSIDE = 2, /**< Use audio streaming from outside */ +} vcd_audio_streaming_mode_e; + struct vce_cmd_s { int index; }; diff --git a/server/vcd_recorder.c b/server/vcd_recorder.c index ca49fb9..6ffb708 100644 --- a/server/vcd_recorder.c +++ b/server/vcd_recorder.c @@ -75,9 +75,9 @@ static int g_buffer_count; static int g_device_id = -1; /* Sound buf save */ -/* +#if 0 #define BUF_SAVE_MODE - */ +#endif #ifdef BUF_SAVE_MODE static FILE* g_normal_file; @@ -507,6 +507,13 @@ int vcd_recorder_destroy() int vcd_recorder_set(const char* audio_type, vce_audio_type_e type, int rate, int channel) { + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_MULTI_ASSISTANT == streaming_mode || VCD_AUDIO_STREAMING_MODE_OUTSIDE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + if (NULL == audio_type) { return VCD_ERROR_INVALID_PARAMETER; } @@ -627,6 +634,13 @@ int vcd_recorder_set(const char* audio_type, vce_audio_type_e type, int rate, in int vcd_recorder_get(char** audio_type) { + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_MULTI_ASSISTANT == streaming_mode || VCD_AUDIO_STREAMING_MODE_OUTSIDE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + if (NULL == audio_type) { return VCD_ERROR_INVALID_PARAMETER; } @@ -793,11 +807,107 @@ static void __check_audio_format() } } +int vcd_recorder_start_streaming() +{ + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] start streaming"); + + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_VC_SERVICE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + +#ifdef BUF_SAVE_MODE + char normal_file_name[128] = {'\0',}; + g_count++; + + while (1) { + snprintf(normal_file_name, sizeof(normal_file_name), "/tmp/vc_streaming_%d_%d", getpid(), g_count); + int ret = access(normal_file_name, 0); + + if (0 == ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File is already exist"); + if (0 == remove(normal_file_name)) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Remove file"); + break; + } else { + g_count++; + } + } else { + break; + } + } + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] File normal name : %s", normal_file_name); + + /* open test file */ + g_normal_file = fopen(normal_file_name, "wb+x"); + if (!g_normal_file) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File not found!"); + } +#endif + + return 0; +} + +int vcd_recorder_send_streaming(const void* buffer, const unsigned int length) +{ + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_VC_SERVICE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + + if (NULL != g_audio_cb) { + int ret = g_audio_cb(buffer, length); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start streaming : %d", ret); + vcd_recorder_stop(); + return ret; + } + } + +#ifdef BUF_SAVE_MODE + /* write pcm buffer */ + if (g_normal_file) + fwrite(buffer, 1, length, g_normal_file); +#endif + + return 0; +} + +int vcd_recorder_stop_streaming() +{ + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] stop streaming"); + + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_VC_SERVICE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + +#ifdef BUF_SAVE_MODE + if (g_normal_file) + fclose(g_normal_file); +#endif + + return 0; +} int vcd_recorder_start() { int ret = -1; + + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_MULTI_ASSISTANT == streaming_mode || VCD_AUDIO_STREAMING_MODE_OUTSIDE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + g_buffer_count = 0; SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Enter, recorder state(%d)", g_recorder_state); @@ -919,6 +1029,13 @@ int vcd_recorder_stop() { int ret = -1; + vcd_audio_streaming_mode_e streaming_mode; + vcd_config_get_audio_streaming_mode(&streaming_mode); + if (VCD_AUDIO_STREAMING_MODE_MULTI_ASSISTANT == streaming_mode || VCD_AUDIO_STREAMING_MODE_OUTSIDE == streaming_mode) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode); + return VCD_ERROR_NONE; + } + if (VCD_RECORDER_STATE_READY == g_recorder_state) return 0; diff --git a/server/vcd_recorder.h b/server/vcd_recorder.h index a061d2a..7a612b8 100644 --- a/server/vcd_recorder.h +++ b/server/vcd_recorder.h @@ -43,6 +43,12 @@ int vcd_recorder_set(const char* audio_type, vce_audio_type_e type, int rate, in int vcd_recorder_get(char** audio_type); +int vcd_recorder_start_streaming(); + +int vcd_recorder_send_streaming(const void* buffer, const unsigned int length); + +int vcd_recorder_stop_streaming(); + int vcd_recorder_start(); int vcd_recorder_read(); diff --git a/server/vcd_server.c b/server/vcd_server.c index d79b946..8de4a88 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -2226,6 +2226,36 @@ int vcd_server_mgr_stop_feedback(void) return VCD_ERROR_NONE; } +int vcd_server_mgr_send_audio_streaming(int pid, int event, unsigned char* buffer, unsigned int len) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] Send Audio Streaming from Multi-assistant. event(%d), buffer(%p), len(%d)", event, &buffer, len); + + int ret = 0; + if (VCD_AUDIO_STREAMING_EVENT_START == event) { + ret = vcd_recorder_start_streaming(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to start streaming, ret(%d)", ret); + return ret; + } + } + + ret = vcd_recorder_send_streaming((const void*)buffer, (const unsigned int)len); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to start streaming, ret(%d)", ret); + return ret; + } + + if (VCD_AUDIO_STREAMING_EVENT_FINISH == event) { + ret = vcd_recorder_stop_streaming(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to stop streaming, ret(%d)", ret); + return ret; + } + } + + return VCD_ERROR_NONE; +} + /* * VC Server Functions for Client diff --git a/server/vcd_server.h b/server/vcd_server.h index 87b735c..d6270f1 100644 --- a/server/vcd_server.h +++ b/server/vcd_server.h @@ -85,6 +85,9 @@ int vcd_server_mgr_start_feedback(void); int vcd_server_mgr_stop_feedback(void); +/* for Multi-assistant */ +int vcd_server_mgr_send_audio_streaming(int pid, int event, unsigned char* buffer, unsigned int len); + /* * For client -- 2.7.4 From a7a674f08246f9f367e06a166168f9d79b659945 Mon Sep 17 00:00:00 2001 From: Wonnam Jang Date: Fri, 28 Sep 2018 16:02:12 +0900 Subject: [PATCH 12/16] Check if connection is NULL or not Change-Id: Ib6758c097f17969a12721915e459c2168717b24e Signed-off-by: Wonnam Jang --- client/vc_dbus.c | 2 +- client/vc_mgr_dbus.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ client/vc_widget_dbus.c | 2 +- 3 files changed, 103 insertions(+), 2 deletions(-) diff --git a/client/vc_dbus.c b/client/vc_dbus.c index 2da8f6b..ebdce04 100644 --- a/client/vc_dbus.c +++ b/client/vc_dbus.c @@ -409,7 +409,7 @@ int vc_dbus_reconnect() static int __dbus_check() { - if (NULL == g_conn_sender) { + if (NULL == g_conn_sender || NULL == g_conn_listener) { SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection"); //LCOV_EXCL_LINE return vc_dbus_reconnect(); } diff --git a/client/vc_mgr_dbus.c b/client/vc_mgr_dbus.c index f889e43..7545a7f 100644 --- a/client/vc_mgr_dbus.c +++ b/client/vc_mgr_dbus.c @@ -825,8 +825,21 @@ int vc_mgr_dbus_reconnect() return 0; } +static int __dbus_check() +{ + if (NULL == g_m_conn_sender || NULL == g_m_conn_listener) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] NULL connection"); //LCOV_EXCL_LINE + return vc_mgr_dbus_reconnect(); + } + return 0; +} + int vc_mgr_dbus_request_hello() { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; msg = dbus_message_new_method_call( @@ -893,6 +906,10 @@ static int __dbus_restore_daemon() int vc_mgr_dbus_request_initialize(int pid, int audio_streaming_mode, int* service_state, int* foreground, int* daemon_pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -993,6 +1010,10 @@ int vc_mgr_dbus_request_initialize(int pid, int audio_streaming_mode, int* servi int vc_mgr_dbus_request_finalize(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1081,6 +1102,10 @@ int vc_mgr_dbus_request_finalize(int pid) int vc_mgr_dbus_request_set_command(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1158,6 +1183,10 @@ int vc_mgr_dbus_request_set_command(int pid) int vc_mgr_dbus_request_unset_command(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1235,6 +1264,10 @@ int vc_mgr_dbus_request_unset_command(int pid) int vc_mgr_dbus_request_demandable_client(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1312,6 +1345,10 @@ int vc_mgr_dbus_request_demandable_client(int pid) int vc_mgr_dbus_request_set_audio_type(int pid, const char* audio_type) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1391,6 +1428,10 @@ int vc_mgr_dbus_request_set_audio_type(int pid, const char* audio_type) int vc_mgr_dbus_request_get_audio_type(int pid, char** audio_type) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1475,6 +1516,10 @@ int vc_mgr_dbus_request_get_audio_type(int pid, char** audio_type) int vc_mgr_dbus_request_set_private_data(int pid, const char* key, const char* data) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; /* create a signal & check for errors */ @@ -1516,6 +1561,10 @@ int vc_mgr_dbus_request_set_private_data(int pid, const char* key, const char* d int vc_mgr_dbus_request_get_private_data(int pid, const char* key, char** data) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; /* create a signal & check for errors */ @@ -1586,6 +1635,10 @@ int vc_mgr_dbus_request_get_private_data(int pid, const char* key, char** data) int vc_mgr_dbus_request_set_client_info(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1664,6 +1717,10 @@ int vc_mgr_dbus_request_set_client_info(int pid) int vc_mgr_dbus_request_set_domain(int pid, const char* domain) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; /* create a signal & check for errors */ @@ -1727,6 +1784,10 @@ int vc_mgr_dbus_request_set_domain(int pid, const char* domain) int vc_mgr_dbus_request_do_action(int pid, vc_send_event_type_e type, char* send_event) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; /* create a signal & check for errors */ @@ -1764,6 +1825,10 @@ int vc_mgr_dbus_request_do_action(int pid, vc_send_event_type_e type, char* send int vc_mgr_dbus_request_start(int pid, int recognition_mode, bool exclusive_command_option, bool start_by_client) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1849,6 +1914,10 @@ int vc_mgr_dbus_request_start(int pid, int recognition_mode, bool exclusive_comm int vc_mgr_dbus_request_stop(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -1927,6 +1996,10 @@ int vc_mgr_dbus_request_stop(int pid) int vc_mgr_dbus_request_cancel(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -2005,6 +2078,10 @@ int vc_mgr_dbus_request_cancel(int pid) int vc_mgr_dbus_request_enable_command_type(int pid, int cmd_type) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -2084,6 +2161,10 @@ int vc_mgr_dbus_request_enable_command_type(int pid, int cmd_type) int vc_mgr_dbus_request_disable_command_type(int pid, int cmd_type) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusError err; dbus_error_init(&err); @@ -2190,6 +2271,10 @@ static DBusMessage* __get_message(int pid, const char* method, int type) int vc_mgr_dbus_send_result(int pid, int cmd_type, int result_id) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg = NULL; switch (cmd_type) { @@ -2228,6 +2313,10 @@ int vc_mgr_dbus_send_result(int pid, int cmd_type, int result_id) int vc_mgr_dbus_send_result_selection(int pid) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; /* create a signal & check for errors */ @@ -2263,6 +2352,10 @@ int vc_mgr_dbus_send_result_selection(int pid) int vc_mgr_dbus_send_specific_engine_request(int pid, const char* engine_app_id, const char* event, const char* request) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; /* create a signal & check for errors */ @@ -2301,6 +2394,10 @@ int vc_mgr_dbus_send_specific_engine_request(int pid, const char* engine_app_id, int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; msg = __get_message(pid, VC_MANAGER_METHOD_UTTERANCE_STATUS, VC_COMMAND_TYPE_FOREGROUND); @@ -2331,6 +2428,10 @@ int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status) int vc_mgr_dbus_send_audio_streaming(int pid, vc_audio_streaming_event_e event, unsigned char* buffer, unsigned int len) { + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + DBusMessage* msg; msg = dbus_message_new_method_call( VC_SERVER_SERVICE_NAME, diff --git a/client/vc_widget_dbus.c b/client/vc_widget_dbus.c index 2289060..d71d479 100644 --- a/client/vc_widget_dbus.c +++ b/client/vc_widget_dbus.c @@ -453,7 +453,7 @@ int vc_widget_dbus_reconnect() static int __dbus_check() { - if (NULL == g_w_conn_sender) { + if (NULL == g_w_conn_sender || NULL == g_w_conn_listener) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] NULL connection"); return vc_widget_dbus_reconnect(); } -- 2.7.4 From 49344121d2107f17dab64d78cbb33b60a5945e02 Mon Sep 17 00:00:00 2001 From: Wonnam Jang Date: Fri, 28 Sep 2018 21:01:21 +0900 Subject: [PATCH 13/16] Add updating logic Change-Id: Ic01f22d43e21c4f1f534492a5d24ae051f7331e3 Signed-off-by: Wonnam Jang --- client/vc_mgr.c | 11 +++++++++++ include/vce.h | 1 - include/vce_internal.h | 12 ++++++++++++ include/voice_control_common.h | 2 +- include/voice_control_internal.h | 1 + include/voice_control_manager_internal.h | 2 ++ server/vcd_main.h | 3 ++- server/vcd_server.c | 28 ++++++++++++++++++++++++++++ server/vcd_server.h | 3 +++ server/vce.c | 28 ++++++++++++++++++++++++++++ 10 files changed, 88 insertions(+), 3 deletions(-) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index a1e4ea0..d97a038 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -2917,6 +2917,13 @@ int __vc_mgr_cb_error(int reason, int daemon_pid, char* msg) if (VC_ERROR_SERVICE_RESET == reason) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] VC daemon reset"); + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_UPDATING) { + SLOG(LOG_INFO, TAG_VCM, "[INFO] VC daemon is terminated by update manager"); + return 0; + } + vc_mgr_client_set_client_state(g_vc_m, VC_STATE_INITIALIZED); __vc_mgr_notify_state_changed(g_vc_m); @@ -3035,6 +3042,10 @@ int __vc_mgr_cb_service_state(int state) SLOG(LOG_DEBUG, TAG_VCM, "Internal state is changed to NONE"); vc_mgr_client_set_internal_state(g_vc_m, VC_INTERNAL_STATE_NONE); } + if (VC_SERVICE_STATE_UPDATING == current_state) { + SLOG(LOG_DEBUG, TAG_VCM, "Internal state is changed to NONE by updating"); + vc_mgr_client_set_internal_state(g_vc_m, VC_INTERNAL_STATE_NONE); + } if (current_state == before_state) { SLOG(LOG_WARN, TAG_VCM, "Service State NOT changed : Before(%d) Current(%d)", diff --git a/include/vce.h b/include/vce.h index af6f5ce..b73fabd 100644 --- a/include/vce.h +++ b/include/vce.h @@ -121,7 +121,6 @@ typedef enum { VCE_FEEDBACK_EVENT_FINISH = 3 /**< Finish event */ } vce_feedback_event_e; - /** * @brief A structure of handle for VC command. * @since_tizen @if MOBILE 4.0 @elseif WEARABLE 5.0 @endif diff --git a/include/vce_internal.h b/include/vce_internal.h index c7439bb..19c51f6 100644 --- a/include/vce_internal.h +++ b/include/vce_internal.h @@ -41,6 +41,18 @@ typedef struct { void* get_tts_audio_format_user_data; } vce_internal_request_callback_s; +/** + * @brief Enumeration for TTS feedback events. + * @since_tizen 5.0 + */ +typedef enum { + VCE_UPDATE_EVENT_FAIL = -1, /**< Failed */ + VCE_UPDATE_EVENT_START = 1, /**< Start event */ + VCE_UPDATE_EVENT_FINISH = 2 /**< Finish event */ +} vce_update_event_e; + +int vce_send_update_status(vce_update_event_e update_event, const char* msg); + #ifdef __cplusplus } diff --git a/include/voice_control_common.h b/include/voice_control_common.h index 5ae1ffa..4bf4ba1 100644 --- a/include/voice_control_common.h +++ b/include/voice_control_common.h @@ -79,7 +79,7 @@ typedef enum { VC_SERVICE_STATE_NONE = 0, /**< 'None' state */ VC_SERVICE_STATE_READY = 1, /**< 'Ready' state */ VC_SERVICE_STATE_RECORDING = 2, /**< 'Recording' state */ - VC_SERVICE_STATE_PROCESSING = 3 /**< 'Processing' state */ + VC_SERVICE_STATE_PROCESSING = 3 /**< 'Processing' state */ } vc_service_state_e; diff --git a/include/voice_control_internal.h b/include/voice_control_internal.h index dc26186..8bc1961 100644 --- a/include/voice_control_internal.h +++ b/include/voice_control_internal.h @@ -40,6 +40,7 @@ typedef enum { VC_TTS_UTTERANCE_CANCELED = 3 } vc_tts_utterance_status_e; + /** * @brief Called when client gets the asr recognition result from vc-daemon. * diff --git a/include/voice_control_manager_internal.h b/include/voice_control_manager_internal.h index 4b58230..91778b2 100644 --- a/include/voice_control_manager_internal.h +++ b/include/voice_control_manager_internal.h @@ -40,6 +40,8 @@ typedef enum { VC_AUDIO_STREAMING_MODE_OUTSIDE = 2, /**< Use audio streaming from outside */ } vc_audio_streaming_mode_e; +#define VC_SERVICE_STATE_UPDATING 4 /**< 'Updating' state */ + /** * @brief Sets demandable client list. * diff --git a/server/vcd_main.h b/server/vcd_main.h index 46b9fd8..782f501 100644 --- a/server/vcd_main.h +++ b/server/vcd_main.h @@ -71,7 +71,8 @@ typedef enum { VCD_STATE_NONE = 0, VCD_STATE_READY = 1, VCD_STATE_RECORDING = 2, - VCD_STATE_PROCESSING = 3 + VCD_STATE_PROCESSING = 3, + VCD_STATE_UPDATING = 4 } vcd_state_e; typedef enum { diff --git a/server/vcd_server.c b/server/vcd_server.c index 8de4a88..3839763 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -30,6 +30,7 @@ #include "vcd_config.h" #include "vcd_recorder.h" #include "vcd_dbus.h" +#include "vce_internal.h" #include "voice_control_command_expand.h" #include "voice_control_common.h" @@ -3074,6 +3075,33 @@ int vcd_stop_recording() return ret; } +int vcd_send_update_status(vce_update_event_e update_event, const char* msg) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[Server] update status, update event(%d), msg(%s)", update_event, msg); + + int ret = 0; + if (VCE_UPDATE_EVENT_START == update_event) { + if (VCD_STATE_RECORDING == vcd_config_get_service_state() || VCD_STATE_PROCESSING == vcd_config_get_service_state()) { + ret = vcd_server_mgr_cancel(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server Error] Fail to cancel, ret(%d)", ret); + return ret; + } + } + vcd_config_set_service_state(VCD_STATE_UPDATING); + vcdc_send_service_state(VCD_STATE_UPDATING); + + } else if (VCE_UPDATE_EVENT_FINISH == update_event) { + vcd_config_set_service_state(VCD_STATE_READY); + vcdc_send_service_state(VCD_STATE_READY); + + } else if (VCE_UPDATE_EVENT_FAIL == update_event) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Update event : Fail - msg(%s)", msg); + } + + return 0; +} + int vcd_set_private_data_set_cb(vce_private_data_set_cb callback_func) { SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set private data set cb"); diff --git a/server/vcd_server.h b/server/vcd_server.h index d6270f1..739e6ec 100644 --- a/server/vcd_server.h +++ b/server/vcd_server.h @@ -22,6 +22,7 @@ #include "vcd_client_data.h" #include "vce.h" +#include "vce_internal.h" #ifdef __cplusplus extern "C" { @@ -172,6 +173,8 @@ int vcd_start_recording(); int vcd_stop_recording(); +int vcd_send_update_status(vce_update_event_e update_event, const char* msg); + int vcd_set_private_data_set_cb(vce_private_data_set_cb callback_func); int vcd_set_private_data_requested_cb(vce_private_data_requested_cb callback_func); diff --git a/server/vce.c b/server/vce.c index cfc93a8..cc9f73f 100644 --- a/server/vce.c +++ b/server/vce.c @@ -372,6 +372,17 @@ int vce_set_private_data(const char* key, const char* data) return VCE_ERROR_INVALID_PARAMETER; } + if (!strncmp(key, "UpdateEventStart", strlen(key))) + ret = vce_send_update_status(VCE_UPDATE_EVENT_START, NULL); + else if (!strncmp(data, "UpdateEventComplete", strlen(key))) + ret = vce_send_update_status(VCE_UPDATE_EVENT_FINISH, NULL); + else if (!strncmp(data, "UpdateEventFail", strlen(key))) + ret = vce_send_update_status(VCE_UPDATE_EVENT_FAIL, data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to send update status, event(%s), msg(%s): ret(%d)", key, data, ret); + return ret; + } + ret = vcd_set_private_data(key, data); if (0 != ret) { SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set private data to vc manager"); @@ -442,6 +453,23 @@ int vce_stop_recording() return ret; } +int vce_send_update_status(vce_update_event_e update_event, const char* msg) +{ + if (0 != __vce_get_feature_enabled()) { + return VCE_ERROR_NOT_SUPPORTED; + } + if (0 != __vce_check_privilege()) { + return VCE_ERROR_PERMISSION_DENIED; + } + + int ret = vcd_send_update_status(update_event, msg); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to send update status"); + } + + return ret; +} + int vce_set_private_data_set_cb(vce_private_data_set_cb callback_func) { if (0 != __vce_get_feature_enabled()) { -- 2.7.4 From 14eb3b4d4d85cb8d9b7502eeddd38ff9323fcdb5 Mon Sep 17 00:00:00 2001 From: Wonnam Jang Date: Mon, 1 Oct 2018 19:23:52 +0900 Subject: [PATCH 14/16] Add apis to change system volume Change-Id: Ic04618b85abd6e5c3a162bd3d204dd91bc4aeac9 Signed-off-by: Wonnam Jang --- client/vc_mgr.c | 75 ++++++++++++++++++++++++++++ client/vc_mgr_dbus.c | 84 ++++++++++++++++++++++++++++++++ client/vc_mgr_dbus.h | 2 + common/vc_defs.h | 1 + include/voice_control_manager_internal.h | 5 ++ server/vcd_dbus.c | 3 ++ server/vcd_dbus_server.c | 53 ++++++++++++++++++++ server/vcd_dbus_server.h | 2 + server/vcd_main.h | 5 ++ server/vcd_recorder.c | 56 +++++++++++++++++++++ server/vcd_recorder.h | 4 ++ server/vcd_server.c | 22 +++++++++ server/vcd_server.h | 2 + 13 files changed, 314 insertions(+) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index d97a038..553ef4c 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -4369,3 +4369,78 @@ int vc_mgr_set_audio_streaming_mode(vc_audio_streaming_mode_e streaming_mode) return ret; } + +int vc_mgr_change_system_volume() +{ + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Change system volume"); + + if (0 != __vc_mgr_get_feature_enabled()) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] not supported"); + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY', state(%d)", state); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* send audio streaming */ + int ret = vc_mgr_dbus_change_system_volume(g_vc_m->handle, VC_SYSTEM_VOLUME_EVENT_CHANGE); + if (0 != ret) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry to change volume"); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] Success to send"); + } + return ret; +} + +int vc_mgr_recover_system_volume() +{ + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] recover system volume"); + + if (0 != __vc_mgr_get_feature_enabled()) { + SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] not supported"); + return VC_ERROR_NOT_SUPPORTED; + } + + if (0 != __vc_mgr_check_privilege()) { + return VC_ERROR_PERMISSION_DENIED; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY', state(%d)", state); + SLOG(LOG_DEBUG, TAG_VCM, "@@@"); + return VC_ERROR_INVALID_STATE; + } + + /* send audio streaming */ + int ret = vc_mgr_dbus_change_system_volume(g_vc_m->handle, VC_SYSTEM_VOLUME_EVENT_RECOVER); + if (0 != ret) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry to recover volume"); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] Success to send"); + } + return ret; + +} diff --git a/client/vc_mgr_dbus.c b/client/vc_mgr_dbus.c index 7545a7f..7b7c432 100644 --- a/client/vc_mgr_dbus.c +++ b/client/vc_mgr_dbus.c @@ -2468,3 +2468,87 @@ int vc_mgr_dbus_send_audio_streaming(int pid, vc_audio_streaming_event_e event, return 0; } +int vc_mgr_dbus_change_system_volume(int pid, vc_system_volume_event_e volume_event) +{ + if (0 != __dbus_check()) { + return VC_ERROR_OPERATION_FAILED; + } + + DBusError err; + dbus_error_init(&err); + + bool exist = dbus_bus_name_has_owner(g_m_conn_sender, VC_SERVER_SERVICE_NAME, &err); + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + int ret; + int temp_event = (int)volume_event; + if (false == exist) { + ret = __dbus_restore_daemon(); + if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to restore daemon"); + return VC_ERROR_TIMED_OUT; + } + return VC_ERROR_OPERATION_FAILED; + } + + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + VC_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + VC_MANAGER_METHOD_CHANGE_SYSTEM_VOLUME); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, "@@ vc change system volume : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "@@ vc change system volume : pid(%d) volume_event(%d)", pid, temp_event); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &temp_event, + DBUS_TYPE_INVALID); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn_sender, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "@@ Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "@@ vc change system volume : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "@@ vc change system volume : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "@@ Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + diff --git a/client/vc_mgr_dbus.h b/client/vc_mgr_dbus.h index 9ce1239..a6202ea 100644 --- a/client/vc_mgr_dbus.h +++ b/client/vc_mgr_dbus.h @@ -80,6 +80,8 @@ int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status); int vc_mgr_dbus_send_audio_streaming(int pid, vc_audio_streaming_event_e event, unsigned char* buffer, unsigned int len); +int vc_mgr_dbus_change_system_volume(int pid, vc_system_volume_event_e volume_event); + #ifdef __cplusplus } #endif diff --git a/common/vc_defs.h b/common/vc_defs.h index 55fc210..79b6d7a 100644 --- a/common/vc_defs.h +++ b/common/vc_defs.h @@ -152,6 +152,7 @@ extern "C" { #define VC_MANAGER_METHOD_UTTERANCE_STATUS "vc_manager_method_utterance_status" #define VC_MANAGER_METHOD_SEND_AUDIO_STREAMING "vc_manager_method_send_audio_streaming" +#define VC_MANAGER_METHOD_CHANGE_SYSTEM_VOLUME "vc_manager_method_change_system_volume" #define VCD_MANAGER_METHOD_HELLO "vcd_manager_method_hello" #define VCD_MANAGER_METHOD_SPEECH_DETECTED "vcd_manager_method_speech_detected" diff --git a/include/voice_control_manager_internal.h b/include/voice_control_manager_internal.h index 91778b2..4e3953c 100644 --- a/include/voice_control_manager_internal.h +++ b/include/voice_control_manager_internal.h @@ -40,6 +40,11 @@ typedef enum { VC_AUDIO_STREAMING_MODE_OUTSIDE = 2, /**< Use audio streaming from outside */ } vc_audio_streaming_mode_e; +typedef enum { + VC_SYSTEM_VOLUME_EVENT_CHANGE, + VC_SYSTEM_VOLUME_EVENT_RECOVER +} vc_system_volume_event_e; + #define VC_SERVICE_STATE_UPDATING 4 /**< 'Updating' state */ /** diff --git a/server/vcd_dbus.c b/server/vcd_dbus.c index 1718191..4c9fde0 100644 --- a/server/vcd_dbus.c +++ b/server/vcd_dbus.c @@ -1153,6 +1153,9 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_MANAGER_METHOD_SEND_AUDIO_STREAMING)) vcd_dbus_server_mgr_send_audio_streaming(g_conn_listener, msg); + else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_MANAGER_METHOD_CHANGE_SYSTEM_VOLUME)) + vcd_dbus_server_mgr_change_system_volume(g_conn_listener, msg); + /* client event */ else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_INITIALIZE)) vcd_dbus_server_initialize(g_conn_listener, msg); diff --git a/server/vcd_dbus_server.c b/server/vcd_dbus_server.c index 9740609..2739c5b 100644 --- a/server/vcd_dbus_server.c +++ b/server/vcd_dbus_server.c @@ -1224,6 +1224,59 @@ int vcd_dbus_server_mgr_send_audio_streaming(DBusConnection* conn, DBusMessage* return ret; } +int vcd_dbus_server_mgr_change_system_volume(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid = 0; + int volume_event = 0; + + int ret = VCD_ERROR_OPERATION_FAILED; + + SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD Manager change system volume"); + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &volume_event, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd mgr disable command type : get arguments error (%s)", err.message); + dbus_error_free(&err); + ret = VCD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd mgr change system volume: pid(%d), volume_event(%d)", pid, volume_event); + ret = vcd_server_mgr_change_system_volume(pid, volume_event); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d)", ret); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_VCD, "@@@"); + + return 0; + +} /* * Dbus Server functions for client diff --git a/server/vcd_dbus_server.h b/server/vcd_dbus_server.h index ac02296..6182697 100644 --- a/server/vcd_dbus_server.h +++ b/server/vcd_dbus_server.h @@ -69,6 +69,8 @@ int vcd_dbus_server_mgr_disable_command_type(DBusConnection* conn, DBusMessage* int vcd_dbus_server_mgr_send_specific_engine_request(DBusConnection* conn, DBusMessage* msg); +int vcd_dbus_server_mgr_change_system_volume(DBusConnection* conn, DBusMessage* msg); + /* for TTS feedback */ int vcd_dbus_server_mgr_start_feedback(DBusConnection* conn, DBusMessage* msg); diff --git a/server/vcd_main.h b/server/vcd_main.h index 782f501..04ecdbf 100644 --- a/server/vcd_main.h +++ b/server/vcd_main.h @@ -88,6 +88,11 @@ typedef enum { VCD_AUDIO_STREAMING_MODE_OUTSIDE = 2, /**< Use audio streaming from outside */ } vcd_audio_streaming_mode_e; +typedef enum { + VCD_SYSTEM_VOLUME_EVENT_CHANGE, + VCD_SYSTEM_VOLUME_EVENT_RECOVER +} vcd_system_volume_event_e; + struct vce_cmd_s { int index; }; diff --git a/server/vcd_recorder.c b/server/vcd_recorder.c index 6ffb708..a024942 100644 --- a/server/vcd_recorder.c +++ b/server/vcd_recorder.c @@ -74,6 +74,9 @@ static int g_buffer_count; static int g_device_id = -1; +static sound_stream_info_h g_stream_for_volume_h = NULL; +static virtual_sound_stream_h g_virtual_sound_stream_h = NULL; + /* Sound buf save */ #if 0 #define BUF_SAVE_MODE @@ -897,6 +900,59 @@ int vcd_recorder_stop_streaming() return 0; } +int vcd_recorder_change_system_volume() +{ + if (!g_stream_for_volume_h) { + int ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE, NULL, NULL, &g_stream_for_volume_h); + if (0 != ret) { + SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Fail to create stream information, ret(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + if (!g_virtual_sound_stream_h) { + ret = sound_manager_create_virtual_stream(g_stream_for_volume_h, &g_virtual_sound_stream_h); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create virtual stream, ret(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + ret = sound_manager_start_virtual_stream(g_virtual_sound_stream_h); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start virtual stream, ret(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + } + } + + return 0; +} + +int vcd_recorder_recover_system_volume() +{ + if (g_virtual_sound_stream_h) { + int ret = sound_manager_stop_virtual_stream(g_virtual_sound_stream_h); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to stop virtual stream, ret(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + ret = sound_manager_destroy_virtual_stream(g_virtual_sound_stream_h); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to destroy virtual stream, ret(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + g_virtual_sound_stream_h = NULL; + + if (g_stream_for_volume_h) { + ret = sound_manager_destroy_stream_information(g_stream_for_volume_h); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to destroy stream information, ret(%d)", ret); + return VCD_ERROR_OPERATION_FAILED; + } + g_stream_for_volume_h = NULL; + } + } + + return 0; +} + int vcd_recorder_start() { int ret = -1; diff --git a/server/vcd_recorder.h b/server/vcd_recorder.h index 7a612b8..9ac8b1e 100644 --- a/server/vcd_recorder.h +++ b/server/vcd_recorder.h @@ -49,6 +49,10 @@ int vcd_recorder_send_streaming(const void* buffer, const unsigned int length); int vcd_recorder_stop_streaming(); +int vcd_recorder_change_system_volume(); + +int vcd_recorder_recover_system_volume(); + int vcd_recorder_start(); int vcd_recorder_read(); diff --git a/server/vcd_server.c b/server/vcd_server.c index 3839763..4f369e0 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -2257,6 +2257,28 @@ int vcd_server_mgr_send_audio_streaming(int pid, int event, unsigned char* buffe return VCD_ERROR_NONE; } +int vcd_server_mgr_change_system_volume(int pid, vcd_system_volume_event_e system_volume_event) +{ + SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] change system volume, system volume event(%d)", system_volume_event); + + int ret = 0; + if (VCD_SYSTEM_VOLUME_EVENT_CHANGE == system_volume_event) { + ret = vcd_recorder_change_system_volume(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to change system volume, ret(%d)", ret); + return ret; + } + } else if (VCD_SYSTEM_VOLUME_EVENT_RECOVER == system_volume_event) { + ret = vcd_recorder_recover_system_volume(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to recover system volume, ret(%d)", ret); + return ret; + } + } + + return ret; +} + /* * VC Server Functions for Client diff --git a/server/vcd_server.h b/server/vcd_server.h index 739e6ec..7979e4a 100644 --- a/server/vcd_server.h +++ b/server/vcd_server.h @@ -81,6 +81,8 @@ int vcd_server_mgr_enable_command_type(int pid, int cmd_type); int vcd_server_mgr_disable_command_type(int pid, int cmd_type); +int vcd_server_mgr_change_system_volume(int pid, vcd_system_volume_event_e system_volume_event); + /* for TTS feedback */ int vcd_server_mgr_start_feedback(void); -- 2.7.4 From ce46d2756a744b8b2320d84c0d6764651f84b1dc Mon Sep 17 00:00:00 2001 From: Wonnam Jang Date: Mon, 1 Oct 2018 20:55:45 +0900 Subject: [PATCH 15/16] Add system volume api on internal header Change-Id: I5ade6a51bf9c30ebc75d06ccdb9c3ed528df5087 Signed-off-by: Wonnam Jang --- include/voice_control_manager_internal.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/voice_control_manager_internal.h b/include/voice_control_manager_internal.h index 4e3953c..9d22ede 100644 --- a/include/voice_control_manager_internal.h +++ b/include/voice_control_manager_internal.h @@ -108,6 +108,20 @@ int vc_mgr_send_audio_streaming(vc_audio_streaming_event_e event, unsigned char* int vc_mgr_set_audio_streaming_mode(vc_audio_streaming_mode_e streaming_mode); +/** + * @brief Changes system volume. + * @since_tizen 5.0 + * + */ +int vc_mgr_change_system_volume(); + +/** + * @brief Recover system volume. + * @since_tizen 5.0 + * + */ +int vc_mgr_recover_system_volume(); + #ifdef __cplusplus } #endif -- 2.7.4 From b6e06afc544143e6b05f3fb0cc59a9386784a430 Mon Sep 17 00:00:00 2001 From: Wonnam Jang Date: Mon, 8 Oct 2018 17:51:01 +0900 Subject: [PATCH 16/16] Sync with tizen 4.0 branch Change-Id: I22ddb9911deeafa4b12dc3d89fea3b0059fec383 Signed-off-by: Wonnam Jang --- client/vc_mgr.c | 4 +- client/vc_mgr_data.cpp | 18 +++--- include/voice_control_internal.h | 56 +++++++++---------- include/voice_control_manager.h | 118 ++++++++++++++++++++------------------- server/vcd_main.h | 3 +- server/vcd_server.c | 72 ++++++++++++++++-------- 6 files changed, 152 insertions(+), 119 deletions(-) diff --git a/client/vc_mgr.c b/client/vc_mgr.c index 553ef4c..39e46e9 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -3443,7 +3443,7 @@ int __vc_mgr_cb_feedback_streaming(int pid, int utt_id, vc_feedback_event_e even } } - return ret; + return ret; } @@ -4079,6 +4079,7 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread) } if (200 < cnt) { SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Wrong request, there's no pcm data"); + vc_mgr_data_clear_feedback_data(&feedback_data); return; } cnt++; @@ -4086,6 +4087,7 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread) SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish to wait for new feedback data come"); /* resume feedback thread */ + vc_mgr_data_clear_feedback_data(&feedback_data); continue; } diff --git a/client/vc_mgr_data.cpp b/client/vc_mgr_data.cpp index 866d3da..26482c1 100644 --- a/client/vc_mgr_data.cpp +++ b/client/vc_mgr_data.cpp @@ -96,20 +96,22 @@ int vc_mgr_data_get_feedback_data_size() int vc_mgr_data_clear_feedback_data(vc_feedback_data_s** data) { - SLOG(LOG_DEBUG, TAG_VCM, "[DATA] clear feedback data"); + SLOG(LOG_DEBUG, TAG_VCM, "[DATA] clear feedback data, empty(%d)", g_feedback_data.empty()); pthread_mutex_lock(&g_feedback_data_mutex); if (!g_feedback_data.empty()) { - SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] pid(%d), utt_id(%d), data(%p) size(%d) rate(%d)", (*data)->pid, (*data)->utt_id, (*data)->data, (*data)->data_size, (*data)->rate); + if (NULL != *data) { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] pid(%d), utt_id(%d), data(%p) size(%d) rate(%d)", (*data)->pid, (*data)->utt_id, (*data)->data, (*data)->data_size, (*data)->rate); - if (NULL != (*data)->data) { - free((*data)->data); - (*data)->data = NULL; - } + if (NULL != (*data)->data) { + free((*data)->data); + (*data)->data = NULL; + } - free(*data); - *data = NULL; + free(*data); + *data = NULL; + } } pthread_mutex_unlock(&g_feedback_data_mutex); diff --git a/include/voice_control_internal.h b/include/voice_control_internal.h index 8bc1961..cfbb9ea 100644 --- a/include/voice_control_internal.h +++ b/include/voice_control_internal.h @@ -1,18 +1,18 @@ -/* - * Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** + * Copyright (c) 2011-2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __VOICE_CONTROL_INTERNAL_H__ @@ -42,19 +42,19 @@ typedef enum { /** -* @brief Called when client gets the asr recognition result from vc-daemon. -* -* @param[in] event The result event -* @param[in] result ASR text -* @param[in] user_data The user data passed from the callback registration function -* -* @return @c true when asr result is consumed \n @c false to propagate. -* -* @pre An application registers callback function using vc_mgr_set_pre_result_cb(). -* -* @see vc_widget_set_asr_result_cb() -* @see vc_widget_unset_asr_result_cb() -*/ + * @brief Called when client gets the asr recognition result from vc-daemon. + * + * @param[in] event The result event + * @param[in] result ASR text + * @param[in] user_data The user data passed from the callback registration function + * + * @return @c true when asr result is consumed \n @c false to propagate. + * + * @pre An application registers callback function using vc_mgr_set_pre_result_cb(). + * + * @see vc_widget_set_asr_result_cb() + * @see vc_widget_unset_asr_result_cb() + */ typedef bool (*vc_asr_result_cb)(vc_result_event_e event, const char* result, void *user_data); /** diff --git a/include/voice_control_manager.h b/include/voice_control_manager.h index 430daa5..3d4ece3 100644 --- a/include/voice_control_manager.h +++ b/include/voice_control_manager.h @@ -1,18 +1,18 @@ -/* -* Copyright (c) 2011-2018 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the License); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an AS IS BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ +/** + * Copyright (c) 2011-2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __VOICE_CONTROL_MANAGER_H__ @@ -247,55 +247,57 @@ typedef int (*vc_mgr_private_data_requested_cb)(const char *key, char **data, vo /* for TTS feedback */ /** -* @brief Called when engine sends audio formats necessary for playing TTS feedback -* @since_tizen 5.0 -* -* @param[in] rate Audio sampling rate -* @param[in] channel Audio channel (e.g. #VC_AUDIO_CHANNEL_MONO, #VC_AUDIO_CHANNEL_STEREO) -* @param[in] audio_type Audio type (e.g. #VC_AUDIO_TYPE_PCM_S16_LE, #VC_AUDIO_TYPE_PCM_U8) -* @param[in] user_data The user data passed from the callback registration function -* -* @pre An application registers callback function using vc_mgr_set_feedback_audio_format_cb(). -* -* @see vc_mgr_set_feedback_audio_format_cb() -* @see vc_mgr_unset_feedback_audio_format_cb() -*/ + * @brief Called when engine sends audio formats necessary for playing TTS feedback + * @since_tizen 5.0 + * + * @param[in] rate Audio sampling rate + * @param[in] channel Audio channel (e.g. #VC_AUDIO_CHANNEL_MONO, #VC_AUDIO_CHANNEL_STEREO) + * @param[in] audio_type Audio type (e.g. #VC_AUDIO_TYPE_PCM_S16_LE, #VC_AUDIO_TYPE_PCM_U8) + * @param[in] user_data The user data passed from the callback registration function + * + * @pre An application registers callback function using vc_mgr_set_feedback_audio_format_cb(). + * + * @see vc_mgr_set_feedback_audio_format_cb() + * @see vc_mgr_unset_feedback_audio_format_cb() + */ typedef void (*vc_mgr_feedback_audio_format_cb)(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type, void *user_data); /** -* @brief Called when engine sends audio streaming for TTS feedback -* @since_tizen 5.0 -* -* @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE) -* @param[in] buffer Audio streaming data -* @param[in] len Length of the audio streaming data -* @param[in] user_data The user data passed from the callback registration function -* -* @pre An application registers callback function using vc_mgr_set_feedback_streaming_cb(). -* -* @see vc_mgr_set_feedback_streaming_cb() -* @see vc_mgr_unset_feedback_streaming_cb() -*/ + * @brief Called when engine sends audio streaming for TTS feedback + * @since_tizen 5.0 + * + * @remarks The @a buffer must be released with free() by you when you no longer need it. + * + * @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE) + * @param[in] buffer Audio streaming data + * @param[in] len Length of the audio streaming data + * @param[in] user_data The user data passed from the callback registration function + * + * @pre An application registers callback function using vc_mgr_set_feedback_streaming_cb(). + * + * @see vc_mgr_set_feedback_streaming_cb() + * @see vc_mgr_unset_feedback_streaming_cb() + */ typedef void (*vc_mgr_feedback_streaming_cb)(vc_feedback_event_e event, char* buffer, int len, void *user_data); /** -* @brief Called when the vc client sends audio streaming for TTS feedback -* @since_tizen 5.0 -* -* @remarks The @a buffer must be released with free() by you when you no longer need it. -* -* @param[in] pid The process id of the vc client -* @param[in] utt_id The utterance id -* @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE) -* @param[in] buffer Audio streaming data -* @param[in] len Length of the audio streaming data -* @param[in] user_data The user data passed from the callback registration function -* -* @pre An application registers callback function using vc_mgr_set_vc_tts_streaming_cb(). -* -* @see vc_mgr_set_vc_tts_streaming_cb() -* @see vc_mgr_unset_vc_tts_streaming_cb() -*/ + * @brief Called when the vc client sends audio streaming for TTS feedback + * @since_tizen 5.0 + * + * @remarks The @a buffer must be released with free() by you when you no longer need it. + * + * @param[in] pid The process id of the vc client + * @param[in] utt_id The utterance id + * @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE) + * @param[in] buffer Audio streaming data + * @param[in] len Length of the audio streaming data + * @param[in] user_data The user data passed from the callback registration function + * + * @pre An application registers callback function using vc_mgr_set_vc_tts_streaming_cb(). + * + * @see vc_mgr_set_vc_tts_streaming_cb() + * @see vc_mgr_unset_vc_tts_streaming_cb() + */ typedef void (*vc_mgr_vc_tts_streaming_cb)(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len, void *user_data); /** diff --git a/server/vcd_main.h b/server/vcd_main.h index 04ecdbf..70bcd18 100644 --- a/server/vcd_main.h +++ b/server/vcd_main.h @@ -72,7 +72,8 @@ typedef enum { VCD_STATE_READY = 1, VCD_STATE_RECORDING = 2, VCD_STATE_PROCESSING = 3, - VCD_STATE_UPDATING = 4 + VCD_STATE_SYNTHESIZING = 4, + VCD_STATE_UPDATING = 5 } vcd_state_e; typedef enum { diff --git a/server/vcd_server.c b/server/vcd_server.c index 4f369e0..f2e34f1 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -1098,16 +1098,16 @@ int vcd_send_error(vce_error_e error, const char* msg, void *user_data) /* for TTS feedback */ int vcd_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_audio_type_e audio_type) { - SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback audio format"); + SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback audio format, g_current_uid(%d)", g_current_uid); /* send TTS feedback audio format to VC manager */ int ret = VCD_ERROR_NONE; int pid = g_current_uid / 1000; if (-1 == g_current_uid || vcd_client_manager_get_pid() == pid) { - ret = vcdc_send_feedback_audio_format_to_manager(vcd_client_manager_get_pid(), rate, channel, audio_type); - if (VCD_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback audio format to VC manager"); - } + ret = vcdc_send_feedback_audio_format_to_manager(vcd_client_manager_get_pid(), rate, channel, audio_type); + if (VCD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback audio format to VC manager"); + } } else { SLOG(LOG_INFO, TAG_VCD, "[Server INFO] Do not send TTS feedback audio format to VC manager"); } @@ -1120,14 +1120,14 @@ int vcd_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int le if (-1 == g_current_uid && VCE_FEEDBACK_EVENT_START == event) { g_current_utt_id = (g_current_utt_id + 1) % 1000; g_current_uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id; - SLOG(LOG_INFO, TAG_VCD, "[Server info] set current uid and utt_id as manager pid"); + SLOG(LOG_INFO, TAG_VCD, "[Server info] set current uid and utt_id as manager pid(%d)", vcd_client_manager_get_pid()); } int ret = VCD_ERROR_NONE; int pid = g_current_uid / 1000; int utt_id = g_current_uid % 1000; - SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback streaming to pid(%d), is_mgr_client(%d)", pid, (pid == vcd_client_manager_get_pid() ? true : false)); + SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback streaming event(%d), uid(%d), is_mgr_client(%d)", event, g_current_uid, (pid == vcd_client_manager_get_pid() ? true : false)); if (pid == vcd_client_manager_get_pid()) { /* send TTS feedback streaming to manager client */ @@ -1138,14 +1138,21 @@ int vcd_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int le } else { /* send TTS feedback streaming to client */ ret = vcdc_send_feedback_streaming(pid, utt_id, event, buffer, len); - if (VCD_ERROR_NONE != ret) { + if (VCD_ERROR_NONE != ret) { SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to client"); - } + } } if (VCE_FEEDBACK_EVENT_FINISH == event) { /* reset current uid */ g_current_uid = -1; + + /* Set service state to ready if state is synthesizing */ + vcd_state_e state = vcd_config_get_service_state(); + if (VCD_STATE_SYNTHESIZING == state) { + vcd_config_set_service_state(VCD_STATE_READY); + } + SLOG(LOG_INFO, TAG_VCD, "[Server info] feedback streaming finish event, reset current uid & service state(%d)", vcd_config_get_service_state()); } return ret; } @@ -1845,8 +1852,8 @@ int vcd_server_mgr_start(vcd_recognition_mode_e recognition_mode, bool exclusive /* 1. check current state */ vcd_state_e state = vcd_config_get_service_state(); - if (VCD_STATE_READY != state) { - SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready"); + if (VCD_STATE_READY != state && VCD_STATE_SYNTHESIZING != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready and not synthesizine, state(%d)", state); return VCD_ERROR_INVALID_STATE; } if (-1 == vcd_client_manager_get_pid()) { @@ -2091,8 +2098,8 @@ int vcd_server_mgr_send_specific_engine_request(int pid, const char* engine_app_ return VCD_ERROR_INVALID_PARAMETER; } vcd_state_e state = vcd_config_get_service_state(); - if (VCD_STATE_READY != state) { - SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready"); + if (VCD_STATE_READY != state && VCD_STATE_SYNTHESIZING != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready and not synthesizing, state(%d)", state); return VCD_ERROR_INVALID_STATE; } @@ -2118,8 +2125,8 @@ int vcd_server_mgr_do_action(int pid, int type, const char* action) } vcd_state_e state = vcd_config_get_service_state(); - if (VCD_STATE_READY != state) { - SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready"); + if (VCD_STATE_READY != state && VCD_STATE_SYNTHESIZING != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready and not synthesizing, state(%d)", state); return VCD_ERROR_INVALID_STATE; } @@ -2514,6 +2521,7 @@ static void __start_tts_request_thread(void* data, Ecore_Thread* thread) while (1) { int ret = -1; + int cnt = 0; /* Get tts text data */ ret = vcd_data_get_first_tts_text_data(&tts_text_data); @@ -2527,6 +2535,23 @@ static void __start_tts_request_thread(void* data, Ecore_Thread* thread) continue; } + while (1) { + vcd_state_e state = vcd_config_get_service_state(); + if (VCD_STATE_READY != state) { + if (0 == cnt++ % 10) + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Waiting to request TTS, state(%d)", state); + usleep(100000); + continue; + } + break; + } + + /* Set service state to synthesizing */ + vcd_config_set_service_state(VCD_STATE_SYNTHESIZING); + + /* Set current uid */ + g_current_uid = tts_text_data->uid; + /* Request tts to engine */ ret = vcd_engine_request_tts(tts_text_data->pid, tts_text_data->utt_id, tts_text_data->text, tts_text_data->language); if (0 != ret) { @@ -2556,20 +2581,21 @@ int vcd_server_request_tts(int pid, const char* text, const char* language, int } vcd_state_e state = vcd_config_get_service_state(); - if (VCD_STATE_READY != state) { + if (VCD_STATE_READY != state && VCD_STATE_SYNTHESIZING != state) { SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready, state(%d)", state); return VCD_ERROR_INVALID_STATE; } + int uid = -1; g_current_utt_id = (g_current_utt_id + 1) % 1000; *utt_id = g_current_utt_id; if (0 == to_vcm) { - g_current_uid = pid * 1000 + g_current_utt_id; + uid = pid * 1000 + g_current_utt_id; } else { - g_current_uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id; + uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id; } SLOG(LOG_INFO, TAG_VCD, "[Server INFO] pid(%d), text(%s), language(%s), to_vcm(%d), ", pid, text, language, to_vcm); - SLOG(LOG_INFO, TAG_VCD, "[Server INFO] current_uid(%d), current_utt_id(%d)", g_current_uid, g_current_utt_id); + SLOG(LOG_INFO, TAG_VCD, "[Server INFO] current_uid(%d), current_utt_id(%d)", uid, g_current_utt_id); vc_tts_text_data_s* tts_text_data; tts_text_data = (vc_tts_text_data_s*)calloc(1, sizeof(vc_tts_text_data_s)); @@ -2577,7 +2603,7 @@ int vcd_server_request_tts(int pid, const char* text, const char* language, int SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to callocate memory "); return VCD_ERROR_OUT_OF_MEMORY; } - tts_text_data->uid = g_current_uid; + tts_text_data->uid = uid; tts_text_data->pid = pid; tts_text_data->utt_id = g_current_utt_id; tts_text_data->text = strdup(text); @@ -2606,7 +2632,7 @@ int vcd_server_cancel_tts(int pid, int utt_id) } vcd_state_e state = vcd_config_get_service_state(); - if (VCD_STATE_READY != state) { + if (VCD_STATE_READY != state && VCD_STATE_SYNTHESIZING != state) { SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready, state(%d)", state); return VCD_ERROR_INVALID_STATE; } @@ -2642,8 +2668,8 @@ int vcd_server_get_tts_audio_format(int pid, int* rate, int* channel, int* audio } vcd_state_e state = vcd_config_get_service_state(); - if (VCD_STATE_READY != state) { - SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready"); + if (VCD_STATE_READY != state && VCD_STATE_SYNTHESIZING != state) { + SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready and not synthesizing, state(%d)", state); return VCD_ERROR_INVALID_STATE; } -- 2.7.4