From 095ee50edc61cedc6067406127fc589497b5542b Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Mon, 17 Jul 2017 12:05:58 -0400 Subject: [PATCH 01/22] 2017-07-06 Fred Gleason * Added an 'RDEscapeShellString()' function in 'lib/rdescape_string.h' and 'lib/rdescape_string.cpp'. * Fixed a bug in 'lib/rduser.cpp' that caused PAM authentication of accounts with a password containing one or more '$' characters to fail. --- ChangeLog | 5 +++ lib/rdescape_string.cpp | 83 ++++------------------------------------- lib/rdescape_string.h | 4 +- lib/rduser.cpp | 3 +- 4 files changed, 16 insertions(+), 79 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42b0a393..c1289201 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15891,3 +15891,8 @@ * Removed RD_MAX_STATIONS from 'lib/rd.h'. 2017-07-06 Fred Gleason * Incremented the package version to 2.16.0int06. +2017-07-06 Fred Gleason + * Added an 'RDEscapeShellString()' function in 'lib/rdescape_string.h' + and 'lib/rdescape_string.cpp'. + * Fixed a bug in 'lib/rduser.cpp' that caused PAM authentication of + accounts with a password containing one or more '$' characters to fail. diff --git a/lib/rdescape_string.cpp b/lib/rdescape_string.cpp index c2a1c6f7..9f44fe65 100644 --- a/lib/rdescape_string.cpp +++ b/lib/rdescape_string.cpp @@ -2,7 +2,7 @@ // // Escape non-valid characters in a string. // -// (C) Copyright 2002-2005,2016 Fred Gleason +// (C) Copyright 2002-2005,2016-2017 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -147,80 +147,11 @@ QString RDEscapeString(QString const &str) } } - /* - for(unsigned i=0;i': - res+=QString("\\>"); - break; - - case '|': - res+=QString("\\|"); - break; - - default: - res+=((const char *)str)[i]; - break; - } - } - */ - return res; } + + +QString RDEscapeShellString(QString str) +{ + return "\""+str.replace("$","\\$")+"\""; +} diff --git a/lib/rdescape_string.h b/lib/rdescape_string.h index 553d84a6..f811b49a 100644 --- a/lib/rdescape_string.h +++ b/lib/rdescape_string.h @@ -2,7 +2,7 @@ // // Escape non-valid characters in a string. // -// (C) Copyright 2002-2005,2016 Fred Gleason +// (C) Copyright 2002-2005,2016-2017 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -28,7 +28,7 @@ QString RDCheckDateTime(const QTime &time, const QString &format); QString RDCheckDateTime(const QDateTime &datetime, const QString &format); QString RDCheckDateTime(const QDate &date, const QString &format); QString RDEscapeString(const QString &str); - +QString RDEscapeShellString(QString str); #endif // RDESCAPE_STRING_H diff --git a/lib/rduser.cpp b/lib/rduser.cpp index 32d331c7..4f049464 100644 --- a/lib/rduser.cpp +++ b/lib/rduser.cpp @@ -70,7 +70,8 @@ bool RDUser::authenticated(bool webuser) const #ifndef WIN32 else { QString cmd= - "rdauth "+pamService()+" \""+user_name+"\" \""+user_password+"\""; + "rdauth "+pamService()+" "+RDEscapeShellString(user_name)+" "+ + RDEscapeShellString(user_password); int exitcode=system(cmd); return WEXITSTATUS(exitcode)==0; } From 292e7a1046b9d4ae95f19aadee776279a2b0131c Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Mon, 17 Jul 2017 12:08:14 -0400 Subject: [PATCH 02/22] Fixed typo in ChangeLog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c1289201..d55e5e64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15891,7 +15891,7 @@ * Removed RD_MAX_STATIONS from 'lib/rd.h'. 2017-07-06 Fred Gleason * Incremented the package version to 2.16.0int06. -2017-07-06 Fred Gleason +2017-07-17 Fred Gleason * Added an 'RDEscapeShellString()' function in 'lib/rdescape_string.h' and 'lib/rdescape_string.cpp'. * Fixed a bug in 'lib/rduser.cpp' that caused PAM authentication of From 9f18d8ba2b592e5174658fe2ff16b26570b2555e Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Mon, 17 Jul 2017 12:11:51 -0400 Subject: [PATCH 03/22] 2017-07-17 Fred Gleason * Incremented the package version to 2.16.0int06_rfa00. --- ChangeLog | 2 ++ PACKAGE_VERSION | 2 +- rivendell.ism | Bin 499284 -> 499284 bytes 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d55e5e64..e5106932 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15896,3 +15896,5 @@ and 'lib/rdescape_string.cpp'. * Fixed a bug in 'lib/rduser.cpp' that caused PAM authentication of accounts with a password containing one or more '$' characters to fail. +2017-07-17 Fred Gleason + * Incremented the package version to 2.16.0int06_rfa00. diff --git a/PACKAGE_VERSION b/PACKAGE_VERSION index 4b2a8275..7747dbcd 100644 --- a/PACKAGE_VERSION +++ b/PACKAGE_VERSION @@ -1 +1 @@ -2.16.0int06 \ No newline at end of file +2.16.0int06_rfa00 \ No newline at end of file diff --git a/rivendell.ism b/rivendell.ism index 2e4ee876084c998be02d356a3aae2e7bcc2ba2fb..df5cebb610b2af8c374713e2fee85b068ec98c0c 100644 GIT binary patch delta 16959 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%0DT`yR>0rA2E_rViP2NFq9}RaSJp7$Vt&*q zHci#yJ78ue=;wJn2h*}ZN_zm^5C?cKr&Pw4@KGl9227HtB4bq-9_fdUV3@oz+f+>~ z>PAm{mk1Vy~0Lf{+^ILZ=B8<9LKZIIFRa-oLoKW;Uq!zY*ql=Ewwer333&{<4* z8R3IvqTyD`!iLsCLJ?^s!$%VeU0!aRfET1$3MdWUlyr0&LpkvXRFo12WAlM!pR}b`Wg?%3N~Gf75{3}VyiADq<#;X z!-*8PUzyj{OxKD~uH8CaOGahs?&+Gl z1HOQgs^m^^#sT^TqojpxU&b1R*j8*J3||q;{`h&8g1{;1I`==SaaEK=*ync$&Z?; z4H<8R{{o&F1{W{WXz6>pxho~LNsT2sW)JZGz4kE&F2+bgp1RQ%AmvW z|B{akFl;0+)CGjdmuW;6`-Im3gbDb-hs*6rP%71hI!hZ= zh)_oNNtb{0I(rt~&Unuy{ZH5-$BTldi%GMzyqNHc38?B6LahB0mgB@R)Ah&&h@*JT~jexd$)aloH zMP>#DV!GD>Vah(x&mDkLZlI8sDZsX?G${cvJmInEl}SVhK6EcKy$BqE%)4cn5@@u| zKo$|&$-6Bi2agPjI%MIt8iI)c{Xzar_Ioc;p8$hxd~gS603${H9B@FD*gi)~>cE`_J<_DmJm@mg%PRmO zF$0v>A5aFN;IqGt4cRO>j055UFOsTJfVEf{th1rnUYH-{6AMsQSHMRD028raw_Qb= zitr>EpOEgi)4m;{9S?N-Et-$#ilvj1T-|rM+^(HKx6><`cub6*s}+uu)v$FS{V`#x zu46&-!1^*bg9nXhvHe~E4)hxg87uQAi{kKY1U2~rQm>0n+Vh$aQ7XP~7O&0K@;taV zq1CPS9!+r3AV3+%g5(HL7IMIBkK=jCuHd@^fbnAJ@3fqJQ%0-JD`j77Kq~dk$k8ye zA4dKPdM5%RRelsOUTpfEmNiNizT73U92RECV8+3NrQZqptaj3%;LyjWhB1}pElmv# zE%eL)h0Y-zcawJj&KIFln{I3A!V7;KFeSjcZFQUD1fVQ_Ws01)h zTscoGj+N!34=30U!F`yt4Y*ajF;9z2ku|Jw*8d0_{B|8!c)4)Q*Gg(+sqFhnAT}rt zNZ>v|@V<0ITLEPn2ksaSD6D`4E3tp07PGO>f z<=pN^T~B;CUrS|8;=l8?dfWumFVL)cFh^OYN}6hW4--cE&J=ra3$}eDprk9HSHr93VyXT!@Tg zo5)+JjqU*1c@Pu)2R}$t@ObH06da-SD8o}1AT-8;i7f=QnNz29Kq)DNn%_=SP$&g+ z8ng}2W=@kv1C~>*?nA$C@Ty*xEsX96%c7riWT`kLpGa9E$3eV0o@lQ4b)hzS^aRZ9 zM!n~wPMK-R$GUxvK`zJTZUH_zeuea*rI66o(`~zxJe3UiJ8^K4R#bz+9~E8EO_4f% zHPc?Z1$((0(56U(#sZ?^X24se1M1ij?B&1=n{mC+>~VnAB6sospE6X#g?iKAuw%w4 zHV%`VzHYHLO?pA6;4)|z460KpN6+_n5j-uY|geBAN*M><1(b`w(BuNGy6e4{HB9rn(R=t8|70W6nI7g@FFj;T$ z#!@XFk~8TnQs(g7UB*<6xtC|}((zSE-*M?oAe>PnQ92jOGR=w~fjt`m>YQ)y*&i_J zO2AlAw@k|@#}S!ekUuX_Xr?@^0G$MsS2f_EwSZD%U{(o$Gb9W9=mdJB9A-e%@3jXy zx=b5_i|Mn=;D`NChm=KjF(3dg#)~g-mQ}bbl{xFptB8(b*KP#=h4=-d*iN;bCc~-1 zw*EgLG*B?RHCdk5rSEivVE#T*s}Lth7u)Y4g!rVrw6kOQmL$G&?k38g5YtOpm{H(nO#Z91S$?mD>vaqJ$*^h2z#5xazDz5y5|^c7lq z8$t%u3=GOZTC!O(u8edRZl6dU0 z8w!L+FXPH*sCamVmVzqK>npT59ocvqQAOfXJDD}XN^iG!`vf0t2ef^HPE!EoqCsXc zfOfF%p&k!WKX$ZbBlSoXDO(CeliGB4O^ZpNi`hj2_k0%CRxCi4=Y)H9gO20$F87j~ip+C*qlEMT&{Nx%_K z#%K}tWFgLnL;FJm(LgbKt(HBzOvi243MzlhmIx9Fi&mn;WEhb_Zvf#!9dU!7#v*RW zz{%V7=Cet1Etljg)gfzyBn0ePr;pJOQEC7T^bTOO`1e{ZgIS{gI<24sEaxF@bLh|! z8@mAIzMx$vHg&TcTq+=#*b7ri0F-J23v>crc6o!qywNVCgslY*`J=T&E4#@KF~41& zu`{)H^5284Vm{p~_kB;jjBaJ;?r6xMdqHfOVSB^De;O|@?|xXP)ud#}aN723cP;8J z0U-fwr(QC+7H#Ws`|Ss>yoXKMH^L@82N*B5u7^TM>HhO7X|#xNy|fWFF)@;d&tc>j0&4f*NK54kBEN>N4}(jygjgf=nNT{a8Pev6AkUiAm2V zLi@Du4YQjRDhihz$b{D7zOz_VY|t{tT#^97(+(6$(}VoqE`r1kyr_ zI0uE?&$eKTmtO$#xMq&$#B2H<67 z8Ti4^dxvfd-3Uux!S7SU)`Nr)SNfOb+fdNG)8##;%}OZsIYLs^QJ~F5u^~r#J?VOq z4k#J6$FU3d&os)%E=kp(-ypL>k+V@7!D_^;ji@qs!6Ru~?cq#t&PljUo2mnNwZYz< z1yWK0ZL0Rs1x$xm8$2MTMS!8IK)2fZh}C2KaJ5Bs9#>FRut@l{49tVn+XVTP0OHLY zBORn;0;5KTJ8U1l)PC_I#YeZ{dzZ-V(5%^^36Nk$g8;(c6@b=$j2An+(v6|8@)f%L zQ92`ORvC9lDu!gFX?)l$_lU{^-sZVM63Qi8MF4o^99buOwnG~TzVxADj7Orw9zlJV z0w~(Z@Cbz13mzWPkBJ!K)HX;M2MxyT1Oy=(;MBG$i6r7O-S^Te5L=_@*rZL&#mf%lz0p1qcwi6x9V0Y{Ef)H^(+PY0 z{bnssag*qGKVH@vxmg=fVuHQi-J#g`A|T7nfU=|nDl7y|KLttpo?Yr#ldJ!^A1+1i&fFa|Yx^?I;KHID%j}ILi1eRA!lpVH2 zBr!iCYb&#(4?lf?{x1_MX|SYG2z+$t3$nO-c3{$a9*2ad8D!l2xpY@~TYKU!@hL zAUg2VDf~JhY*@T{^ied?QgQey&EKmGC12c~?U5`U`QdtO1zKP{{;VoFNV zQPmOIS3`wOINW#k+UcK#Fy|^jNmKBpd4QmGyq!ZoV{ECd;JkBy;Y*R#j)OR{(5qP8 z2@|Mq8A{_8h5owhVh~yPdwcH|IPVrf84yH(^csL`#2Z&@K6gFtkq!HfYWRMlzxE2b zE=bMh?@Rl_-Tm7T^)%tTMoWzek4%uP-w18-i+R_e)~w@on~^t3&4B;%(U&4bQ!tyG z0g zoJj~yWWc@x=O+Vpk#nt@b=?oX$#1~qCFT(P6{`%;+7D3f?X;Au_FtH^$i}t z*;*iyn*b-v0)bB3@c^t@zEFl2mS!lZNZ5HWgl@lw2oeJY@3V=(a(5W?9XiOU4HbnC z0I__Tini0tVtKmF$OFN!YRE9*n-8Na-r)&=)As6?#29t8B()kDcz)>7s~gs@CK&5GFb!{h78J!s&@)HE+V|U zCoj8N^W?(pT(6y);GV$k(BvEJ!BM3O(7OF0A%XG+0>bJISY0F_cIN@*?ZC4YIR1dx zdA(+~nxM2}2V`Ld!8b$*2w#OeI~0x%+T-gWgSCLNY7GkJfc6_=9=Z}Rl=62UGwMWV z5mPJ|@msYlkBO69etWl{@K7$GEo>Cn4uvXZV5vEPa3o$Cd;yk=_N`h{j4Y>I2|tD` z%nM2}0Bgi;TeY}YFMP|crQP0AzSV@Eriz!hYRx?i)NxKhqN7E>8*tAy>;}mRkj~t@ zWTXMU_tHn8EJQIL(8J?^&?YYod>Y^cJE)Vf+YUI^p^!ZaM9-sVI|PH{S$nsgG<%_^ z79i@cIB!4Q3GA{XK$A*PU@o=wz@mHceLAXSXKv6cI`DSa3aUG9AE^&-gW>2T)fhy&ZS%ru#_K6jrTa#*lp4v6i0V8vqqtHp=gw8V*0;TJ)K;enf<2G0 zvl-MAp;~zT3p4!_+sB9qZaq|UznwwAPkU)7aGGe^u4T2_k znt+hUK zquv@GU}7DqxON`Or{9+-lwDdvOnAhD>!>cbti%`W(#%Ylp#?Je6&dV&tOhba515SI zfLCS#mhW}rFUD@#rDYY$>wH8%D`?8{(A6Z4{@mkAC;&yO2pA=)2N$n^wc^4qyq*o; zBdPx&7&rm_ks`O#UG*3DaFJnkN}GtHswm#AC0~4-)lZ+G^cjB3f+bZVs%jGJcWb3} zeiZFz9Sc>=kxYyOL@C#VG2Z@!&At}+WjrA0*#mxg8V|s&dqFDe0L!8IvK&pr7|kYVyih1Ri=~~KH4;T0#IZKnVMj6q%xb!P6SD6aR5dS)WD$*wzIN(E&;?k z3|ReOz<80gS99l?FxHn&C^nTN%Q*%JU9n);^8sar7KR-Q*eX`+)vRcEj_01S;}Sn& zkuJa}@#J1Du|wuaOAsB0zd9~+sJ91ruWeiZ&l&GOe&!U|Ky}5 z6!&Bj`NDp=W)!pnq@zn@nAu_*Pxd0XSEz_&aczx!6ak8-2Zrf%C`d)cvpH&9N5Ql9 z#!c{k-&3K?1m@Qp5aO`F6Mw)1;0X_SVgleINCrgW1`KCR9X9yIcA{kr9IVqX=np!! zKpBq$O5YC3SO{nrfZfyzC|zMJ_WS4Ox`P|MK`;e)9SMC2lEg%z#j$=`8NGZK%6lCyq8{jw>v&Yk_(97#z5Jx z6)+E(CTujb-d4cuJ%LtD4w#I)I82W=lFE?2xad2y1L*`xl0(RYqVWLQ zfHskSMH@xq6Xif0Z4!Nq)?sjGX!Ijmm0FNOt8@=q2YrmT7Y$976HiCmkM2!{ z*Tc8za@C0$gz)+bv_0vV-S*6sKhQ@&bF-x+zC+uC zYIEf_9vUp$oq2NN6KLZpWr!T%2-=}E25t~@=R@j4D8Eo1!8K@8>7Qs-N`oIniC8DR z3J^4aMaDi*%t3@R5%h)~)C}>;bqb;S(sW=l2?-NMN{S9qCO=^=vWT9pm zMUgYGUa|C6Ejm6hOK$rUv`7hO%Pace9K32N4&ACHw#-<7QP|`~a=(kv`f2K7nFmi= zDn-6~xx7JbTR|uky|z*+%Ae5sY0PRVt0&hGUiF#0j_5Z!x1R9V8?hUSo+9y|TeXC; zE3THWlFhkBKEL)_`G!jRb+UaCt)KpDx4!Eoj@v5p^?T8drolHLPiJjAAX-I?*{{7W SzTL0oiP5)dk-~kOmi2$c`e@Gp From 298c50c20dd1627b955d0889cceec120ffd204b4 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Tue, 18 Jul 2017 13:54:49 -0400 Subject: [PATCH 04/22] 2017-07-18 Fred Gleason * Fixed a bug in the 'ListCuts web API call that caused incorrect and values to the returned. --- ChangeLog | 3 +++ lib/rdcut.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e5106932..74b69b0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15898,3 +15898,6 @@ accounts with a password containing one or more '$' characters to fail. 2017-07-17 Fred Gleason * Incremented the package version to 2.16.0int06_rfa00. +2017-07-18 Fred Gleason + * Fixed a bug in the 'ListCuts web API call that caused incorrect + and values to the returned. diff --git a/lib/rdcut.cpp b/lib/rdcut.cpp index 7b68175d..62e2a8b4 100644 --- a/lib/rdcut.cpp +++ b/lib/rdcut.cpp @@ -1496,7 +1496,7 @@ QString RDCut::xml(RDSqlQuery *q,bool absolute,RDSettings *settings) else { xml+=" "+RDXmlField("startPoint",0); xml+=" "+ - RDXmlField("endPoint",q->value(31).toInt()-q->value(59).toInt()); + RDXmlField("endPoint",q->value(60).toInt()-q->value(59).toInt()); if(q->value(61).toInt()<0) { xml+=" "+RDXmlField("fadeupPoint",-1); } From 9a8cea6f66673e7043672e2a42fc1e054fd70d62 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Tue, 18 Jul 2017 17:01:11 -0400 Subject: [PATCH 05/22] 2017-07-18 Fred Gleason * Incremented the package version to 2.16.0int06_rfa01. --- ChangeLog | 2 ++ PACKAGE_VERSION | 2 +- rivendell.ism | Bin 499284 -> 499284 bytes 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 74b69b0d..05dc3965 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15901,3 +15901,5 @@ 2017-07-18 Fred Gleason * Fixed a bug in the 'ListCuts web API call that caused incorrect and values to the returned. +2017-07-18 Fred Gleason + * Incremented the package version to 2.16.0int06_rfa01. diff --git a/PACKAGE_VERSION b/PACKAGE_VERSION index 7747dbcd..edd985d9 100644 --- a/PACKAGE_VERSION +++ b/PACKAGE_VERSION @@ -1 +1 @@ -2.16.0int06_rfa00 \ No newline at end of file +2.16.0int06_rfa01 \ No newline at end of file diff --git a/rivendell.ism b/rivendell.ism index df5cebb610b2af8c374713e2fee85b068ec98c0c..61d97b6bdb06f8714a37425657176c0ec4c98ec3 100644 GIT binary patch delta 18453 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 From e34497543375d2a8d00d880f668936faac969dec Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 07:20:07 -0400 Subject: [PATCH 06/22] 2017-07-28 Fred Gleason * Fixed a bug in 'lib/rdevent_line.cpp' that caused embedded traffic import events to be assigned incorrect link parameters when scheduled immediately after a voice track. --- ChangeLog | 4 ++++ lib/rdevent_line.cpp | 10 ++++++++-- lib/rdsvc.cpp | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05dc3965..a018622e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15903,3 +15903,7 @@ and values to the returned. 2017-07-18 Fred Gleason * Incremented the package version to 2.16.0int06_rfa01. +2017-07-28 Fred Gleason + * Fixed a bug in 'lib/rdevent_line.cpp' that caused embedded traffic + import events to be assigned incorrect link parameters when scheduled + immediately after a voice track. diff --git a/lib/rdevent_line.cpp b/lib/rdevent_line.cpp index eb73a12e..a28cbb0e 100644 --- a/lib/rdevent_line.cpp +++ b/lib/rdevent_line.cpp @@ -1040,8 +1040,14 @@ bool RDEventLine::linkLog(RDLogEvent *e,int next_id,const QString &svcname, logline->setTransType(trans_type); logline->setEventLength(event_length); logline->setLinkEventName(event_nested_event); - logline->setLinkStartTime(link_logline->linkStartTime()); - logline->setLinkLength(link_logline->linkLength()); + if((!q->value(12).isNull())&&(!q->value(13).isNull())) { + logline->setLinkStartTime(q->value(12).toTime()); + logline->setLinkLength(q->value(13).toInt()); + } + else { + logline->setLinkStartTime(link_logline->linkStartTime()); + logline->setLinkLength(link_logline->linkLength()); + } logline->setLinkStartSlop(link_logline->linkStartSlop()); logline->setLinkEndSlop(link_logline->linkEndSlop()); logline->setLinkId(link_logline->linkId()); diff --git a/lib/rdsvc.cpp b/lib/rdsvc.cpp index 3ada27e7..c74cf9b4 100644 --- a/lib/rdsvc.cpp +++ b/lib/rdsvc.cpp @@ -966,8 +966,8 @@ bool RDSvc::linkLog(RDSvc::ImportSource src,const QDate &date, emit generationProgress(24); delete src_event; delete dest_event; - // printf("Import Table: %s\n",(const char *)import_name); + // printf("Import Table: %s\n",(const char *)import_name); sql=QString().sprintf("drop table `%s`",(const char *)import_name); q=new RDSqlQuery(sql); delete q; From e9b46ea8736c19988178394e4ae3685b5dd844ce Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 07:48:38 -0400 Subject: [PATCH 07/22] 2017-07-28 Fred Gleason * Fixed a bug in 'lib/rdevent_line.cpp' that caused embedded traffic import events to be assigned incorrect link parameters when scheduled immediately after a voice track. --- ChangeLog | 4 ++++ lib/rdevent_line.cpp | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e532e85a..b8c8af3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15819,3 +15819,7 @@ 2017-06-02 Fred Gleason * Updated 'NEWS'. * Incremented the package version to 2.16.0. +2017-07-28 Fred Gleason + * Fixed a bug in 'lib/rdevent_line.cpp' that caused embedded traffic + import events to be assigned incorrect link parameters when scheduled + immediately after a voice track. diff --git a/lib/rdevent_line.cpp b/lib/rdevent_line.cpp index eb73a12e..a28cbb0e 100644 --- a/lib/rdevent_line.cpp +++ b/lib/rdevent_line.cpp @@ -1040,8 +1040,14 @@ bool RDEventLine::linkLog(RDLogEvent *e,int next_id,const QString &svcname, logline->setTransType(trans_type); logline->setEventLength(event_length); logline->setLinkEventName(event_nested_event); - logline->setLinkStartTime(link_logline->linkStartTime()); - logline->setLinkLength(link_logline->linkLength()); + if((!q->value(12).isNull())&&(!q->value(13).isNull())) { + logline->setLinkStartTime(q->value(12).toTime()); + logline->setLinkLength(q->value(13).toInt()); + } + else { + logline->setLinkStartTime(link_logline->linkStartTime()); + logline->setLinkLength(link_logline->linkLength()); + } logline->setLinkStartSlop(link_logline->linkStartSlop()); logline->setLinkEndSlop(link_logline->linkEndSlop()); logline->setLinkId(link_logline->linkId()); From 37468003cf55be9755f9f896974a4276cb7158d0 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 07:51:19 -0400 Subject: [PATCH 08/22] 2017-07-28 Fred Gleason * Incremented the package version to 2.16.0kxxo00. --- ChangeLog | 2 ++ PACKAGE_VERSION | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b8c8af3a..deac98a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15823,3 +15823,5 @@ * Fixed a bug in 'lib/rdevent_line.cpp' that caused embedded traffic import events to be assigned incorrect link parameters when scheduled immediately after a voice track. +2017-07-28 Fred Gleason + * Incremented the package version to 2.16.0kxxo00. diff --git a/PACKAGE_VERSION b/PACKAGE_VERSION index 79a00e9a..ae888143 100644 --- a/PACKAGE_VERSION +++ b/PACKAGE_VERSION @@ -1 +1 @@ -2.16.0 \ No newline at end of file +2.16.0kxxo00 \ No newline at end of file From 2b3919ff6cccd8aa397cf893527bb478c179c77e Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 09:09:56 -0400 Subject: [PATCH 09/22] 2017-07-28 Fred Gleason * Refactored the 'RDUser::authenticated()' method to eliminate use of rdauth(8). --- ChangeLog | 3 +++ lib/rduser.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index a018622e..0c2cd360 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15907,3 +15907,6 @@ * Fixed a bug in 'lib/rdevent_line.cpp' that caused embedded traffic import events to be assigned incorrect link parameters when scheduled immediately after a voice track. +2017-07-28 Fred Gleason + * Refactored the 'RDUser::authenticated()' method to eliminate use + of rdauth(8). diff --git a/lib/rduser.cpp b/lib/rduser.cpp index 4f049464..c3307af7 100644 --- a/lib/rduser.cpp +++ b/lib/rduser.cpp @@ -69,11 +69,11 @@ bool RDUser::authenticated(bool webuser) const } #ifndef WIN32 else { - QString cmd= - "rdauth "+pamService()+" "+RDEscapeShellString(user_name)+" "+ - RDEscapeShellString(user_password); - int exitcode=system(cmd); - return WEXITSTATUS(exitcode)==0; + bool ret=false; + RDPam *pam=new RDPam(pamService()); + ret=pam->authenticate(user_name,user_password); + delete pam; + return ret; } #endif // WIN32 return false; From 9438b440634f29dc141ab1a32780e74d723fd1c2 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 09:23:51 -0400 Subject: [PATCH 10/22] 2017-07-28 Fred Gleason * Removed rdauth(8). --- ChangeLog | 2 ++ configure.ac | 1 - rivendell.spec.in | 1 - utils/Makefile.am | 1 - utils/rdauth/Makefile.am | 49 ------------------------------- utils/rdauth/rdauth.cpp | 63 ---------------------------------------- utils/rdauth/rdauth.h | 42 --------------------------- 7 files changed, 2 insertions(+), 157 deletions(-) delete mode 100644 utils/rdauth/Makefile.am delete mode 100644 utils/rdauth/rdauth.cpp delete mode 100644 utils/rdauth/rdauth.h diff --git a/ChangeLog b/ChangeLog index 0c2cd360..0e7947ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15910,3 +15910,5 @@ 2017-07-28 Fred Gleason * Refactored the 'RDUser::authenticated()' method to eliminate use of rdauth(8). +2017-07-28 Fred Gleason + * Removed rdauth(8). diff --git a/configure.ac b/configure.ac index 8fdb3ca1..9b02cc58 100644 --- a/configure.ac +++ b/configure.ac @@ -470,7 +470,6 @@ AC_CONFIG_FILES([rivendell.spec \ cae/Makefile \ utils/Makefile \ utils/rdalsaconfig/Makefile \ - utils/rdauth/Makefile \ utils/rdcheckcuts/Makefile \ utils/rdchunk/Makefile \ utils/rdcleandirs/Makefile \ diff --git a/rivendell.spec.in b/rivendell.spec.in index fa43b1c7..7212ccd1 100644 --- a/rivendell.spec.in +++ b/rivendell.spec.in @@ -212,7 +212,6 @@ rm -rf $RPM_BUILD_ROOT @LOCAL_PREFIX@/@RD_LIB_PATH@/rivendell/*.rlm @LOCAL_PREFIX@/bin/rdadmin @LOCAL_PREFIX@/bin/rdairplay -%attr(6755,root,root)@LOCAL_PREFIX@/bin/rdauth @LOCAL_PREFIX@/bin/rdpanel @LOCAL_PREFIX@/bin/rdcartslots @LOCAL_PREFIX@/bin/rdcatch diff --git a/utils/Makefile.am b/utils/Makefile.am index 9cb9a543..eb60ceda 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -28,7 +28,6 @@ if ALSA_RD_AM endif SUBDIRS = $(ALSACONFIG_RD_OPT)\ $(HPIINFO_RD_OPT)\ - rdauth\ rddbcheck\ rddgimport\ rdcheckcuts\ diff --git a/utils/rdauth/Makefile.am b/utils/rdauth/Makefile.am deleted file mode 100644 index 141b7a84..00000000 --- a/utils/rdauth/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -## automake.am -## -## Automake.am for rivendell/utils/rdauth -## -## (C) Copyright 2017 Fred Gleason -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License version 2 as -## published by the Free Software Foundation. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public -## License along with this program; if not, write to the Free Software -## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -## -## Use automake to process this into a Makefile.in - -AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib -LIBS = @QT_LIBS@ -L$(top_srcdir)/lib -MOC = @QT_MOC@ - -# The dependency for qt's Meta Object Compiler (moc) -moc_%.cpp: %.h - $(MOC) $< -o $@ - -install-exec-hook: - if test -z $(DESTDIR) ; then chown root $(DESTDIR)$(prefix)/bin/rdauth ; chmod 4755 $(DESTDIR)$(prefix)/bin/rdauth ; fi - -bin_PROGRAMS = rdauth - -dist_rdauth_SOURCES = rdauth.cpp rdauth.h - -rdauth_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ - -CLEANFILES = *~\ - *.idb\ - *ilk\ - *.obj\ - *.pdb\ - *.qm\ - moc_* - -MAINTAINERCLEANFILES = *~\ - Makefile.in\ - moc_* diff --git a/utils/rdauth/rdauth.cpp b/utils/rdauth/rdauth.cpp deleted file mode 100644 index 3259a6f3..00000000 --- a/utils/rdauth/rdauth.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// rdauth.cpp -// -// Authenticate against a PAM service. -// -// (C) Copyright 2017 Fred Gleason -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#include - -#include - -#include "rdauth.h" - -MainObject::MainObject(QObject *parent) - :QObject(parent) -{ - // - // Read Command Options - // - QString service_name; - QString user; - QString password=""; - RDCmdSwitch *cmd= - new RDCmdSwitch(qApp->argc(),qApp->argv(),"rdauth",RDAUTH_USAGE); - if(cmd->keys()==3) { - password=cmd->key(2); - } - else { - if(cmd->keys()!=2) { - fprintf(stderr,"rdauth: invalid arguments\n"); - exit(256); - } - } - service_name=cmd->key(0); - user=cmd->key(1); - - RDPam *pam=new RDPam(service_name); - if(pam->authenticate(user,password)) { - exit(0); - } - exit(1); -} - - -int main(int argc,char *argv[]) -{ - QApplication a(argc,argv,false); - new MainObject(); - return a.exec(); -} diff --git a/utils/rdauth/rdauth.h b/utils/rdauth/rdauth.h deleted file mode 100644 index b38bc8d0..00000000 --- a/utils/rdauth/rdauth.h +++ /dev/null @@ -1,42 +0,0 @@ -// rdauth.h -// -// Authenticate against a PAM service. -// -// (C) Copyright 2017 Fred Gleason -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#ifndef RDAUTH_H -#define RDAUTH_H - -#include - -#include -#include - -#include -#include -#include - -#define RDAUTH_USAGE "\n" - -class MainObject : public QObject -{ - public: - MainObject(QObject *parent=0); -}; - - -#endif // RDAUTH_H From 96a6640a7e90d700b7c09769c5eb0065851725b3 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 16:34:00 -0400 Subject: [PATCH 11/22] 2017-07-28 Fred Gleason * Fixed a bug in 'lib/rdevent_line.cpp' that caused an embedded traffic import event to be assigned incorrect link parameters when scheduled at midnight. --- ChangeLog | 4 ++++ lib/rdevent_line.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index deac98a8..f2bec7f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15825,3 +15825,7 @@ immediately after a voice track. 2017-07-28 Fred Gleason * Incremented the package version to 2.16.0kxxo00. +2017-07-28 Fred Gleason + * Fixed a bug in 'lib/rdevent_line.cpp' that caused an embedded traffic + import event to be assigned incorrect link parameters when scheduled + at midnight. diff --git a/lib/rdevent_line.cpp b/lib/rdevent_line.cpp index a28cbb0e..86298e16 100644 --- a/lib/rdevent_line.cpp +++ b/lib/rdevent_line.cpp @@ -977,7 +977,7 @@ bool RDEventLine::linkLog(RDLogEvent *e,int next_id,const QString &svcname, logline->setTransType(trans_type); logline->setEventLength(event_length); logline->setLinkEventName(event_nested_event); - if((!q->value(12).isNull())&&(!q->value(13).isNull())) { + if(!q->value(13).isNull()) { logline->setLinkStartTime(q->value(12).toTime()); logline->setLinkLength(q->value(13).toInt()); } @@ -1040,7 +1040,7 @@ bool RDEventLine::linkLog(RDLogEvent *e,int next_id,const QString &svcname, logline->setTransType(trans_type); logline->setEventLength(event_length); logline->setLinkEventName(event_nested_event); - if((!q->value(12).isNull())&&(!q->value(13).isNull())) { + if(!q->value(13).isNull()) { logline->setLinkStartTime(q->value(12).toTime()); logline->setLinkLength(q->value(13).toInt()); } From 0da427b1015f18e24a9e453bbb07e8bc1e2f0812 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 28 Jul 2017 16:37:13 -0400 Subject: [PATCH 12/22] 2017-07-28 Fred Gleason * Incremented the package version to 2.16.0kxxo01. --- ChangeLog | 2 ++ PACKAGE_VERSION | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f2bec7f7..ff92c74f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15829,3 +15829,5 @@ * Fixed a bug in 'lib/rdevent_line.cpp' that caused an embedded traffic import event to be assigned incorrect link parameters when scheduled at midnight. +2017-07-28 Fred Gleason + * Incremented the package version to 2.16.0kxxo01. diff --git a/PACKAGE_VERSION b/PACKAGE_VERSION index ae888143..5599ce01 100644 --- a/PACKAGE_VERSION +++ b/PACKAGE_VERSION @@ -1 +1 @@ -2.16.0kxxo00 \ No newline at end of file +2.16.0kxxo01 \ No newline at end of file From 39c8eb4d58f6f54b960283fa6d29340013cb8c27 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Tue, 1 Aug 2017 09:01:10 -0400 Subject: [PATCH 13/22] 2017-08-01 Fred Gleason * Fixed a bug in 'rdlogmanager/edit_grid.cpp' to broke functioning of the 'Clear Hour' item in the right-click menu. --- ChangeLog | 3 +++ rdlogmanager/edit_grid.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 465f91c1..85bd8b9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15916,3 +15916,6 @@ * Fixed a bug in 'lib/rdevent_line.cpp' that caused an embedded traffic import event to be assigned incorrect link parameters when scheduled at midnight. +2017-08-01 Fred Gleason + * Fixed a bug in 'rdlogmanager/edit_grid.cpp' to broke functioning of + the 'Clear Hour' item in the right-click menu. diff --git a/rdlogmanager/edit_grid.cpp b/rdlogmanager/edit_grid.cpp index 4ffd6209..272c736d 100644 --- a/rdlogmanager/edit_grid.cpp +++ b/rdlogmanager/edit_grid.cpp @@ -264,9 +264,10 @@ void EditGrid::clearHourData() { int dayofweek=edit_rightclick_id/24+1; int hour=edit_rightclick_id-24*(dayofweek-1); + QString sql=QString("update SERVICE_CLOCKS set CLOCK_NAME=null where ")+ "(SERVICE_NAME=\""+RDEscapeString(edit_servicename)+"\")&&"+ - QString().sprintf("HOUR=%d)",hour); + QString().sprintf("(HOUR=%d)",(dayofweek-1)*24+hour); RDSqlQuery *q=new RDSqlQuery(sql); delete q; LabelButton(dayofweek,hour,""); From 32186e03167111fea99a511ae48b76eb0bcb12ef Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Wed, 2 Aug 2017 12:02:40 -0400 Subject: [PATCH 14/22] 2017-08-02 Fred Gleason * Refactored the algorithm for calculating web tickets in 'web/rdxport/rdxport.cpp'. --- ChangeLog | 3 +++ web/rdxport/rdxport.cpp | 24 +++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 85bd8b9b..c1e813fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15919,3 +15919,6 @@ 2017-08-01 Fred Gleason * Fixed a bug in 'rdlogmanager/edit_grid.cpp' to broke functioning of the 'Clear Hour' item in the right-click menu. +2017-08-02 Fred Gleason + * Refactored the algorithm for calculating web tickets in + 'web/rdxport/rdxport.cpp'. diff --git a/web/rdxport/rdxport.cpp b/web/rdxport/rdxport.cpp index 3f0dc4b2..af1ba3f8 100644 --- a/web/rdxport/rdxport.cpp +++ b/web/rdxport/rdxport.cpp @@ -18,6 +18,7 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // +#include #include #include #include @@ -355,23 +356,32 @@ void Xport::TryCreateTicket(const QString &name) QString ticket; QString passwd; int command; - unsigned char rawstr[1024]; + char rawstr[1024]; unsigned char sha1[SHA_DIGEST_LENGTH]; QString sql; RDSqlQuery *q; if(xport_post->getValue("COMMAND",&command)) { if(command==RDXPORT_COMMAND_CREATETICKET) { - QDateTime now=QDateTime::currentDateTime(); - snprintf((char *)rawstr,1024,"%s %s %s", - (const char *)now.toString("yyyy-MM-dd hh:mm:ss.zzz"), - (const char *)name, - (const char *)xport_post->clientAddress().toString()); - SHA1(rawstr,strlen((char *)rawstr),sha1); + struct timeval tv; + memset(&tv,0,sizeof(tv)); + gettimeofday(&tv,NULL); + srandom(tv.tv_usec); + for(int i=0;i<5;i++) { + long r=random(); + unsigned ipv4_addr=xport_post->clientAddress().toIPv4Address(); + snprintf(rawstr+i*8,8,"%c%c%c%c%c%c%c%c", + 0xff&((int)r>>24),0xff&(ipv4_addr>>24), + 0xff&((int)r>>16),0xff&(ipv4_addr>>16), + 0xff&((int)r>>8),0xff&(ipv4_addr>>8), + 0xff&(int)r,0xff&ipv4_addr); + } + SHA1((const unsigned char *)rawstr,40,sha1); ticket=""; for(int i=0;i Date: Thu, 3 Aug 2017 09:11:45 -0400 Subject: [PATCH 15/22] 2017-08-03 Fred Gleason * Added an 'rlm_urlwrite' RLM in 'rlm/rlm_urlwrite.c'. --- ChangeLog | 2 + conf/Makefile.am | 1 + conf/rlm_urlwrite.conf | 74 +++++++++++++ rivendell.spec.in | 1 + rlm/Makefile-example | 4 +- rlm/Makefile.am | 4 +- rlm/rlm_urlwrite.c | 239 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 conf/rlm_urlwrite.conf create mode 100644 rlm/rlm_urlwrite.c diff --git a/ChangeLog b/ChangeLog index c1e813fe..5d1c14e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15922,3 +15922,5 @@ 2017-08-02 Fred Gleason * Refactored the algorithm for calculating web tickets in 'web/rdxport/rdxport.cpp'. +2017-08-03 Fred Gleason + * Added an 'rlm_urlwrite' RLM in 'rlm/rlm_urlwrite.c'. diff --git a/conf/Makefile.am b/conf/Makefile.am index c6f3ac38..358171e2 100644 --- a/conf/Makefile.am +++ b/conf/Makefile.am @@ -51,6 +51,7 @@ EXTRA_DIST = my.cnf-master\ rlm_tagstation.conf\ rlm_twitter.conf\ rlm_udp.conf\ + rlm_urlwrite.conf\ rlm_walltime.conf\ rlm_xds.conf\ rlm_xmpad.conf diff --git a/conf/rlm_urlwrite.conf b/conf/rlm_urlwrite.conf new file mode 100644 index 00000000..1da75628 --- /dev/null +++ b/conf/rlm_urlwrite.conf @@ -0,0 +1,74 @@ +; rlm_urlwrite.conf +; +; This is the sample configuration file for the 'rlm_urlwrite' RLM for +; Rivendell, which can be used to send one or more files to a local or +; remote system using Now & Next data. +; +; To enable this module, add it to the 'Loadable Modules' list in +; RDAdmin->ManageHosts->RDAirPlay->ConfigureNow&Next. The 'Argument' +; field should point to the location of this file. + +; Section Header +; +; One section per file to be written should be configured, starting with +; 'File1' and working up consecutively +[Url1] + +; Url +; +; The URL to which to send the file. The follow URL schemes are recognized: +; file:// +; ftp:// +; http:// (uses the PUT method) +; sftp:// +; +Url=sftp://server.example.com/myfile.txt + +; Username +; +; The username to be used when authenticating to the remote server. +; +Username=someuser + +; Password +; +; The password to be used when authenticating to the remote server. +Password=hackme + +; Format String. The string to be sent each time RDAirPlay changes +; play state, including any wildcards as placeholders for metadata values. +; +; The list of available wildcards can be found in the 'metadata_wildcards.txt' +; file in the Rivendell documentation directory. +; +FormatString=NOW: %d(ddd MMM d hh:mm:ss yyyy): %t - %a\nNEXT: %D(ddd MMM d hh:mm:ss yyyy): %T - %A\n + +; Encoding. Defines the set of escapes to be applied to the PAD fields. +; The following options are available: +; +; 0 - Perform no character escaping. +; 1 - "XML" escaping: Escape reserved characters as per XML-v1.0 +; 2 - "Web" escaping: Escape reserved characters as per RFC 2396 Section 2.4 +Encoding=0 + +; Log Selection +; +; Set the status for each log to 'Yes', 'No' or 'Onair' to indicate whether +; state changes on that log should be output. If set to 'Onair', then +; output will be generated only if RDAirPlays OnAir flag is active. +MasterLog=Yes +Aux1Log=Yes +Aux2Log=Yes + + +; Additional files can be written by adding new sections... +; +;[Url2] +;Url=file:///home/rd/somefile.txt +;Username=janedoe +;Password=crackme +;FormatString=%t by %a\r\n +;Encoding=0 +;MasterLog=Yes +;Aux1Log=No +;Aux2Log=Onair diff --git a/rivendell.spec.in b/rivendell.spec.in index 7212ccd1..6826f917 100644 --- a/rivendell.spec.in +++ b/rivendell.spec.in @@ -423,6 +423,7 @@ rm -rf $RPM_BUILD_ROOT %doc conf/rlm_shoutcast1.conf %doc conf/rlm_spottrap.conf %doc conf/rlm_filewrite.conf +%doc conf/rlm_urlwrite.conf %doc conf/rlm_spinitron_plus.conf %doc conf/rlm_tagstation.conf %doc docs/implemented_macros.txt diff --git a/rlm/Makefile-example b/rlm/Makefile-example index 71695965..100eec30 100644 --- a/rlm/Makefile-example +++ b/rlm/Makefile-example @@ -2,7 +2,7 @@ ## ## An example Makefile for building Rivendell Loadable Modules ## -## (C) Copyright 2008-2013 Fred Gleason +## (C) Copyright 2008-2017 Fred Gleason ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU Library General Public License @@ -20,6 +20,7 @@ OBJS = rlm_ando.rlm\ rlm_facebook.rlm\ + rlm_filewrite.rlm\ rlm_icecast2.rlm\ rlm_inno713.rlm\ rlm_liqcomp.rlm\ @@ -33,6 +34,7 @@ OBJS = rlm_ando.rlm\ rlm_test.rlm\ rlm_twitter.rlm\ rlm_udp.rlm \ + rlm_urlwrite.rlm\ rlm_walltime.rlm\ rlm_xmpad.rlm diff --git a/rlm/Makefile.am b/rlm/Makefile.am index a9eaf001..86abe35d 100644 --- a/rlm/Makefile.am +++ b/rlm/Makefile.am @@ -2,7 +2,7 @@ ## ## Automake.am for rivendell/rlm ## -## (C) Copyright 2008,2016 Fred Gleason +## (C) Copyright 2008,2016-2017 Fred Gleason ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License version 2 as @@ -37,6 +37,7 @@ RLM_MODULES=rlm_ando.rlm\ rlm_test.rlm\ rlm_twitter.rlm\ rlm_udp.rlm\ + rlm_urlwrite.rlm\ rlm_walltime.rlm\ rlm_xds.rlm\ rlm_xmpad.rlm @@ -76,6 +77,7 @@ EXTRA_DIST = Makefile-example\ rlm_test.c\ rlm_twitter.c\ rlm_udp.c\ + rlm_urlwrite.c\ rlm_walltime.c\ rlm_xds.c\ rlm_xmpad.c diff --git a/rlm/rlm_urlwrite.c b/rlm/rlm_urlwrite.c new file mode 100644 index 00000000..def7e5f5 --- /dev/null +++ b/rlm/rlm_urlwrite.c @@ -0,0 +1,239 @@ +/* rlm_urlwrite.c + * + * (C) Copyright 2012 Fred Gleason + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This is a Rivendell Loadable Module. It uses Now&Next PAD data + * to write to one or more file(s) on the local system specified in the + * configuration file pointed to by the plugin argument. + * + * To compile this module, just do: + * + * gcc -shared -o rlm_urlwrite.rlm rlm_urlwrite.c + */ + +#include +#include +#include +#include +#include +#include + +#include + +int rlm_urlwrite_devs; +char *rlm_urlwrite_urls; +char *rlm_urlwrite_usernames; +char *rlm_urlwrite_passwords; +char *rlm_urlwrite_formats; +int *rlm_urlwrite_encodings; +int *rlm_urlwrite_masters; +int *rlm_urlwrite_aux1s; +int *rlm_urlwrite_aux2s; + +void rlm_urlwrite_ReplaceChar(char c,char *str,int pos) +{ + int i; + + str[pos]=c; + for(i=pos+1;i0) { + rlm_urlwrite_urls=realloc(rlm_urlwrite_urls, + (rlm_urlwrite_devs+1)*(rlm_urlwrite_devs+1)*256); + strcpy(rlm_urlwrite_urls+256*rlm_urlwrite_devs,url); + rlm_urlwrite_usernames=realloc(rlm_urlwrite_usernames,(rlm_urlwrite_devs+1)*256); + strncpy(rlm_urlwrite_usernames+256*rlm_urlwrite_devs, + RLMGetStringValue(ptr,arg,section,"Username",""),256); + rlm_urlwrite_passwords=realloc(rlm_urlwrite_passwords,(rlm_urlwrite_devs+1)*256); + strncpy(rlm_urlwrite_passwords+256*rlm_urlwrite_devs, + RLMGetStringValue(ptr,arg,section,"Password",""),256); + rlm_urlwrite_formats=realloc(rlm_urlwrite_formats,(rlm_urlwrite_devs+1)*8192); + strncpy(rlm_urlwrite_formats+8192*rlm_urlwrite_devs, + RLMGetStringValue(ptr,arg,section,"FormatString",""),8192); + rlm_urlwrite_masters=realloc(rlm_urlwrite_masters, + (rlm_urlwrite_devs+1)*sizeof(int)); + rlm_urlwrite_masters[rlm_urlwrite_devs]= + rlm_urlwrite_GetLogStatus(ptr,arg,section,"MasterLog"); + + rlm_urlwrite_encodings=realloc(rlm_urlwrite_encodings, + (rlm_urlwrite_devs+1)*sizeof(int)); + rlm_urlwrite_encodings[rlm_urlwrite_devs]= + RLMGetIntegerValue(ptr,arg,section,"Encoding",RLM_ENCODE_NONE); + rlm_urlwrite_aux1s=realloc(rlm_urlwrite_aux1s, + (rlm_urlwrite_devs+1)*sizeof(int)); + rlm_urlwrite_aux1s[rlm_urlwrite_devs]= + rlm_urlwrite_GetLogStatus(ptr,arg,section,"Aux1Log"); + rlm_urlwrite_aux2s=realloc(rlm_urlwrite_aux2s, + (rlm_urlwrite_devs+1)*sizeof(int)); + rlm_urlwrite_aux2s[rlm_urlwrite_devs]= + rlm_urlwrite_GetLogStatus(ptr,arg,section,"Aux2Log"); + sprintf(errtext,"rlm_urlwrite: configured URL \"%s\"", + rlm_urlwrite_urls+256*rlm_urlwrite_devs); + rlm_urlwrite_devs++; + RLMLog(ptr,LOG_INFO,errtext); + sprintf(section,"Url%d",i++); + strncpy(url,RLMGetStringValue(ptr,arg,section,"Url",""),255); + url[255]=0; + } +} + + +void rlm_urlwrite_RLMFree(void *ptr) +{ + free(rlm_urlwrite_urls); + free(rlm_urlwrite_usernames); + free(rlm_urlwrite_passwords); + free(rlm_urlwrite_formats); + free(rlm_urlwrite_encodings); + free(rlm_urlwrite_masters); + free(rlm_urlwrite_aux1s); + free(rlm_urlwrite_aux2s); +} + + +void rlm_urlwrite_RLMPadDataSent(void *ptr,const struct rlm_svc *svc, + const struct rlm_log *log, + const struct rlm_pad *now, + const struct rlm_pad *next) +{ + int i; + int flag=0; + char str[8192]; + char msg[1500]; + char account[1024]; + char tempfile[1024]; + FILE *f; + + for(i=0;ilog_mach) { + case 0: + flag=rlm_urlwrite_masters[i]; + break; + + case 1: + flag=rlm_urlwrite_aux1s[i]; + break; + + case 2: + flag=rlm_urlwrite_aux2s[i]; + break; + } + if((flag==1)||((flag==2)&&(log->log_onair!=0))) { + strncpy(str,RLMResolveNowNextEncoded(ptr,now,next, + rlm_urlwrite_formats+8192*i, + rlm_urlwrite_encodings[i]),8192); + rlm_urlwrite_ProcessString(str); + snprintf(account,1024,"%s:%s",rlm_urlwrite_usernames+256*i, + rlm_urlwrite_passwords+256*i); + snprintf(tempfile,1024,"/tmp/rlm_urlwrite_%d",i); + f=fopen(tempfile,"w"); + if(f!=NULL) { + snprintf(msg,1500,"rlm_urlwrite: sending pad update: \"%s\" to \"%s\"", + str,rlm_urlwrite_urls+256*i); + fprintf(f,"%s",str); + fclose(f); + if(fork()==0) { + execlp("curl","curl","-s","-k","-u",account,"-T",tempfile, + rlm_urlwrite_urls+256*i,(char *)NULL); + RLMLog(ptr,LOG_WARNING,"rlm_urlwrite: unable to execute curl(1)"); + exit(0); + } + RLMLog(ptr,LOG_INFO,msg); + } + else { + snprintf(msg,1500,"rlm_urlwrite: unable to open file \"%s\"", + rlm_urlwrite_urls+256*i); + RLMLog(ptr,LOG_WARNING,msg); + } + } + } +} From 81c5377fb36f2a83c8a93ba80df7a47ae7e21e35 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Thu, 3 Aug 2017 09:20:07 -0400 Subject: [PATCH 16/22] 2017-08-03 Fred Gleason * Increased the length of the 'Formats=' parameter in the 'rlm_filewrite' RLM from 256 to 8192 characters. --- ChangeLog | 3 +++ rlm/rlm_filewrite.c | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d1c14e0..010ad81d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15924,3 +15924,6 @@ 'web/rdxport/rdxport.cpp'. 2017-08-03 Fred Gleason * Added an 'rlm_urlwrite' RLM in 'rlm/rlm_urlwrite.c'. +2017-08-03 Fred Gleason + * Increased the length of the 'Formats=' parameter in the + 'rlm_filewrite' RLM from 256 to 8192 characters. diff --git a/rlm/rlm_filewrite.c b/rlm/rlm_filewrite.c index d3c02841..9803c285 100644 --- a/rlm/rlm_filewrite.c +++ b/rlm/rlm_filewrite.c @@ -132,9 +132,9 @@ void rlm_filewrite_RLMStart(void *ptr,const char *arg) (rlm_filewrite_devs+1)*sizeof(int)); rlm_filewrite_appends[rlm_filewrite_devs]= RLMGetIntegerValue(ptr,arg,section,"Append",0); - rlm_filewrite_formats=realloc(rlm_filewrite_formats,(rlm_filewrite_devs+1)*256); - strncpy(rlm_filewrite_formats+256*rlm_filewrite_devs, - RLMGetStringValue(ptr,arg,section,"FormatString",""),256); + rlm_filewrite_formats=realloc(rlm_filewrite_formats,(rlm_filewrite_devs+1)*8192); + strncpy(rlm_filewrite_formats+8192*rlm_filewrite_devs, + RLMGetStringValue(ptr,arg,section,"FormatString",""),8192); rlm_filewrite_masters=realloc(rlm_filewrite_masters, (rlm_filewrite_devs+1)*sizeof(int)); rlm_filewrite_masters[rlm_filewrite_devs]= @@ -202,7 +202,7 @@ void rlm_filewrite_RLMPadDataSent(void *ptr,const struct rlm_svc *svc, } if((flag==1)||((flag==2)&&(log->log_onair!=0))) { strncpy(str,RLMResolveNowNextEncoded(ptr,now,next, - rlm_filewrite_formats+256*i, + rlm_filewrite_formats+8192*i, rlm_filewrite_encodings[i]),8192); rlm_filewrite_ProcessString(str); if(rlm_filewrite_appends[i]==0) { From 98e9c89dec0c71b59faa6f41fb53dfa66e6162d8 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Mon, 7 Aug 2017 11:11:40 -0400 Subject: [PATCH 17/22] 2017-08-07 Fred Gleason * Incremented the package version to 2.16.0int06_rfa02. --- ChangeLog | 2 ++ PACKAGE_VERSION | 2 +- rivendell.ism | Bin 499284 -> 499284 bytes 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 010ad81d..c72fd4bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15927,3 +15927,5 @@ 2017-08-03 Fred Gleason * Increased the length of the 'Formats=' parameter in the 'rlm_filewrite' RLM from 256 to 8192 characters. +2017-08-07 Fred Gleason + * Incremented the package version to 2.16.0int06_rfa02. diff --git a/PACKAGE_VERSION b/PACKAGE_VERSION index edd985d9..1b74c8e9 100644 --- a/PACKAGE_VERSION +++ b/PACKAGE_VERSION @@ -1 +1 @@ -2.16.0int06_rfa01 \ No newline at end of file +2.16.0int06_rfa02 \ No newline at end of file diff --git a/rivendell.ism b/rivendell.ism index 61d97b6bdb06f8714a37425657176c0ec4c98ec3..90b7697e1f0e62269e6ad7398bb95e0d87d2bf74 100644 GIT binary patch delta 16893 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 delta 18548 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 Date: Sat, 12 Aug 2017 16:50:49 -0400 Subject: [PATCH 18/22] 2017-08-12 Fred Gleason * Implemented a driver for WheatNet SLIO devices. --- ChangeLog | 2 + docs/SWITCHERS.txt | 15 ++ lib/rdmatrix.cpp | 13 +- lib/rdmatrix.h | 2 +- ripcd/Makefile.am | 6 +- ripcd/loaddrivers.cpp | 7 +- ripcd/wheatnet_slio.cpp | 370 ++++++++++++++++++++++++++++++++++++++++ ripcd/wheatnet_slio.h | 81 +++++++++ 8 files changed, 489 insertions(+), 7 deletions(-) create mode 100644 ripcd/wheatnet_slio.cpp create mode 100644 ripcd/wheatnet_slio.h diff --git a/ChangeLog b/ChangeLog index c72fd4bf..a65ebaf6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15929,3 +15929,5 @@ 'rlm_filewrite' RLM from 256 to 8192 characters. 2017-08-07 Fred Gleason * Incremented the package version to 2.16.0int06_rfa02. +2017-08-12 Fred Gleason + * Implemented a driver for WheatNet SLIO devices. diff --git a/docs/SWITCHERS.txt b/docs/SWITCHERS.txt index db7935e5..286a83a9 100644 --- a/docs/SWITCHERS.txt +++ b/docs/SWITCHERS.txt @@ -37,6 +37,7 @@ Sine Systems ACU-1 (Prophet version) Software Authority Protocol StarGuide III Satellite Receiver Wegener Unity4000 DVB Satellite Receiver +WheatNet Blade SLIO See the sections below for notes on each specific model. @@ -851,4 +852,18 @@ output at a time. Commanding a stream to an output will cause that stream to be silently deselected from a previously selected output. +---------------------------------------------------------------------------- +WHEATNET BLADE SLIO + +Driver Name: WheatNet SLIO + +Supported RML Commands: + GPO Set ('GO') + +GENERAL NOTES: +Control is done by means of a TCP/IP connection to port 55776 on a blade. +The only required configuration parameters are IP Address and IP Port. +The number of pins is auto-detected at driver startup. + + ---------------------------------------------------------------------------- diff --git a/lib/rdmatrix.cpp b/lib/rdmatrix.cpp index e9782744..f80a037b 100644 --- a/lib/rdmatrix.cpp +++ b/lib/rdmatrix.cpp @@ -68,7 +68,8 @@ bool __mx_primary_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT ADMS 44.22 {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR {0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // Modbus - {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // Kernel GPIO + {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // Kernel GPIO + {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // WheatNet SLIO }; bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= { @@ -113,7 +114,8 @@ bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT ADMS 44.22 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Modbus - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Kernel GPIO + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Kernel GPIO + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // WheatNet SLIO }; int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= @@ -159,7 +161,8 @@ int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,8,2,16,13,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT ADMS 44.22 {0,0,0,0,0,0,0,0,0,0,0,4,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT SS 4.1 MLR {1,0,0,502,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Modbus - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // Kernel GPIO + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Kernel GPIO + {1,0,0,55776,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // WheatNet SLIO }; RDMatrix::RDMatrix(const QString &station,int matrix) @@ -731,6 +734,10 @@ QString RDMatrix::typeString(RDMatrix::Type type) return QString("Kernel GPIO"); break; + case RDMatrix::WheatnetSlio: + return QString("WheatNet SLIO"); + break; + default: return QString("Unknown Type"); break; diff --git a/lib/rdmatrix.h b/lib/rdmatrix.h index e7319ee3..4774dca0 100644 --- a/lib/rdmatrix.h +++ b/lib/rdmatrix.h @@ -38,7 +38,7 @@ class RDMatrix BtSrc16=24,Harlond=25,Acu1p=26,LiveWireMcastGpio=27,Am16=28, LiveWireLwrpGpio=29,BtSentinel4Web=30,BtGpi16=31,ModemLines=32, SoftwareAuthority=33,Sas16000=34,RossNkScp=35,BtAdms4422=36, - BtSs41Mlr=37,Modbus=38,KernelGpio=39,LastType=40}; + BtSs41Mlr=37,Modbus=38,KernelGpio=39,WheatnetSlio=40,LastType=41}; enum Endpoint {Input=0,Output=1}; enum Mode {Stereo=0,Left=1,Right=2}; enum VguestAttribute {VguestEngine=0,VguestDevice=1,VguestSurface=2, diff --git a/ripcd/Makefile.am b/ripcd/Makefile.am index df5610a8..479a59ed 100644 --- a/ripcd/Makefile.am +++ b/ripcd/Makefile.am @@ -76,7 +76,8 @@ dist_ripcd_SOURCES = acu1p.cpp acu1p.h\ switcher.cpp switcher.h\ unity4000.cpp unity4000.h\ unity_feed.cpp unity_feed.h\ - vguest.cpp vguest.h + vguest.cpp vguest.h\ + wheatnet_slio.cpp wheatnet_slio.h nodist_ripcd_SOURCES = moc_am16.cpp\ moc_acu1p.cpp\ @@ -118,7 +119,8 @@ nodist_ripcd_SOURCES = moc_am16.cpp\ moc_swauthority.cpp\ moc_switcher.cpp\ moc_unity4000.cpp\ - moc_vguest.cpp + moc_vguest.cpp\ + moc_wheatnet_slio.cpp ripcd_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ diff --git a/ripcd/loaddrivers.cpp b/ripcd/loaddrivers.cpp index 3a48e96d..64aa9c63 100644 --- a/ripcd/loaddrivers.cpp +++ b/ripcd/loaddrivers.cpp @@ -2,7 +2,7 @@ // // Load Switcher drivers for ripcd(8) // -// (C) Copyright 2002-2016 Fred Gleason +// (C) Copyright 2002-2017 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -61,6 +61,7 @@ #include #include #include +#include bool MainObject::LoadSwitchDriver(int matrix_num) { @@ -219,6 +220,10 @@ bool MainObject::LoadSwitchDriver(int matrix_num) ripcd_switcher[matrix_num]=new Unity4000(matrix,this); break; + case RDMatrix::WheatnetSlio: + ripcd_switcher[matrix_num]=new WheatnetSlio(matrix,this); + break; + default: ripcd_switcher[matrix_num]=NULL; delete matrix; diff --git a/ripcd/wheatnet_slio.cpp b/ripcd/wheatnet_slio.cpp new file mode 100644 index 00000000..5ab9eb35 --- /dev/null +++ b/ripcd/wheatnet_slio.cpp @@ -0,0 +1,370 @@ +// wheatnet_slio.cpp +// +// A Rivendell switcher driver for Modbus TCP +// +// (C) Copyright 2017 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include + +#include +#include + +#include "wheatnet_slio.h" + +WheatnetSlio::WheatnetSlio(RDMatrix *matrix,QObject *parent) + : Switcher(matrix,parent) +{ + slio_watchdog_active=false; + + slio_gpios=0; + slio_ip_address=matrix->ipAddress(RDMatrix::Primary); + slio_ip_port=matrix->ipPort(RDMatrix::Primary); + + slio_socket=new QSocket(this); + connect(slio_socket,SIGNAL(connected()),this,SLOT(connectedData())); + connect(slio_socket,SIGNAL(readyRead()),this,SLOT(readyReadData())); + connect(slio_socket,SIGNAL(error(int)),this,SLOT(errorData(int))); + slio_socket->connectToHost(slio_ip_address.toString(),slio_ip_port); + + slio_poll_timer=new QTimer(this); + connect(slio_poll_timer,SIGNAL(timeout()),this,SLOT(pollInputs())); + + slio_reset_mapper=new QSignalMapper(this); + connect(slio_reset_mapper,SIGNAL(mapped(int)), + this,SLOT(resetStateData(int))); + for(int i=0;isetMapping(slio_reset_timers.back(),i); + slio_reset_states.push_back(false); + } + slio_watchdog_timer=new QTimer(this); + connect(slio_watchdog_timer,SIGNAL(timeout()),this,SLOT(watchdogData())); +} + + +WheatnetSlio::~WheatnetSlio() +{ + delete slio_watchdog_timer; + delete slio_poll_timer; + for(unsigned i=0;icommand()) { + case RDMacro::GO: + if((cmd->argQuantity()!=5)|| + ((cmd->arg(1).toString().lower()!="i")&& + (cmd->arg(1).toString().lower()!="o"))|| + (cmd->arg(2).toInt()<1)||(cmd->arg(3).toInt()>slio_gpios)|| + (cmd->arg(2).toInt()>slio_gpios)|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(1).toString().lower()!="i"))|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(3).toInt()!=-1)&&(cmd->arg(1).toString().lower()=="i"))|| + (cmd->arg(4).toInt()<0)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(3).toInt()==0) { // Turn OFF + if(cmd->arg(4).toInt()==0) { + if(cmd->arg(1).toString().lower()=="o") { + SendCommand(QString().sprintf("",cmd->arg(2).toInt())); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,false); + } + } + else { + if(cmd->echoRequested()) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + } + return; + } + } + else { + if(cmd->arg(4).toInt()==0) { // Turn ON + if(cmd->arg(1).toString().lower()=="o") { + SendCommand(QString().sprintf("",cmd->arg(2).toInt())); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,true); + } + } + else { // Pulse + if(cmd->arg(1).toString().lower()=="o") { + SendCommand(QString().sprintf("", + cmd->arg(2).toInt(), + cmd->arg(3).toInt()!=0)); + slio_reset_states[cmd->arg(2).toInt()-1]=cmd->arg(3).toInt()==0; + slio_reset_timers[cmd->arg(2).toInt()-1]-> + start(cmd->arg(4).toInt(),true); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1, + cmd->arg(3).toInt()!=0); + } + } + } + + if(cmd->echoRequested()) { + cmd->acknowledge(true); + emit rmlEcho(cmd); + } + break; + + default: + break; + } +} + + +void WheatnetSlio::connectedData() +{ + syslog(LOG_INFO, + "connection to WheatNet SLIO device at %s:%u established", + (const char *)slio_ip_address.toString(),0xffff&slio_ip_port); + slio_watchdog_active=false; + SendCommand(""); +} + + +void WheatnetSlio::readyReadData() +{ + char data[1501]; + int n=0; + + while((n=slio_socket->readBlock(data,1500))>0) { + data[n]=0; + for(int i=0;i",i+1)); + } +} + + +void WheatnetSlio::resetStateData(int line) +{ + SendCommand(QString().sprintf("",line+1, + (int)slio_reset_states[line])); + emit gpoChanged(matrixNumber(),line,slio_reset_states[line]); +} + + +void WheatnetSlio::watchdogData() +{ + if(!slio_watchdog_active) { + syslog(LOG_WARNING, + "connection to Wheatnet SLIO device at %s:%u lost, attempting reconnect", + (const char *)slio_ip_address.toString(),0xffff&slio_ip_port); + slio_watchdog_active=true; + } + slio_socket->close(); + slio_socket->connectToHost(slio_ip_address.toString(),slio_ip_port); +} + + +void WheatnetSlio::CheckLineEntry(int line) +{ + QString sql; + RDSqlQuery *q; + + sql=QString("select ID from GPIS where ")+ + "(STATION_NAME=\""+RDEscapeString(stationName())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",matrixNumber())+ + QString().sprintf("(NUMBER=%d)",line); + q=new RDSqlQuery(sql); + if(!q->first()) { + delete q; + sql=QString("insert into GPIS set ")+ + "STATION_NAME=\""+RDEscapeString(stationName())+"\","+ + QString().sprintf("MATRIX=%d,",matrixNumber())+ + QString().sprintf("NUMBER=%d",line); + q=new RDSqlQuery(sql); + } + delete q; + + sql=QString("select ID from GPOS where ")+ + "(STATION_NAME=\""+RDEscapeString(stationName())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",matrixNumber())+ + QString().sprintf("(NUMBER=%d)",line); + q=new RDSqlQuery(sql); + if(!q->first()) { + delete q; + sql=QString("insert into GPOS set ")+ + "STATION_NAME=\""+RDEscapeString(stationName())+"\","+ + QString().sprintf("MATRIX=%d,",matrixNumber())+ + QString().sprintf("NUMBER=%d",line); + q=new RDSqlQuery(sql); + } + delete q; +} + + +void WheatnetSlio::ProcessSys(const QString &cmd) +{ + // printf("SYS: %s\n",(const char *)cmd); + QString sql; + RDSqlQuery *q; + bool ok=false; + + QStringList f0=f0.split(":",cmd); + if((f0[0]=="SLIO")&&(f0.size()==2)) { + int slio=f0[1].toUInt(&ok); + if(ok) { + slio_gpios=slio; + for(unsigned i=0;isetMapping(slio_reset_timers.back(),i); + slio_reset_states.push_back(false); + slio_gpi_states.push_back(false); + CheckLineEntry(i+1); + } + sql=QString("update MATRICES set ")+ + QString().sprintf("GPIS=%d,GPOS=%d where ",slio_gpios,slio_gpios)+ + "(STATION_NAME=\""+RDEscapeString(stationName())+"\")&&"+ + QString().sprintf("(MATRIX=%d)",matrixNumber()); + q=new RDSqlQuery(sql); + delete q; + pollInputs(); + } + } +} + + +void WheatnetSlio::ProcessSlio(int chan,QString &cmd) +{ + // printf("ProcessSlip(%d,%s)\n",chan,(const char *)cmd); + QStringList f0=f0.split(":",cmd); + if((f0[0]=="LVL")&&(f0.size()==2)) { + if(chan<=(int)slio_gpi_states.size()) { + bool state=f0[1]=="1"; + if(state!=slio_gpi_states[chan-1]) { + printf("change chan: %d state: %d\n",chan,state); + slio_gpi_states[chan-1]=state; + emit gpiChanged(matrixNumber(),chan-1,state); + } + } + else { + syslog(LOG_WARNING, + "WheatNet device at %s:%d sent invalid SLIO LVL update [%s]", + (const char *)slio_ip_address.toString(), + slio_ip_port,(const char *)cmd); + } + if(chan==slio_gpios) { + slio_poll_timer->start(50,true); + slio_watchdog_timer->stop(); + slio_watchdog_timer->start(1000,true); + } + } +} + + +void WheatnetSlio::ProcessCommand(const QString &cmd) +{ + // printf("ProcessCommand(%s)\n",(const char *)cmd); + bool ok=false; + + if((cmd.left(1)=="<")&&(cmd.right(1)==">")) { + QStringList f0=f0.split("|",cmd.mid(1,cmd.length()-2)); + if(f0.size()==2) { + QStringList f1=f1.split(":",f0[0]); + if(f1[0]=="SYS") { + ProcessSys(f0[1]); + } + if((f1[0]=="SLIO")&&(f1.size()==2)) { + int chan=f1[1].toUInt(&ok); + if(ok) { + ProcessSlio(chan,f0[1]); + } + } + } + } +} + + +void WheatnetSlio::SendCommand(const QString &cmd) +{ + slio_socket->writeBlock(cmd+"\r\n",cmd.length()+2); +} diff --git a/ripcd/wheatnet_slio.h b/ripcd/wheatnet_slio.h new file mode 100644 index 00000000..096e1706 --- /dev/null +++ b/ripcd/wheatnet_slio.h @@ -0,0 +1,81 @@ +// wheatnet_slio.h +// +// A Rivendell switcher driver for Wheatnet SLIO devices +// +// (C) Copyright 2017 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef WHEATNET_SLIO_H +#define WHEATNET_SLIO_H + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#define WHEATNET_SLIO_POLL_INTERVAL 100 +#define WHEATNET_SLIO_WATCHDOG_INTERVAL 1000 + +class WheatnetSlio : public Switcher +{ + Q_OBJECT + public: + WheatnetSlio(RDMatrix *matrix,QObject *parent=0); + ~WheatnetSlio(); + RDMatrix::Type type(); + unsigned gpiQuantity(); + unsigned gpoQuantity(); + bool primaryTtyActive(); + bool secondaryTtyActive(); + void processCommand(RDMacro *cmd); + + private slots: + void connectedData(); + void readyReadData(); + void errorData(int err); + void pollInputs(); + void resetStateData(int line); + void watchdogData(); + + private: + void CheckLineEntry(int line); + void ProcessSys(const QString &cmd); + void ProcessSlio(int chan,QString &cmd); + void ProcessCommand(const QString &cmd); + void SendCommand(const QString &cmd); + QSocket *slio_socket; + QTimer *slio_poll_timer; + QTimer *slio_watchdog_timer; + bool slio_watchdog_active; + QHostAddress slio_ip_address; + uint16_t slio_ip_port; + int slio_gpios; + QString slio_accum; + std::vector slio_gpi_states; + QSignalMapper *slio_reset_mapper; + std::vector slio_reset_timers; + std::vector slio_reset_states; +}; + + +#endif // WHEATNET_SLIO_H From b548f6264be1ef9e5dca41b28d6c9c34f50e0c7a Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Sat, 12 Aug 2017 18:04:01 -0400 Subject: [PATCH 19/22] 2017-08-12 Fred Gleason * Implemented a driver for WheatNet LIO devices. --- ChangeLog | 2 + docs/SWITCHERS.txt | 23 ++- lib/rdmatrix.cpp | 13 +- lib/rdmatrix.h | 3 +- ripcd/Makefile.am | 2 + ripcd/loaddrivers.cpp | 5 + ripcd/wheatnet_lio.cpp | 372 +++++++++++++++++++++++++++++++++++++++++ ripcd/wheatnet_lio.h | 82 +++++++++ 8 files changed, 496 insertions(+), 6 deletions(-) create mode 100644 ripcd/wheatnet_lio.cpp create mode 100644 ripcd/wheatnet_lio.h diff --git a/ChangeLog b/ChangeLog index a65ebaf6..ea859f0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15931,3 +15931,5 @@ * Incremented the package version to 2.16.0int06_rfa02. 2017-08-12 Fred Gleason * Implemented a driver for WheatNet SLIO devices. +2017-08-12 Fred Gleason + * Implemented a driver for WheatNet LIO devices. diff --git a/docs/SWITCHERS.txt b/docs/SWITCHERS.txt index 286a83a9..1ec90354 100644 --- a/docs/SWITCHERS.txt +++ b/docs/SWITCHERS.txt @@ -37,6 +37,7 @@ Sine Systems ACU-1 (Prophet version) Software Authority Protocol StarGuide III Satellite Receiver Wegener Unity4000 DVB Satellite Receiver +WheatNet Blade LIO WheatNet Blade SLIO See the sections below for notes on each specific model. @@ -853,11 +854,13 @@ stream to be silently deselected from a previously selected output. ---------------------------------------------------------------------------- -WHEATNET BLADE SLIO +WHEATNET BLADE LIO -Driver Name: WheatNet SLIO +Driver Name: WheatNet LIO Supported RML Commands: + GPI Enable ('GE') + GPI Set ('GI') GPO Set ('GO') GENERAL NOTES: @@ -866,4 +869,20 @@ The only required configuration parameters are IP Address and IP Port. The number of pins is auto-detected at driver startup. +---------------------------------------------------------------------------- +WHEATNET BLADE SLIO + +Driver Name: WheatNet SLIO + +Supported RML Commands: + GPI Enable ('GE') + GPI Set ('GI') + GPO Set ('GO') + +GENERAL NOTES: +Control is done by means of a TCP/IP connection to port 55776 on a blade. +The only required configuration parameters are IP Address and IP Port. +The number of soft pins is auto-detected at driver startup. + + ---------------------------------------------------------------------------- diff --git a/lib/rdmatrix.cpp b/lib/rdmatrix.cpp index f80a037b..912071f8 100644 --- a/lib/rdmatrix.cpp +++ b/lib/rdmatrix.cpp @@ -69,7 +69,8 @@ bool __mx_primary_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR {0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // Modbus {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // Kernel GPIO - {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // WheatNet SLIO + {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // WheatNet SLIO + {0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // WheatNet LIO }; bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= { @@ -115,7 +116,8 @@ bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Modbus {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Kernel GPIO - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // WheatNet SLIO + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // WheatNet SLIO + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // WheatNet LIO }; int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= @@ -162,7 +164,8 @@ int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,4,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT SS 4.1 MLR {1,0,0,502,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Modbus {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Kernel GPIO - {1,0,0,55776,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // WheatNet SLIO + {1,0,0,55776,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // WheatNet SLIO + {1,0,0,55776,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // WheatNet LIO }; RDMatrix::RDMatrix(const QString &station,int matrix) @@ -738,6 +741,10 @@ QString RDMatrix::typeString(RDMatrix::Type type) return QString("WheatNet SLIO"); break; + case RDMatrix::WheatnetLio: + return QString("WheatNet LIO"); + break; + default: return QString("Unknown Type"); break; diff --git a/lib/rdmatrix.h b/lib/rdmatrix.h index 4774dca0..c16a408b 100644 --- a/lib/rdmatrix.h +++ b/lib/rdmatrix.h @@ -38,7 +38,8 @@ class RDMatrix BtSrc16=24,Harlond=25,Acu1p=26,LiveWireMcastGpio=27,Am16=28, LiveWireLwrpGpio=29,BtSentinel4Web=30,BtGpi16=31,ModemLines=32, SoftwareAuthority=33,Sas16000=34,RossNkScp=35,BtAdms4422=36, - BtSs41Mlr=37,Modbus=38,KernelGpio=39,WheatnetSlio=40,LastType=41}; + BtSs41Mlr=37,Modbus=38,KernelGpio=39,WheatnetSlio=40, + WheatnetLio=41,LastType=42}; enum Endpoint {Input=0,Output=1}; enum Mode {Stereo=0,Left=1,Right=2}; enum VguestAttribute {VguestEngine=0,VguestDevice=1,VguestSurface=2, diff --git a/ripcd/Makefile.am b/ripcd/Makefile.am index 479a59ed..a4affe95 100644 --- a/ripcd/Makefile.am +++ b/ripcd/Makefile.am @@ -77,6 +77,7 @@ dist_ripcd_SOURCES = acu1p.cpp acu1p.h\ unity4000.cpp unity4000.h\ unity_feed.cpp unity_feed.h\ vguest.cpp vguest.h\ + wheatnet_lio.cpp wheatnet_lio.h\ wheatnet_slio.cpp wheatnet_slio.h nodist_ripcd_SOURCES = moc_am16.cpp\ @@ -120,6 +121,7 @@ nodist_ripcd_SOURCES = moc_am16.cpp\ moc_switcher.cpp\ moc_unity4000.cpp\ moc_vguest.cpp\ + moc_wheatnet_lio.cpp\ moc_wheatnet_slio.cpp ripcd_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ diff --git a/ripcd/loaddrivers.cpp b/ripcd/loaddrivers.cpp index 64aa9c63..637d8105 100644 --- a/ripcd/loaddrivers.cpp +++ b/ripcd/loaddrivers.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include bool MainObject::LoadSwitchDriver(int matrix_num) @@ -220,6 +221,10 @@ bool MainObject::LoadSwitchDriver(int matrix_num) ripcd_switcher[matrix_num]=new Unity4000(matrix,this); break; + case RDMatrix::WheatnetLio: + ripcd_switcher[matrix_num]=new WheatnetLio(matrix,this); + break; + case RDMatrix::WheatnetSlio: ripcd_switcher[matrix_num]=new WheatnetSlio(matrix,this); break; diff --git a/ripcd/wheatnet_lio.cpp b/ripcd/wheatnet_lio.cpp new file mode 100644 index 00000000..3f297a61 --- /dev/null +++ b/ripcd/wheatnet_lio.cpp @@ -0,0 +1,372 @@ +// wheatnet_lio.cpp +// +// A Rivendell switcher driver for Modbus TCP +// +// (C) Copyright 2017 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include + +#include +#include + +#include "wheatnet_lio.h" + +WheatnetLio::WheatnetLio(RDMatrix *matrix,QObject *parent) + : Switcher(matrix,parent) +{ + lio_watchdog_active=false; + + lio_gpios=0; + lio_ip_address=matrix->ipAddress(RDMatrix::Primary); + lio_ip_port=matrix->ipPort(RDMatrix::Primary); + lio_card=matrix->card(); + + lio_socket=new QSocket(this); + connect(lio_socket,SIGNAL(connected()),this,SLOT(connectedData())); + connect(lio_socket,SIGNAL(readyRead()),this,SLOT(readyReadData())); + connect(lio_socket,SIGNAL(error(int)),this,SLOT(errorData(int))); + lio_socket->connectToHost(lio_ip_address.toString(),lio_ip_port); + + lio_poll_timer=new QTimer(this); + connect(lio_poll_timer,SIGNAL(timeout()),this,SLOT(pollInputs())); + + lio_reset_mapper=new QSignalMapper(this); + connect(lio_reset_mapper,SIGNAL(mapped(int)), + this,SLOT(resetStateData(int))); + for(int i=0;isetMapping(lio_reset_timers.back(),i); + lio_reset_states.push_back(false); + } + lio_watchdog_timer=new QTimer(this); + connect(lio_watchdog_timer,SIGNAL(timeout()),this,SLOT(watchdogData())); +} + + +WheatnetLio::~WheatnetLio() +{ + delete lio_watchdog_timer; + delete lio_poll_timer; + for(unsigned i=0;icommand()) { + case RDMacro::GO: + if((cmd->argQuantity()!=5)|| + ((cmd->arg(1).toString().lower()!="i")&& + (cmd->arg(1).toString().lower()!="o"))|| + (cmd->arg(2).toInt()<1)||(cmd->arg(3).toInt()>lio_gpios)|| + (cmd->arg(2).toInt()>lio_gpios)|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(1).toString().lower()!="i"))|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(3).toInt()!=-1)&&(cmd->arg(1).toString().lower()=="i"))|| + (cmd->arg(4).toInt()<0)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(3).toInt()==0) { // Turn OFF + if(cmd->arg(4).toInt()==0) { + if(cmd->arg(1).toString().lower()=="o") { + SendCommand(QString().sprintf("", + cmd->arg(2).toInt()-1)); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,false); + } + } + else { + if(cmd->echoRequested()) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + } + return; + } + } + else { + if(cmd->arg(4).toInt()==0) { // Turn ON + if(cmd->arg(1).toString().lower()=="o") { + SendCommand(QString().sprintf("", + cmd->arg(2).toInt()-1)); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,true); + } + } + else { // Pulse + if(cmd->arg(1).toString().lower()=="o") { + SendCommand(QString().sprintf("", + cmd->arg(2).toInt()-1, + cmd->arg(3).toInt()!=0)); + lio_reset_states[cmd->arg(2).toInt()-1]=cmd->arg(3).toInt()==0; + lio_reset_timers[cmd->arg(2).toInt()-1]-> + start(cmd->arg(4).toInt(),true); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1, + cmd->arg(3).toInt()!=0); + } + } + } + + if(cmd->echoRequested()) { + cmd->acknowledge(true); + emit rmlEcho(cmd); + } + break; + + default: + break; + } +} + + +void WheatnetLio::connectedData() +{ + syslog(LOG_INFO, + "connection to WheatNet LIO device at %s:%u established", + (const char *)lio_ip_address.toString(),0xffff&lio_ip_port); + lio_watchdog_active=false; + SendCommand(""); +} + + +void WheatnetLio::readyReadData() +{ + char data[1501]; + int n=0; + + while((n=lio_socket->readBlock(data,1500))>0) { + data[n]=0; + for(int i=0;i",i)); + } +} + + +void WheatnetLio::resetStateData(int line) +{ + SendCommand(QString().sprintf("",line, + (int)lio_reset_states[line])); + emit gpoChanged(matrixNumber(),line,lio_reset_states[line]); +} + + +void WheatnetLio::watchdogData() +{ + if(!lio_watchdog_active) { + syslog(LOG_WARNING, + "connection to Wheatnet LIO device at %s:%u lost, attempting reconnect", + (const char *)lio_ip_address.toString(),0xffff&lio_ip_port); + lio_watchdog_active=true; + } + lio_socket->close(); + lio_socket->connectToHost(lio_ip_address.toString(),lio_ip_port); +} + + +void WheatnetLio::CheckLineEntry(int line) +{ + QString sql; + RDSqlQuery *q; + + sql=QString("select ID from GPIS where ")+ + "(STATION_NAME=\""+RDEscapeString(stationName())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",matrixNumber())+ + QString().sprintf("(NUMBER=%d)",line); + q=new RDSqlQuery(sql); + if(!q->first()) { + delete q; + sql=QString("insert into GPIS set ")+ + "STATION_NAME=\""+RDEscapeString(stationName())+"\","+ + QString().sprintf("MATRIX=%d,",matrixNumber())+ + QString().sprintf("NUMBER=%d",line); + q=new RDSqlQuery(sql); + } + delete q; + + sql=QString("select ID from GPOS where ")+ + "(STATION_NAME=\""+RDEscapeString(stationName())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",matrixNumber())+ + QString().sprintf("(NUMBER=%d)",line); + q=new RDSqlQuery(sql); + if(!q->first()) { + delete q; + sql=QString("insert into GPOS set ")+ + "STATION_NAME=\""+RDEscapeString(stationName())+"\","+ + QString().sprintf("MATRIX=%d,",matrixNumber())+ + QString().sprintf("NUMBER=%d",line); + q=new RDSqlQuery(sql); + } + delete q; +} + + +void WheatnetLio::ProcessSys(const QString &cmd) +{ + // printf("SYS: %s\n",(const char *)cmd); + QString sql; + RDSqlQuery *q; + bool ok=false; + + QStringList f0=f0.split(":",cmd); + if((f0[0]=="LIO")&&(f0.size()==2)) { + int lio=f0[1].toUInt(&ok); + if(ok) { + lio_gpios=lio; + for(unsigned i=0;isetMapping(lio_reset_timers.back(),i); + lio_reset_states.push_back(false); + lio_gpi_states.push_back(false); + CheckLineEntry(i+1); + } + sql=QString("update MATRICES set ")+ + QString().sprintf("GPIS=%d,GPOS=%d where ",lio_gpios,lio_gpios)+ + "(STATION_NAME=\""+RDEscapeString(stationName())+"\")&&"+ + QString().sprintf("(MATRIX=%d)",matrixNumber()); + q=new RDSqlQuery(sql); + delete q; + pollInputs(); + } + } +} + + +void WheatnetLio::ProcessLio(int chan,QString &cmd) +{ + // printf("ProcessSlip(%d,%s)\n",chan,(const char *)cmd); + QStringList f0=f0.split(":",cmd); + if((f0[0]=="LVL")&&(f0.size()==2)) { + if(chan<(int)lio_gpi_states.size()) { + bool state=f0[1]=="1"; + if(state!=lio_gpi_states[chan]) { + lio_gpi_states[chan]=state; + emit gpiChanged(matrixNumber(),chan,state); + } + } + else { + syslog(LOG_WARNING, + "WheatNet device at %s:%d sent invalid LIO LVL update [%s]", + (const char *)lio_ip_address.toString(), + lio_ip_port,(const char *)cmd); + } + if((chan+1)==lio_gpios) { + lio_poll_timer->start(50,true); + lio_watchdog_timer->stop(); + lio_watchdog_timer->start(1000,true); + } + } +} + + +void WheatnetLio::ProcessCommand(const QString &cmd) +{ + // printf("ProcessCommand(%s)\n",(const char *)cmd); + bool ok=false; + + if((cmd.left(1)=="<")&&(cmd.right(1)==">")) { + QStringList f0=f0.split("|",cmd.mid(1,cmd.length()-2)); + if(f0.size()==2) { + QStringList f1=f1.split(":",f0[0]); + if(f1[0]=="SYS") { + ProcessSys(f0[1]); + } + if((f1[0]=="LIO")&&(f1.size()==2)) { + int chan=f1[1].toUInt(&ok); + if(ok) { + ProcessLio(chan,f0[1]); + } + } + } + } +} + + +void WheatnetLio::SendCommand(const QString &cmd) +{ + lio_socket->writeBlock(cmd+"\r\n",cmd.length()+2); +} diff --git a/ripcd/wheatnet_lio.h b/ripcd/wheatnet_lio.h new file mode 100644 index 00000000..e1fd5a04 --- /dev/null +++ b/ripcd/wheatnet_lio.h @@ -0,0 +1,82 @@ +// wheatnet_lio.h +// +// A Rivendell switcher driver for Wheatnet LIO devices +// +// (C) Copyright 2017 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef WHEATNET_LIO_H +#define WHEATNET_LIO_H + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#define WHEATNET_LIO_POLL_INTERVAL 100 +#define WHEATNET_LIO_WATCHDOG_INTERVAL 1000 + +class WheatnetLio : public Switcher +{ + Q_OBJECT + public: + WheatnetLio(RDMatrix *matrix,QObject *parent=0); + ~WheatnetLio(); + RDMatrix::Type type(); + unsigned gpiQuantity(); + unsigned gpoQuantity(); + bool primaryTtyActive(); + bool secondaryTtyActive(); + void processCommand(RDMacro *cmd); + + private slots: + void connectedData(); + void readyReadData(); + void errorData(int err); + void pollInputs(); + void resetStateData(int line); + void watchdogData(); + + private: + void CheckLineEntry(int line); + void ProcessSys(const QString &cmd); + void ProcessLio(int chan,QString &cmd); + void ProcessCommand(const QString &cmd); + void SendCommand(const QString &cmd); + QSocket *lio_socket; + QTimer *lio_poll_timer; + QTimer *lio_watchdog_timer; + bool lio_watchdog_active; + QHostAddress lio_ip_address; + uint16_t lio_ip_port; + int lio_card; + int lio_gpios; + QString lio_accum; + std::vector lio_gpi_states; + QSignalMapper *lio_reset_mapper; + std::vector lio_reset_timers; + std::vector lio_reset_states; +}; + + +#endif // WHEATNET_LIO_H From 2e3a2d5d1b6bcbe611fd94dd5e2d9bfc64881275 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Sun, 13 Aug 2017 08:48:16 -0400 Subject: [PATCH 20/22] 2017-08-13 Fred Gleason * Refactored the WheatNet LIO driver to use event subscription. --- ChangeLog | 2 ++ ripcd/wheatnet_lio.cpp | 43 ++++++++++++++++++++++++------------------ ripcd/wheatnet_lio.h | 10 +++++----- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea859f0f..09f6f0a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15933,3 +15933,5 @@ * Implemented a driver for WheatNet SLIO devices. 2017-08-12 Fred Gleason * Implemented a driver for WheatNet LIO devices. +2017-08-13 Fred Gleason + * Refactored the WheatNet LIO driver to use event subscription. diff --git a/ripcd/wheatnet_lio.cpp b/ripcd/wheatnet_lio.cpp index 3f297a61..75415061 100644 --- a/ripcd/wheatnet_lio.cpp +++ b/ripcd/wheatnet_lio.cpp @@ -42,7 +42,7 @@ WheatnetLio::WheatnetLio(RDMatrix *matrix,QObject *parent) lio_socket->connectToHost(lio_ip_address.toString(),lio_ip_port); lio_poll_timer=new QTimer(this); - connect(lio_poll_timer,SIGNAL(timeout()),this,SLOT(pollInputs())); + connect(lio_poll_timer,SIGNAL(timeout()),this,SLOT(pollData())); lio_reset_mapper=new QSignalMapper(this); connect(lio_reset_mapper,SIGNAL(mapped(int)), @@ -211,14 +211,6 @@ void WheatnetLio::errorData(int err) } -void WheatnetLio::pollInputs() -{ - for(int i=0;i",i)); - } -} - - void WheatnetLio::resetStateData(int line) { SendCommand(QString().sprintf("",line, @@ -227,6 +219,12 @@ void WheatnetLio::resetStateData(int line) } +void WheatnetLio::pollData() +{ + SendCommand(""); +} + + void WheatnetLio::watchdogData() { if(!lio_watchdog_active) { @@ -303,6 +301,7 @@ void WheatnetLio::ProcessSys(const QString &cmd) lio_reset_states.push_back(false); lio_gpi_states.push_back(false); CheckLineEntry(i+1); + SendCommand(QString().sprintf("",i)); } sql=QString("update MATRICES set ")+ QString().sprintf("GPIS=%d,GPOS=%d where ",lio_gpios,lio_gpios)+ @@ -310,15 +309,21 @@ void WheatnetLio::ProcessSys(const QString &cmd) QString().sprintf("(MATRIX=%d)",matrixNumber()); q=new RDSqlQuery(sql); delete q; - pollInputs(); + lio_watchdog_timer->start(WHEATNET_LIO_WATCHDOG_INTERVAL,true); + lio_poll_timer->start(WHEATNET_LIO_POLL_INTERVAL,true); } } + if((f0[0]=="BLID")&&(f0.size()==2)) { + lio_watchdog_timer->stop(); + lio_watchdog_timer->start(WHEATNET_LIO_WATCHDOG_INTERVAL,true); + lio_poll_timer->start(WHEATNET_LIO_POLL_INTERVAL,true); + } } -void WheatnetLio::ProcessLio(int chan,QString &cmd) +void WheatnetLio::ProcessLioevent(int chan,QString &cmd) { - // printf("ProcessSlip(%d,%s)\n",chan,(const char *)cmd); + // printf("ProcessLioevent(%d,%s)\n",chan,(const char *)cmd); QStringList f0=f0.split(":",cmd); if((f0[0]=="LVL")&&(f0.size()==2)) { if(chan<(int)lio_gpi_states.size()) { @@ -330,12 +335,11 @@ void WheatnetLio::ProcessLio(int chan,QString &cmd) } else { syslog(LOG_WARNING, - "WheatNet device at %s:%d sent invalid LIO LVL update [%s]", + "WheatNet device at %s:%d sent invalid LIOEVENT LVL update [%s]", (const char *)lio_ip_address.toString(), lio_ip_port,(const char *)cmd); } if((chan+1)==lio_gpios) { - lio_poll_timer->start(50,true); lio_watchdog_timer->stop(); lio_watchdog_timer->start(1000,true); } @@ -355,10 +359,13 @@ void WheatnetLio::ProcessCommand(const QString &cmd) if(f1[0]=="SYS") { ProcessSys(f0[1]); } - if((f1[0]=="LIO")&&(f1.size()==2)) { - int chan=f1[1].toUInt(&ok); - if(ok) { - ProcessLio(chan,f0[1]); + if((f1[0]=="LIOEVENT")&&(f1.size()==2)) { + QStringList f2=f2.split(".",f1[1]); + if((f2[0]=="0")&&(f2.size()==2)) { + int chan=f2[1].toUInt(&ok); + if(ok) { + ProcessLioevent(chan,f0[1]); + } } } } diff --git a/ripcd/wheatnet_lio.h b/ripcd/wheatnet_lio.h index e1fd5a04..91cd6e4b 100644 --- a/ripcd/wheatnet_lio.h +++ b/ripcd/wheatnet_lio.h @@ -33,8 +33,8 @@ #include -#define WHEATNET_LIO_POLL_INTERVAL 100 -#define WHEATNET_LIO_WATCHDOG_INTERVAL 1000 +#define WHEATNET_LIO_POLL_INTERVAL 1000 +#define WHEATNET_LIO_WATCHDOG_INTERVAL 5000 class WheatnetLio : public Switcher { @@ -53,18 +53,17 @@ class WheatnetLio : public Switcher void connectedData(); void readyReadData(); void errorData(int err); - void pollInputs(); void resetStateData(int line); + void pollData(); void watchdogData(); private: void CheckLineEntry(int line); void ProcessSys(const QString &cmd); - void ProcessLio(int chan,QString &cmd); + void ProcessLioevent(int chan,QString &cmd); void ProcessCommand(const QString &cmd); void SendCommand(const QString &cmd); QSocket *lio_socket; - QTimer *lio_poll_timer; QTimer *lio_watchdog_timer; bool lio_watchdog_active; QHostAddress lio_ip_address; @@ -76,6 +75,7 @@ class WheatnetLio : public Switcher QSignalMapper *lio_reset_mapper; std::vector lio_reset_timers; std::vector lio_reset_states; + QTimer *lio_poll_timer; }; From f0f908aad392f39dc42316962b8b5e11697c03ba Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Sun, 13 Aug 2017 09:11:51 -0400 Subject: [PATCH 21/22] 2017-08-13 Fred Gleason * Refactored the WheatNet SLIO driver to use event subscription. --- ChangeLog | 2 ++ ripcd/wheatnet_slio.cpp | 34 +++++++++++++++++++--------------- ripcd/wheatnet_slio.h | 10 +++++----- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09f6f0a1..dcb74899 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15935,3 +15935,5 @@ * Implemented a driver for WheatNet LIO devices. 2017-08-13 Fred Gleason * Refactored the WheatNet LIO driver to use event subscription. +2017-08-13 Fred Gleason + * Refactored the WheatNet SLIO driver to use event subscription. diff --git a/ripcd/wheatnet_slio.cpp b/ripcd/wheatnet_slio.cpp index 5ab9eb35..305d5af4 100644 --- a/ripcd/wheatnet_slio.cpp +++ b/ripcd/wheatnet_slio.cpp @@ -41,7 +41,7 @@ WheatnetSlio::WheatnetSlio(RDMatrix *matrix,QObject *parent) slio_socket->connectToHost(slio_ip_address.toString(),slio_ip_port); slio_poll_timer=new QTimer(this); - connect(slio_poll_timer,SIGNAL(timeout()),this,SLOT(pollInputs())); + connect(slio_poll_timer,SIGNAL(timeout()),this,SLOT(pollData())); slio_reset_mapper=new QSignalMapper(this); connect(slio_reset_mapper,SIGNAL(mapped(int)), @@ -208,14 +208,6 @@ void WheatnetSlio::errorData(int err) } -void WheatnetSlio::pollInputs() -{ - for(int i=0;i",i+1)); - } -} - - void WheatnetSlio::resetStateData(int line) { SendCommand(QString().sprintf("",line+1, @@ -224,6 +216,12 @@ void WheatnetSlio::resetStateData(int line) } +void WheatnetSlio::pollData() +{ + SendCommand(""); +} + + void WheatnetSlio::watchdogData() { if(!slio_watchdog_active) { @@ -300,6 +298,7 @@ void WheatnetSlio::ProcessSys(const QString &cmd) slio_reset_states.push_back(false); slio_gpi_states.push_back(false); CheckLineEntry(i+1); + SendCommand(QString().sprintf("",i+1)); } sql=QString("update MATRICES set ")+ QString().sprintf("GPIS=%d,GPOS=%d where ",slio_gpios,slio_gpios)+ @@ -307,13 +306,19 @@ void WheatnetSlio::ProcessSys(const QString &cmd) QString().sprintf("(MATRIX=%d)",matrixNumber()); q=new RDSqlQuery(sql); delete q; - pollInputs(); + slio_watchdog_timer->start(WHEATNET_SLIO_WATCHDOG_INTERVAL,true); + slio_poll_timer->start(WHEATNET_SLIO_POLL_INTERVAL,true); } } + if((f0[0]=="BLID")&&(f0.size()==2)) { + slio_watchdog_timer->stop(); + slio_watchdog_timer->start(WHEATNET_SLIO_WATCHDOG_INTERVAL,true); + slio_poll_timer->start(WHEATNET_SLIO_POLL_INTERVAL,true); + } } -void WheatnetSlio::ProcessSlio(int chan,QString &cmd) +void WheatnetSlio::ProcessSlioevent(int chan,QString &cmd) { // printf("ProcessSlip(%d,%s)\n",chan,(const char *)cmd); QStringList f0=f0.split(":",cmd); @@ -321,14 +326,13 @@ void WheatnetSlio::ProcessSlio(int chan,QString &cmd) if(chan<=(int)slio_gpi_states.size()) { bool state=f0[1]=="1"; if(state!=slio_gpi_states[chan-1]) { - printf("change chan: %d state: %d\n",chan,state); slio_gpi_states[chan-1]=state; emit gpiChanged(matrixNumber(),chan-1,state); } } else { syslog(LOG_WARNING, - "WheatNet device at %s:%d sent invalid SLIO LVL update [%s]", + "WheatNet device at %s:%d sent invalid SLIOEVENT LVL update [%s]", (const char *)slio_ip_address.toString(), slio_ip_port,(const char *)cmd); } @@ -353,10 +357,10 @@ void WheatnetSlio::ProcessCommand(const QString &cmd) if(f1[0]=="SYS") { ProcessSys(f0[1]); } - if((f1[0]=="SLIO")&&(f1.size()==2)) { + if((f1[0]=="SLIOEVENT")&&(f1.size()==2)) { int chan=f1[1].toUInt(&ok); if(ok) { - ProcessSlio(chan,f0[1]); + ProcessSlioevent(chan,f0[1]); } } } diff --git a/ripcd/wheatnet_slio.h b/ripcd/wheatnet_slio.h index 096e1706..1104066e 100644 --- a/ripcd/wheatnet_slio.h +++ b/ripcd/wheatnet_slio.h @@ -33,8 +33,8 @@ #include -#define WHEATNET_SLIO_POLL_INTERVAL 100 -#define WHEATNET_SLIO_WATCHDOG_INTERVAL 1000 +#define WHEATNET_SLIO_POLL_INTERVAL 1000 +#define WHEATNET_SLIO_WATCHDOG_INTERVAL 5000 class WheatnetSlio : public Switcher { @@ -53,18 +53,17 @@ class WheatnetSlio : public Switcher void connectedData(); void readyReadData(); void errorData(int err); - void pollInputs(); void resetStateData(int line); + void pollData(); void watchdogData(); private: void CheckLineEntry(int line); void ProcessSys(const QString &cmd); - void ProcessSlio(int chan,QString &cmd); + void ProcessSlioevent(int chan,QString &cmd); void ProcessCommand(const QString &cmd); void SendCommand(const QString &cmd); QSocket *slio_socket; - QTimer *slio_poll_timer; QTimer *slio_watchdog_timer; bool slio_watchdog_active; QHostAddress slio_ip_address; @@ -75,6 +74,7 @@ class WheatnetSlio : public Switcher QSignalMapper *slio_reset_mapper; std::vector slio_reset_timers; std::vector slio_reset_states; + QTimer *slio_poll_timer; }; From 959761b8ed0d5ef33ddec972d1852d616d4cc6f4 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Wed, 16 Aug 2017 11:07:24 -0400 Subject: [PATCH 22/22] 2017-08-16 Fred Gleason * Fixed a bug in 'lib/rdlog.cpp' that caused incorrect results when calculating the total number of voice tracks in a log. --- ChangeLog | 3 +++ lib/rdlog.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c72fd4bf..9d640062 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15929,3 +15929,6 @@ 'rlm_filewrite' RLM from 256 to 8192 characters. 2017-08-07 Fred Gleason * Incremented the package version to 2.16.0int06_rfa02. +2017-08-16 Fred Gleason + * Fixed a bug in 'lib/rdlog.cpp' that caused incorrect results when + calculating the total number of voice tracks in a log. diff --git a/lib/rdlog.cpp b/lib/rdlog.cpp index 8b6874c7..824b6c20 100644 --- a/lib/rdlog.cpp +++ b/lib/rdlog.cpp @@ -394,8 +394,10 @@ void RDLog::updateTracks() unsigned scheduled=0; unsigned completed=0; - sql=QString().sprintf("select NUMBER from CART where OWNER=\"%s\"", - (const char *)RDEscapeString(log_name)); + sql=QString("select `")+RDLog::tableName(log_name)+"`.ID from "+ + "`"+RDLog::tableName(log_name)+"` left join CART "+ + "on `"+RDLog::tableName(log_name)+"`.CART_NUMBER=CART.NUMBER where "+ + "CART.OWNER is not null"; q=new RDSqlQuery(sql); completed=q->size(); delete q;