You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

428 lines
11KB

  1. #include "NauModular.hpp"
  2. #include <iostream>
  3. #ifdef ARCH_WIN
  4. #include <Winsock2.h>
  5. #include <ws2tcpip.h>
  6. #else
  7. #include <arpa/inet.h>
  8. #include <sys/select.h>
  9. #include <fcntl.h>
  10. #include <unistd.h>
  11. #endif
  12. #include <signal.h>
  13. #include <stdbool.h>
  14. #include <stdio.h>
  15. #include "tinyosc.h"
  16. #include "dsp/digital.hpp"
  17. #define osc_strncpy(_dst, _src, _len) strncpy(_dst, _src, _len)
  18. namespace rack_plugin_NauModular {
  19. struct Osc : Module{
  20. enum ParamIds{
  21. NUM_PARAMS
  22. };
  23. enum InputIds{
  24. GATE_INPUT,
  25. TRIG_INPUT,
  26. NUM_INPUTS
  27. };
  28. enum OutputIds{
  29. CV_OUTPUT,
  30. GATE_OUTPUT,
  31. TRIG_OUTPUT,
  32. NUM_OUTPUTS
  33. };
  34. enum LightIds{
  35. GATE_IN_LIGHT,
  36. TRIG_IN_LIGHT,
  37. CV_OUT_LIGHT,
  38. GATE_OUT_LIGHT,
  39. TRIG_OUT_LIGHT,
  40. NUM_LIGHTS
  41. };
  42. Osc();
  43. ~Osc();
  44. void makeUDPSocket();
  45. void checkIncomingOsc();
  46. int makeFloatMsg(char * _buf, int _bufLen, std::string _addr, float _val);
  47. int makeGateMsg(char * _buf, int _bufLen, float _val);
  48. int makeTrigMsg(char * _buf, int _bufLen, float _val);
  49. void sendMsg(char * _buf, int _bufLen);
  50. void sendGateMsg(float _val);
  51. void sendTrigMsg(float _val=5.0);
  52. void step() override;
  53. void updateGateIn();
  54. void updateTrigIn();
  55. void openRemoteGate(float _val=5.0);
  56. void closeRemoteGate();
  57. void openLocalGate(float _val=5.0);
  58. void closeLocalGate();
  59. void setLocalCv(float _val);
  60. void setTrigNow();
  61. bool isAnyOutputActive();
  62. SchmittTrigger trigIn;
  63. float lastTrigInput;
  64. float lastTrigOutput;
  65. float thrTrig;
  66. float thrGateOpen;
  67. float thrGateClosed;
  68. float curTime;
  69. float stepTime;
  70. std::string ipOut;
  71. char * buffer;
  72. char * bufMsgOut;
  73. int portIn;
  74. int portOut;
  75. int s;
  76. int i;
  77. socklen_t slen;
  78. int recv_len;
  79. const int bufLen;
  80. const int msgBufLen;
  81. struct sockaddr_in si_me, si_other;
  82. bool bReady;
  83. bool bGateOpen;
  84. int n;
  85. };
  86. Osc::Osc() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS), bufLen(1024), msgBufLen(1024){
  87. portIn = 9000;
  88. portOut = 8000;
  89. ipOut = "127.0.0.1";
  90. slen = sizeof(si_other);
  91. buffer = new char[bufLen];
  92. bufMsgOut = new char[msgBufLen];
  93. bReady = false;
  94. n = 0;
  95. lastTrigInput = 0.0;
  96. bGateOpen = false;
  97. thrTrig = 5;
  98. thrGateOpen = 5;
  99. thrGateClosed = 0;
  100. curTime = 0;
  101. #if ARCH_WIN
  102. WSADATA wsaData;
  103. WORD versionRequested = MAKEWORD(2,2);
  104. if(WSAStartup(versionRequested, &wsaData) != 0) {
  105. std::cout<<"OSC ERROR: Failed to start Windows networking"<<std::endl;
  106. return;
  107. }
  108. #endif
  109. makeUDPSocket();
  110. }
  111. Osc::~Osc(){
  112. #if ARCH_WIN
  113. if(bReady && (closesocket(s) != 0)) {
  114. std::cout << "OSC ERROR: Failed to close socket: " << WSAGetLastError() << std::endl;
  115. }
  116. #else
  117. if(bReady)close(s);
  118. #endif
  119. delete [] buffer;
  120. delete [] bufMsgOut;
  121. #if ARCH_WIN
  122. WSACleanup();
  123. #endif
  124. }
  125. void Osc::makeUDPSocket(){
  126. s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  127. if(s==-1){
  128. std::cout<<"OSC ERROR: cannot create socket"<<std::endl;
  129. bReady = false;
  130. #if ARCH_WIN
  131. WSACleanup();
  132. #endif
  133. return;
  134. }
  135. //set local
  136. memset((char *)&si_me, 0, sizeof(si_me));
  137. si_me.sin_family = AF_INET;
  138. si_me.sin_port = htons(portIn);
  139. si_me.sin_addr.s_addr = htonl(INADDR_ANY);
  140. //set remote
  141. memset((char *)&si_other, 0 , sizeof(si_other));
  142. si_other.sin_family = AF_INET;
  143. si_other.sin_port = htons(portOut);
  144. #ifdef ARCH_WIN
  145. const unsigned long addr = inet_addr(ipOut.c_str());
  146. if ((addr == INADDR_NONE) || (addr == INADDR_ANY)){
  147. std::cout<<"OSC ERROR: remote IP is not valid"<<std::endl;
  148. bReady = false;
  149. WSACleanup();
  150. return;
  151. }
  152. si_other.sin_addr.S_un.S_addr = addr;
  153. #else
  154. if(inet_aton(ipOut.c_str(), &si_other.sin_addr)==0){
  155. std::cout<<"OSC ERROR: remote IP is not valid"<<std::endl;
  156. bReady = false;
  157. return;
  158. }
  159. #endif
  160. if(bind(s, (struct sockaddr*)&si_me, sizeof(si_me) ) == -1){
  161. std::cout<<"OSC ERROR: cannot bind socket"<<std::endl;
  162. bReady = false;
  163. #if ARCH_WIN
  164. WSACleanup();
  165. #endif
  166. return;
  167. }
  168. bReady = true;
  169. std::cout<<"OSC listening on port "<<portIn<<" and sending at "<<ipOut<<":"<<portOut<<std::endl;
  170. }
  171. void Osc::checkIncomingOsc(){
  172. if(!isAnyOutputActive()){
  173. //lights[CV_OUT_LIGHT].value = 0;
  174. //lights[GATE_OUT_LIGHT].value = 0;
  175. lights[TRIG_OUT_LIGHT].value = 0;
  176. setLocalCv(0);
  177. closeLocalGate();
  178. return;
  179. }
  180. if(outputs[TRIG_OUTPUT].value>0){
  181. if(curTime > (lastTrigOutput+0.1)){
  182. lights[TRIG_OUT_LIGHT].value = 0;
  183. outputs[TRIG_OUTPUT].value = 0;
  184. }
  185. }
  186. fd_set readSet;
  187. FD_ZERO(&readSet);
  188. FD_SET(s, &readSet);
  189. int microSec = stepTime * 1000000/2;
  190. struct timeval timeout = {0, microSec};
  191. if(select(s+1, &readSet, NULL, NULL, &timeout)>0){
  192. recv_len = 0;
  193. while((recv_len=(int)recvfrom(s, buffer, bufLen, 0, (struct sockaddr *)&si_other,&slen))>0){
  194. if(tosc_isBundle(buffer)){
  195. std::cout<<"OSC ERROR: no bundles, pleeze"<<std::endl;
  196. }else{
  197. tosc_message msg;
  198. tosc_parseMessage(&msg, buffer, bufLen);
  199. //tosc_printMessage(&msg);
  200. std::string sAddr = tosc_getAddress(&msg);
  201. float ff;
  202. if(sAddr=="/gate"){
  203. ff = tosc_getNextFloat(&msg);
  204. if(ff>0){
  205. openLocalGate(ff);
  206. }else{
  207. closeLocalGate();
  208. }
  209. }else if(sAddr=="/trigger"){
  210. ff = tosc_getNextFloat(&msg);
  211. setTrigNow();
  212. }else if(sAddr=="/cv"){
  213. ff = tosc_getNextFloat(&msg);
  214. setLocalCv(ff);
  215. }
  216. }
  217. }
  218. }
  219. }
  220. int Osc::makeFloatMsg(char * _buf, int _bufLen, std::string _addr, float _val){
  221. memset(_buf,0,_bufLen);
  222. uint32_t ii = (uint32_t)strlen(_addr.c_str());
  223. if(_addr.c_str()==NULL || _addr.size()==0 || ii>=_bufLen)return -1;
  224. osc_strncpy(_buf, _addr.c_str(), _bufLen);
  225. ii = (ii+4)& ~0x3;
  226. _buf[ii++] = ',';
  227. int s_len = 1;
  228. osc_strncpy(_buf+ii, "f", _bufLen-ii-s_len);
  229. ii = (ii+4+s_len)& ~0x03;
  230. if((ii+4)>_bufLen)return -3;
  231. *((uint32_t *)(_buf+ii)) = htonl(*((uint32_t *)&_val));
  232. ii+=4;
  233. return ii;
  234. }
  235. int Osc::makeGateMsg(char * _buf, int _bufLen, float _val){
  236. return makeFloatMsg(_buf, _bufLen, "/gate", _val);
  237. }
  238. int Osc::makeTrigMsg(char * _buf, int _bufLen, float _val){
  239. return makeFloatMsg(_buf, _bufLen, "/trigger", _val);
  240. }
  241. void Osc::sendMsg(char * _buf, int _bufLen){
  242. if(bReady)
  243. sendto(s, _buf, _bufLen, 0, (struct sockaddr *)&si_other, slen);
  244. }
  245. void Osc::sendGateMsg(float _val){
  246. int ll = makeGateMsg(bufMsgOut, msgBufLen, _val);
  247. if(ll>0){
  248. sendMsg(bufMsgOut, ll);
  249. }else{
  250. std::cout<<"OSC ERROR: cannot send gate message"<<std::endl;
  251. }
  252. }
  253. void Osc::sendTrigMsg(float _val){
  254. int ll = makeTrigMsg(bufMsgOut, msgBufLen, _val);
  255. if(ll>0){
  256. sendMsg(bufMsgOut, ll);
  257. }else{
  258. std::cout<<"OSC ERROR: cannot send trigger message"<<std::endl;
  259. }
  260. }
  261. void Osc::step(){
  262. stepTime = 1.0/engineGetSampleRate();
  263. curTime += stepTime;
  264. updateGateIn();
  265. updateTrigIn();
  266. checkIncomingOsc();
  267. }
  268. void Osc::updateGateIn(){
  269. if(inputs[GATE_INPUT].active){
  270. float curVal = inputs[GATE_INPUT].value;
  271. if(curVal>=thrGateOpen){
  272. openRemoteGate(curVal);
  273. }else if(curVal<=thrGateClosed){
  274. closeRemoteGate();
  275. }
  276. }else{
  277. closeRemoteGate();
  278. }
  279. }
  280. void Osc::openRemoteGate(float _val){
  281. if(bGateOpen)return;
  282. lights[GATE_IN_LIGHT].value = 1.0;
  283. sendGateMsg(_val);
  284. bGateOpen = true;
  285. }
  286. void Osc::closeRemoteGate(){
  287. if(!bGateOpen)return;
  288. lights[GATE_IN_LIGHT].value = 0.0;
  289. sendGateMsg(0);
  290. bGateOpen = false;
  291. }
  292. void Osc::closeLocalGate(){
  293. lights[GATE_OUT_LIGHT].value = 0;
  294. outputs[GATE_OUTPUT].value = 0;
  295. }
  296. void Osc::openLocalGate(float _val){
  297. lights[GATE_OUT_LIGHT].value = 1.0;
  298. outputs[GATE_OUTPUT].value = _val;
  299. }
  300. void Osc::setLocalCv(float _val){
  301. lights[CV_OUT_LIGHT].value = fabs(_val)/12.0;
  302. outputs[CV_OUTPUT].value = _val;
  303. }
  304. void Osc::setTrigNow(){
  305. lights[TRIG_OUT_LIGHT].value = 1;
  306. lastTrigOutput = curTime;
  307. outputs[TRIG_OUTPUT].value = 5;
  308. }
  309. void Osc::updateTrigIn(){
  310. if(inputs[TRIG_INPUT].active){
  311. float curVal = inputs[TRIG_INPUT].value;
  312. if(trigIn.process(curVal)){
  313. lights[TRIG_IN_LIGHT].value = 1.0;
  314. sendTrigMsg();
  315. lastTrigInput = curTime;
  316. }
  317. if(lights[TRIG_IN_LIGHT].value>0){
  318. if(curTime>(lastTrigInput+0.1)){
  319. lights[TRIG_IN_LIGHT].value = 0;
  320. }
  321. }
  322. }else{
  323. trigIn.reset();
  324. lights[TRIG_IN_LIGHT].value = 0.0;
  325. }
  326. }
  327. bool Osc::isAnyOutputActive(){
  328. return (outputs[CV_OUTPUT].active ||
  329. outputs[GATE_OUTPUT].active ||
  330. outputs[TRIG_OUTPUT].active);
  331. }
  332. struct OscWidget : ModuleWidget{
  333. OscWidget(Osc *module);
  334. };
  335. OscWidget::OscWidget(Osc *module) : ModuleWidget(module){
  336. box.size = Vec(6 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  337. {
  338. SVGPanel *panel = new SVGPanel();
  339. panel->box.size = box.size;
  340. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Osc.svg")));
  341. addChild(panel);
  342. }
  343. addInput(Port::create<PJ301MPort>(Vec(10,75), Port::INPUT, module, Osc::GATE_INPUT));
  344. addInput(Port::create<PJ301MPort>(Vec(55,75), Port::INPUT, module, Osc::TRIG_INPUT));
  345. addOutput(Port::create<PJ301MPort>(Vec(32, 170), Port::OUTPUT, module, Osc::CV_OUTPUT));
  346. addOutput(Port::create<PJ301MPort>(Vec(10, 270), Port::OUTPUT, module, Osc::GATE_OUTPUT));
  347. addOutput(Port::create<PJ301MPort>(Vec(55, 270), Port::OUTPUT, module, Osc::TRIG_OUTPUT));
  348. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(16, 103), module, Osc::GATE_IN_LIGHT));
  349. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(62, 103), module, Osc::TRIG_IN_LIGHT));
  350. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(40, 200), module, Osc::CV_OUT_LIGHT));
  351. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(20, 250), module, Osc::GATE_OUT_LIGHT));
  352. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(60, 250), module, Osc::TRIG_OUT_LIGHT));
  353. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  354. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  355. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  356. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  357. }
  358. } // namespace rack_plugin_NauModular
  359. using namespace rack_plugin_NauModular;
  360. RACK_PLUGIN_MODEL_INIT(NauModular, Osc) {
  361. Model *modelOsc = Model::create<Osc, OscWidget>("NauModular", "Osc", "Osc", CONTROLLER_TAG);
  362. return modelOsc;
  363. }