1 // =====================================================================
2 //
3 // xmlrpc_rig.cxx
4 //
5 // connect to flrig xmlrpc server
6 //
7 // Copyright (C) 2007-2009
8 // Dave Freese, W1HKJ
9 //
10 // This file is part of fldigi.
11 //
12 // Fldigi is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // Fldigi is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
24 // =====================================================================
25
26 #include <iostream>
27 #include <cmath>
28 #include <cstring>
29 #include <vector>
30 #include <list>
31 #include <stdlib.h>
32
33 #include <FL/Fl.H>
34 #include <FL/filename.H>
35 #include <FL/fl_ask.H>
36
37 #include "rigsupport.h"
38 #include "modem.h"
39 #include "trx.h"
40 #include "fl_digi.h"
41 #include "configuration.h"
42 #include "main.h"
43 #include "waterfall.h"
44 #include "macros.h"
45 #include "qrunner.h"
46 #include "debug.h"
47 #include "status.h"
48 #include "icons.h"
49
50 LOG_FILE_SOURCE(debug::debug::LOG_RPC_CLIENT);
51
52 using namespace XmlRpc;
53 using namespace std;
54
55 static int xmlrpc_verbosity = 0;
56
57 //======================================================================
58 // flrig xmlrpc client
59 //======================================================================
60
61 pthread_t *flrig_thread = 0;
62 pthread_mutex_t mutex_flrig = PTHREAD_MUTEX_INITIALIZER;
63
64 void movFreq(Fl_Widget *w, void *d);
65 void show_freq(void *);
66 void flrig_get_vfo();
67 void flrig_get_frequency();
68 void post_mode(void *);
69 void flrig_get_mode();
70 void post_modes(void *);
71 void flrig_get_modes();
72 void post_bw(void *);
73 void flrig_get_bw();
74 void post_bws(void *);
75 void flrig_get_bws();
76 void flrig_get_notch();
77 void flrig_set_notch(int);
78
79 bool flrig_get_xcvr();
80 void flrig_connection();
81 void set_ptt();
82
83 void connect_to_flrig();
84
85 XmlRpcClient *flrig_client = (XmlRpcClient *)0;
86
87 //----------------------------------------------------------------------
88 // declared as extern in rigsupport.h
89 //----------------------------------------------------------------------
90 bool connected_to_flrig = false;
91 //----------------------------------------------------------------------
92
93 static bool bws_posted = false;
94 static bool modes_posted = false;
95 static bool freq_posted = true;
96
97 static string xcvr_name;
98 static string str_freq;
99 static string mode_result;
100 static XmlRpcValue modes_result;
101 static XmlRpcValue bws_result;
102 static XmlRpcValue bw_result;
103 static XmlRpcValue notch_result;
104
105 static double timeout = 5.0;
106
107 static int wait_bws_timeout = 0;
108
109 //======================================================================
110
xmlrpc_rig_set_qsy(long long rfc)111 void xmlrpc_rig_set_qsy(long long rfc)
112 {
113 unsigned long int freq = static_cast<unsigned long int>(rfc);
114 set_flrig_freq(freq);
115 wf->rfcarrier(freq);
116 wf->movetocenter();
117 show_frequency(freq);
118 LOG_VERBOSE("set qsy: %lu", freq);
119 }
120
121 //======================================================================
122 // set / get pairs
123 //======================================================================
124
125 //----------------------------------------------------------------------
126 // push to talk
127 //----------------------------------------------------------------------
128 static int ptt_state = 0;
129
130 static int new_ptt = -1;
131
exec_flrig_ptt()132 void exec_flrig_ptt() {
133 if (!connected_to_flrig) {
134 new_ptt = -1;
135 return;
136 }
137
138 XmlRpcValue val, result, result2;
139
140 try {
141 bool ret;
142 {
143 guard_lock flrig_lock(&mutex_flrig);
144 ret = flrig_client->execute("rig.set_ptt", new_ptt, result, timeout);
145 }
146 if (ret) {
147 LOG_VERBOSE("ptt %s", ptt_state ? "ON" : "OFF");
148 new_ptt = -1;
149 return;
150 }
151 } catch (...) {
152 new_ptt = -1;
153 return;
154 }
155
156 LOG_ERROR("fldigi/flrig PTT %s failure", new_ptt ? "ON" : "OFF");
157 new_ptt = -1;
158 return;
159 }
160
set_flrig_ptt(int on)161 void set_flrig_ptt(int on) {
162 if (!active_modem)
163 return;
164
165 if (active_modem->get_mode() == MODE_CW) {
166 if (progdefaults.use_FLRIGkeying) {
167 flrig_cwio_ptt(on);
168 if (progdefaults.CATkeying_disable_ptt)
169 return;
170 }
171 else if (progdefaults.CATkeying_disable_ptt &&
172 active_modem->get_mode() == MODE_CW &&
173 ( progdefaults.use_ELCTkeying ||
174 progdefaults.use_ICOMkeying ||
175 progdefaults.use_KNWDkeying ||
176 progdefaults.use_YAESUkeying ||
177 progStatus.nanoCW_online ) )
178 return;
179 }
180 new_ptt = on;
181 }
182
183 pthread_mutex_t mutex_flrig_ptt = PTHREAD_MUTEX_INITIALIZER;
184
xmlrpc_rig_show_ptt(void * data)185 void xmlrpc_rig_show_ptt(void *data)
186 {
187 guard_lock flrig_lock(&mutex_flrig_ptt);
188 int on = reinterpret_cast<intptr_t>(data);
189 if (wf && (trx_state != STATE_TUNE)) {
190 wf->xmtrcv->value(on);
191 wf->xmtrcv->do_callback();
192 }
193 }
194
flrig_get_ptt()195 void flrig_get_ptt()
196 {
197 try {
198 XmlRpcValue result;
199 bool ret;
200 {
201 guard_lock flrig_lock(&mutex_flrig);
202 ret = flrig_client->execute("rig.get_ptt", XmlRpcValue(), result, timeout);
203 }
204 if (ret) {
205 int val = (int)result;
206 ptt_state = val;
207 LOG_VERBOSE("get_ptt: %s", ptt_state ? "ON" : "OFF");
208 return;
209 }
210 connected_to_flrig = false;
211 LOG_ERROR("%s", "get_ptt failed!");
212 } catch (...) {}
213 }
214
flrig_get_wpm()215 void flrig_get_wpm()
216 {
217 if (!connected_to_flrig) {
218 return;
219 }
220 try {
221 XmlRpcValue result;
222 bool ret;
223 {
224 guard_lock flrig_lock(&mutex_flrig);
225 ret = flrig_client->execute("rig.cwio_get_wpm", XmlRpcValue(), result, timeout);
226 }
227 if (ret) {
228 int val = (int)result;
229 progdefaults.CWspeed = val;
230 LOG_VERBOSE("rig.cwio_get_wpm = %d", val);
231 return;
232 }
233 connected_to_flrig = false;
234 LOG_ERROR("%s failed!", "flrig_get_wpm");
235 } catch (...) {
236 LOG_ERROR("rig.cwio_get_wpm FAILED");
237 }
238 }
239
flrig_set_wpm()240 void flrig_set_wpm() {
241 if (!connected_to_flrig) {
242 return;
243 }
244 XmlRpcValue val, result;
245 try {
246 bool ret;
247 val = (int)static_cast<int>(progdefaults.CWspeed);
248 {
249 guard_lock flrig_lock(&mutex_flrig);
250 ret = flrig_client->execute("rig.cwio_set_wpm", val, result, timeout);
251 }
252 if (ret) {
253 LOG_VERBOSE("set wpm %f", progdefaults.CWspeed);
254 return;
255 }
256 } catch (...) {
257 }
258
259 LOG_ERROR("set wpm failed");
260 return;
261 }
262
263 //----------------------------------------------------------------------
264 // transceiver radio frequency
265 //----------------------------------------------------------------------
266
267 static bool wait_freq = false; // wait for transceiver to respond
268 static int wait_freq_timeout = 5; // 5 polls and then disable wait
269 static unsigned long int xcvr_freq = 0;
270
271 pthread_mutex_t mutex_flrig_freq = PTHREAD_MUTEX_INITIALIZER;
272
xmlrpc_rig_show_freq(void * fr)273 void xmlrpc_rig_show_freq(void * fr)
274 {
275 guard_lock flrig_lock(&mutex_flrig_freq);
276 if (!wf) return;
277 unsigned long int freq = reinterpret_cast<intptr_t>(fr);
278 LOG_VERBOSE("xmlrpc_rig_show_freq %lu", freq);
279 wf->rfcarrier(freq);
280 wf->movetocenter();
281 show_frequency(freq);
282 }
283
set_flrig_freq(unsigned long int fr)284 void set_flrig_freq(unsigned long int fr)
285 {
286 if (!connected_to_flrig) return;
287
288 XmlRpcValue val, result;
289 try {
290 val = (double)fr;
291 bool ret;
292 {
293 guard_lock flrig_lock(&mutex_flrig);
294 ret = flrig_client->execute("rig.set_vfo", val, result, timeout);
295 }
296 if (ret) {
297 LOG_VERBOSE("set freq: %lu", fr);
298 return;
299 }
300 LOG_ERROR("%s", "rig.set_vfo failed");
301 wait_freq = false;
302 wait_freq_timeout = 0;
303 } catch (...) {
304 LOG_ERROR("rig.set_vfo FAILED");
305 }
306 }
307
flrig_get_frequency()308 void flrig_get_frequency()
309 {
310 XmlRpcValue result;
311 try {
312 if (!freq_posted) return;
313 bool ret;
314 {
315 guard_lock flrig_lock(&mutex_flrig);
316 ret = flrig_client->execute("rig.get_vfo", XmlRpcValue(), result, timeout);
317 }
318 if (ret) {
319 str_freq = (string)result;
320 unsigned long int fr = atoll(str_freq.c_str());
321
322 if (!wait_freq && (fr != xcvr_freq)) {
323 xcvr_freq = fr;
324 guard_lock flrig_lock(&mutex_flrig_freq);
325 Fl::awake(xmlrpc_rig_show_freq, reinterpret_cast<void*>(fr));
326 LOG_VERBOSE("get freq: %lu", fr);
327 } else if (wait_freq && (fr == xcvr_freq)) {
328 wait_freq = false;
329 wait_freq_timeout = 0;
330 } else if (wait_freq_timeout == 0) {
331 wait_freq = false;
332 } else if (wait_freq_timeout)
333 --wait_freq_timeout;
334 } else {
335 connected_to_flrig = false;
336 wait_freq = false;
337 wait_freq_timeout = 5;
338 LOG_ERROR("%s", "get freq failed");
339 }
340 } catch (...) {}
341 }
342
343 //----------------------------------------------------------------------
344 // transceiver set / get mode
345 // transceiver get modes (mode table)
346 //----------------------------------------------------------------------
347
348 static bool wait_mode = false; // wait for transceiver to respond
349 static int wait_mode_timeout = 5; // 5 polls and then disable wait
350 static string posted_mode = "";
351
352 static bool wait_bw = false; // wait for transceiver to respond
353 static int wait_bw_timeout = 5; // 5 polls and then disable wait
354 static bool need_sideband = false;
355 static string posted_bw = "";
356 static string posted_bw1 = "";
357 static string posted_bw2 = "";
358
set_flrig_mode(const char * md)359 void set_flrig_mode(const char *md)
360 {
361 if (!connected_to_flrig) return;
362
363 XmlRpcValue val, result;
364 try {
365 val = string(md);
366
367 bool ret;
368 {
369 guard_lock flrig_lock(&mutex_flrig);
370 ret = flrig_client->execute("rig.set_mode", val, result, timeout);
371 }
372 if (ret) {
373 posted_mode = md;
374 need_sideband = true;
375 bws_posted = false;
376 wait_mode = true;
377 wait_mode_timeout = 10;
378 wait_bws_timeout = 5;
379 qso_opBW->hide();
380 qso_opGROUP->hide();
381 LOG_VERBOSE("set mode: %s", md);
382 } else {
383 LOG_ERROR("%s", "rig.set_mode failed");
384 wait_mode = false;
385 wait_mode_timeout = 10;
386 }
387 } catch (...) {}
388 }
389
390 pthread_mutex_t mutex_flrig_mode = PTHREAD_MUTEX_INITIALIZER;
391 static bool xml_USB = true;
392
xmlrpc_USB()393 bool xmlrpc_USB()
394 {
395 return xml_USB;
396 }
397
xmlrpc_rig_post_mode(void * data)398 void xmlrpc_rig_post_mode(void *data)
399 {
400 guard_lock flrig_lock(&mutex_flrig_mode);
401 if (!qso_opMODE) return;
402 string *s = reinterpret_cast<string *>(data);
403 qso_opMODE->value(s->c_str());
404 bws_posted = false;
405 need_sideband = false;
406 }
407
flrig_get_mode()408 void flrig_get_mode()
409 {
410 XmlRpcValue res;
411 try {
412 bool ret;
413 {
414 guard_lock flrig_lock(&mutex_flrig);
415 ret = flrig_client->execute("rig.get_mode", XmlRpcValue(), res, timeout);
416 }
417 if (ret) {
418 static string md;
419 md = (string)res;
420 bool posted = (md == posted_mode);
421 if (!wait_mode && (!posted || need_sideband)) {
422 posted_mode = md;
423 guard_lock flrig_modelock(&mutex_flrig_mode);
424 {
425 guard_lock flrig_lock(&mutex_flrig);
426 ret = flrig_client->execute("rig.get_sideband", XmlRpcValue(), res, timeout);
427 }
428 if (ret) {
429 static string sb;
430 sb = (string)res;
431 xml_USB = (sb[0] == 'U');
432 } else {
433 xml_USB = true;
434 }
435 if (posted) {
436 need_sideband = false;
437 return;
438 }
439 Fl::awake(xmlrpc_rig_post_mode, reinterpret_cast<void*>(&md));
440 LOG_VERBOSE("get mode: %s:%s", md.c_str(), xml_USB ? "USB" : "LSB");
441 } else if (wait_mode && posted) {
442 wait_mode = false;
443 wait_mode_timeout = 0;
444 } else if (wait_mode_timeout == 0) {
445 wait_mode = false;
446 } else if (wait_mode_timeout)
447 --wait_mode_timeout;
448 } else {
449 connected_to_flrig = false;
450 wait_mode = false;
451 wait_freq_timeout = 0;
452 LOG_ERROR("%s", "get mode failed");
453 }
454 } catch (...) {}
455 }
456
457 pthread_mutex_t mutex_flrig_modes = PTHREAD_MUTEX_INITIALIZER;
xmlrpc_rig_post_modes(void *)458 void xmlrpc_rig_post_modes(void *)
459 {
460 guard_lock flrig_lock(&mutex_flrig_modes);
461 if (!qso_opMODE) return;
462
463 int nargs = modes_result.size();
464
465 qso_opMODE->clear();
466
467 if (nargs == 0) {
468 qso_opMODE->add("");
469 qso_opMODE->index(0);
470 qso_opMODE->deactivate();
471 return;
472 }
473
474 std::string smodes;
475 for (int i = 0; i < nargs; i++)
476 smodes.append((string)modes_result[i]).append("|");
477 qso_opMODE->add(smodes.c_str());
478
479 qso_opMODE->index(0);
480 qso_opMODE->activate();
481
482 modes_posted = true;
483 bws_posted = false;
484 }
485
flrig_get_modes()486 void flrig_get_modes()
487 {
488 try {
489 bool ret;
490 {
491 guard_lock flrig_lock(&mutex_flrig);
492 ret = flrig_client->execute("rig.get_modes", XmlRpcValue(), modes_result, timeout);
493 }
494 if (ret) {
495 guard_lock flrig_lock(&mutex_flrig_modes);
496 Fl::awake(xmlrpc_rig_post_modes);
497 posted_mode = posted_bw = posted_bw1 = posted_bw2 = "GETME";
498 {
499 int nargs = modes_result.size();
500 static string debugstr;
501 debugstr.assign("Mode table: ");
502 for (int i = 0; i < nargs - 1; i++)
503 debugstr.append((string)modes_result[i]).append(",");
504 debugstr.append(modes_result[nargs-1]);
505 LOG_VERBOSE("%s", debugstr.c_str());
506 }
507 } else {
508 LOG_ERROR("%s", "get modes failed");
509 }
510 } catch (...) {}
511 }
512
513 //----------------------------------------------------------------------
514 // transceiver get / set bandwidth
515 // transceiver get bandwidth table
516 //----------------------------------------------------------------------
517
set_flrig_bw(int bw2,int bw1)518 void set_flrig_bw(int bw2, int bw1)
519 {
520 if (!connected_to_flrig) return;
521
522 XmlRpcValue val, result;
523 try {
524 int ival = bw2;
525 if (bw1 > -1) ival = 256*(bw1+128) + bw2;
526 val = ival;
527
528 LOG_VERBOSE("set_flrig_bw %04X", ival);
529 bool ret;
530 {
531 guard_lock flrig_lock(&mutex_flrig);
532 ret = flrig_client->execute("rig.set_bw", val, result, timeout);
533 }
534 if (ret) {
535 wait_bw = true;
536 wait_bw_timeout = 5;
537 } else {
538 LOG_ERROR("%s", "rig.set_bw failed");
539 wait_bw = false;
540 wait_bw_timeout = 0;
541 }
542 } catch (...) {}
543 }
544
545 pthread_mutex_t mutex_flrig_bw = PTHREAD_MUTEX_INITIALIZER;
xmlrpc_rig_post_bw(void *)546 void xmlrpc_rig_post_bw(void *)
547 {
548 guard_lock flrig_lock(&mutex_flrig_bw);
549 if (!qso_opBW) return;
550
551 if (posted_bw != (std::string)(qso_opBW->value())) {
552 qso_opBW->value(posted_bw);//.c_str());
553 qso_opBW->redraw();
554 LOG_VERBOSE("Update BW %s", posted_bw.c_str());
555 }
556 qso_opBW->show();
557 }
558
xmlrpc_rig_post_bw1(void *)559 void xmlrpc_rig_post_bw1(void *)
560 {
561 guard_lock flrig_lock(&mutex_flrig_bw);
562 if (!qso_opBW1) return;
563
564 if (posted_bw1 != (std::string)(qso_opBW1->value())) {
565 qso_opBW1->value(posted_bw1);//.c_str());
566 qso_opBW1->redraw();
567 LOG_VERBOSE("Update combo BW1 %s", posted_bw1.c_str());
568 }
569 qso_opGROUP->show();
570 }
571
xmlrpc_rig_post_bw2(void *)572 void xmlrpc_rig_post_bw2(void *)
573 {
574 guard_lock flrig_lock(&mutex_flrig_bw);
575 if (!qso_opBW2) return;
576
577 if (posted_bw2 != (std::string)(qso_opBW2->value())) {
578 qso_opBW2->value(posted_bw2);//.c_str());
579 qso_opBW2->redraw();
580 LOG_VERBOSE("Update combo BW2 %s", posted_bw2.c_str());
581 }
582 qso_opGROUP->show();
583 }
584
do_flrig_get_bw()585 void do_flrig_get_bw()
586 {
587 XmlRpcValue res;
588 try {
589 bool ret;
590 {
591 guard_lock flrig_lock(&mutex_flrig);
592 ret = flrig_client->execute("rig.get_bw", XmlRpcValue(), res, timeout);
593 }
594 if (ret) {
595 static string s1;
596 static string s2;
597
598 s2 = (string)res[0];
599 s1 = (string)res[1];
600 if (!s1.empty()) {
601 posted_bw1 = s1;
602 Fl::awake(xmlrpc_rig_post_bw1);
603 posted_bw2 = s2;
604 Fl::awake(xmlrpc_rig_post_bw2);
605 } else {
606 if (!s2.empty()) {
607 posted_bw = s2;
608 Fl::awake(xmlrpc_rig_post_bw);
609 }
610 }
611 wait_bw_timeout = 0;
612 } else {
613 connected_to_flrig = false;
614 wait_bw_timeout = 0;
615 LOG_ERROR("%s", "get bw failed!");
616 }
617 } catch (...) {
618 }
619 }
620
flrig_get_bw()621 void flrig_get_bw()
622 {
623 if (wait_bw_timeout) {
624 wait_bw_timeout--;
625 return;
626 }
627 do_flrig_get_bw();
628 }
629
630 pthread_mutex_t mutex_flrig_bws = PTHREAD_MUTEX_INITIALIZER;
xmlrpc_rig_post_bws(void *)631 void xmlrpc_rig_post_bws(void *)
632 {
633 if (!qso_opBW) return;
634
635 int nargs;
636
637 try { // two BW controls
638 nargs = bws_result[1].size();
639
640 static string bwstr;
641 qso_opBW1->clear();
642 for (int i = 1; i < nargs; i++) {
643 bwstr = (string)bws_result[1][i];
644 qso_opBW1->add(bwstr.c_str());
645 }
646
647 string labels1 = (string)bws_result[1][0];
648 static char btn1_label[2];
649 btn1_label[0] = labels1[0]; btn1_label[1] = 0;
650 qso_btnBW1->label(btn1_label);
651 qso_btnBW1->redraw_label();
652 qso_btnBW1->redraw();
653 static char tooltip1[20];
654 snprintf(tooltip1,sizeof(tooltip1),"%s",labels1.substr(2).c_str());
655 qso_opBW1->tooltip(tooltip1);
656 qso_opBW1->index(0);
657 qso_opBW1->redraw();
658
659 {
660 static string debugstr;
661 debugstr.assign("\nBW1 table: ");
662 for (int i = 1; i < nargs-1; i++)
663 debugstr.append((string)bws_result[1][i]).append(", ");
664 debugstr.append((string)bws_result[1][nargs - 1]).append("\n");
665 debugstr.append(labels1);
666 LOG_VERBOSE("%s", debugstr.c_str());
667 }
668
669 try {
670 nargs = bws_result[0].size();
671
672 static string bwstr;
673 qso_opBW2->clear();
674 for (int i = 1; i < nargs; i++) {
675 bwstr = (string)bws_result[0][i];
676 qso_opBW2->add(bwstr.c_str());
677 }
678
679 string labels2 = (string)bws_result[0][0];
680 static char btn2_label[2];
681 btn2_label[0] = labels2[0]; btn2_label[1] = 0;
682 qso_btnBW2->label(btn2_label);
683 qso_btnBW2->redraw_label();
684 qso_btnBW2->redraw();
685 static char tooltip2[20];
686 snprintf(tooltip2,sizeof(tooltip2),"%s",labels2.substr(2).c_str());
687 qso_opBW2->tooltip(tooltip2);
688 qso_opBW2->index(0);
689 qso_opBW2->redraw();
690
691 {
692 static string debugstr;
693 debugstr.assign("\nBW2 table: ");
694 for (int i = 1; i < nargs-1; i++)
695 debugstr.append((string)bws_result[0][i]).append(", ");
696 debugstr.append((string)bws_result[0][nargs - 1]).append("\n");
697 debugstr.append(labels2);
698 LOG_VERBOSE("%s", debugstr.c_str());
699 }
700
701 } catch ( XmlRpcException err) {
702 bws_posted = false;
703 return;
704 }
705 qso_opBW->hide();
706 bws_posted = true;
707 return;
708 } catch (XmlRpcException err) {
709 try { // one BW control
710 nargs = bws_result[0].size();
711 string bwstr;
712 qso_opBW->clear();
713 for (int i = 1; i < nargs; i++) {
714 bwstr.append((string)bws_result[0][i]).append("|");
715 }
716 qso_opBW->add(bwstr.c_str());
717 qso_opBW->index(0);
718 qso_opBW->activate();
719 qso_opBW->tooltip("xcvr bandwidth");
720 qso_opGROUP->hide();
721
722 {
723 static string debugstr;
724 debugstr.assign("BW table: ");
725 for (int i = 1; i < nargs-1; i++)
726 debugstr.append((string)bws_result[0][i]).append(", ");
727 debugstr.append((string)bws_result[0][nargs - 1]);
728 LOG_VERBOSE("%s", debugstr.c_str());
729 }
730
731 } catch (XmlRpcException err) {
732 LOG_ERROR("%s", "no bandwidths specified");
733 qso_opBW->add("");
734 qso_opBW->index(0);
735 qso_opBW->deactivate();
736 return;
737 }
738 }
739 bws_posted = true;
740 do_flrig_get_bw();
741 }
742
flrig_get_bws()743 void flrig_get_bws()
744 {
745 if (bws_posted)
746 return;
747 if (wait_bws_timeout) {
748 wait_bws_timeout--;
749 return;
750 }
751 XmlRpcValue result;
752 try {
753 bool ret;
754 {
755 guard_lock flrig_lock(&mutex_flrig);
756 ret = flrig_client->execute("rig.get_bws", XmlRpcValue(), bws_result, timeout);
757 }
758 if (ret) {
759 bws_posted = false;
760 wait_bw = true;
761 wait_bw_timeout = 5;
762 posted_bw.clear();
763 Fl::awake(xmlrpc_rig_post_bws);
764 } else {
765 LOG_ERROR("%s", "get bws failed");
766 }
767 } catch (...) {}
768 }
769
770 //----------------------------------------------------------------------
771 // transceiver get / set vfo A / B
772 //----------------------------------------------------------------------
773
set_flrig_ab(int n)774 void set_flrig_ab(int n)
775 {
776 }
777
show_A(void *)778 void show_A(void *)
779 {
780 }
781
show_B(void *)782 void show_B(void *)
783 {
784 }
785
flrig_get_vfo()786 void flrig_get_vfo()
787 {
788 XmlRpcValue result;
789 try {
790 bool ret;
791 {
792 guard_lock flrig_lock(&mutex_flrig);
793 ret = flrig_client->execute("rig.get_AB", XmlRpcValue(), result, timeout);
794 }
795 if (ret) {
796 } else {
797 connected_to_flrig = false;
798 }
799 } catch (...) {}
800 }
801
802 //==============================================================================
803 // transceiver set / get notch
804 //==============================================================================
805 static int wait_notch_timeout = 0; // # polls and then disable wait
806
set_flrig_notch()807 void set_flrig_notch()
808 {
809 if (!connected_to_flrig) return;
810
811 XmlRpcValue val, result;
812 try {
813 val = (int)notch_frequency;
814 bool ret;
815 {
816 guard_lock flrig_lock(&mutex_flrig);
817 ret = flrig_client->execute("rig.set_notch", val, result, timeout);
818 }
819 if (ret) {
820 wait_notch_timeout = 2;
821 } else {
822 LOG_ERROR("%s", "rig.set_notch failed");
823 wait_notch_timeout = 0;
824 }
825 } catch (...) {}
826 }
827
flrig_get_notch()828 void flrig_get_notch()
829 {
830 if (wait_notch_timeout == 0)
831 try {
832 bool ret;
833 {
834 guard_lock flrig_lock(&mutex_flrig);
835 ret = flrig_client->execute("rig.get_notch", XmlRpcValue(), notch_result, timeout);
836 }
837 if (ret) {
838 notch_frequency = (int)notch_result;
839 LOG_VERBOSE("rig_get_notch: %d", notch_frequency);
840 }
841 } catch (...) {
842 LOG_ERROR("rig.get_notch FAILED");
843 }
844 else
845 wait_notch_timeout--;
846 }
847
848 //==============================================================================
849 // transceiver get smeter
850 // transceiver get power meter
851 //==============================================================================
852
853 pthread_mutex_t mutex_flrig_smeter = PTHREAD_MUTEX_INITIALIZER;
xmlrpc_rig_set_smeter(void * data)854 static void xmlrpc_rig_set_smeter(void *data)
855 {
856 guard_lock flrig_lock(&mutex_flrig_smeter);
857
858 if (smeter && progStatus.meters) {
859 if (!smeter->visible()) {
860 if (pwrmeter) pwrmeter->hide();
861 smeter->show();
862 }
863 int val = reinterpret_cast<intptr_t>(data);
864 smeter->value(val);
865 }
866 }
867
flrig_get_smeter()868 void flrig_get_smeter()
869 {
870 XmlRpcValue result;
871 try {
872 bool ret;
873 {
874 guard_lock flrig_lock(&mutex_flrig);
875 ret = flrig_client->execute("rig.get_smeter", XmlRpcValue(), result, timeout);
876 }
877 if (ret) {
878 std::string smeter = (string)result;
879 int sm = atoll(smeter.c_str());
880 guard_lock lck(&mutex_flrig_smeter);
881 Fl::awake(xmlrpc_rig_set_smeter, reinterpret_cast<void*>(sm));
882 LOG_VERBOSE("rig.get_smeter: %d", sm);
883 }
884 } catch (...) {
885 LOG_ERROR("rig.get_smeter FAILED");
886 }
887 }
888
889 pthread_mutex_t mutex_flrig_pwrmeter = PTHREAD_MUTEX_INITIALIZER;
xmlrpc_rig_set_pwrmeter(void * data)890 static void xmlrpc_rig_set_pwrmeter(void *data)
891 {
892 guard_lock flrig_lock(&mutex_flrig_pwrmeter);
893 if (!smeter && !pwrmeter) return;
894
895 if (pwrmeter && progStatus.meters) {
896 if (!pwrmeter->visible()) {
897 smeter->hide();
898 pwrmeter->show();
899 }
900 int val = reinterpret_cast<intptr_t>(data);
901 pwrmeter->value(val);
902 }
903 }
904
flrig_get_pwrmeter()905 void flrig_get_pwrmeter()
906 {
907 XmlRpcValue val, result;
908 try {
909 bool ret;
910 {
911 guard_lock flrig_lock(&mutex_flrig);
912 ret = flrig_client->execute("rig.get_pwrmeter", val, result, timeout);
913 }
914 if (ret) {
915 std::string meter = (string)result;
916 int sm = atoll(meter.c_str());
917 guard_lock lck(&mutex_flrig_pwrmeter);
918 Fl::awake(xmlrpc_rig_set_pwrmeter, reinterpret_cast<void*>(sm));
919 }
920 } catch (...) {
921 LOG_ERROR("rig.get_pwrmeter FAILED");
922 }
923 }
924
925 //==============================================================================
926 // transceiver get name
927 //==============================================================================
928
xmlrpc_rig_show_xcvr_name(void *)929 static void xmlrpc_rig_show_xcvr_name(void *)
930 {
931 xcvr_title = xcvr_name;
932 setTitle();
933 }
934
no_rig_init(void *)935 static void no_rig_init(void *)
936 {
937 init_NoRig_RigDialog();
938 }
939
flrig_get_xcvr()940 bool flrig_get_xcvr()
941 {
942 XmlRpcValue result;
943 try {
944 bool ret;
945 {
946 guard_lock flrig_lock(&mutex_flrig);
947 ret = flrig_client->execute("rig.get_xcvr", XmlRpcValue(), result, timeout);
948 }
949 if (ret) {
950 string nuxcvr = (string)result;
951 if (nuxcvr != xcvr_name) {
952 xcvr_name = nuxcvr;
953 modes_posted = false;
954 bws_posted = false;
955 flrig_get_modes();
956 flrig_get_bws();
957 flrig_get_mode();
958 flrig_get_bw();
959 Fl::awake(xmlrpc_rig_show_xcvr_name);
960 LOG_VERBOSE("flrig_get_xcvr %s", nuxcvr.c_str());
961 }
962 return true;
963 } else {
964 if (xcvr_name != "") {
965 xcvr_name = "";
966 Fl::awake(xmlrpc_rig_show_xcvr_name);
967 Fl::awake(no_rig_init);
968 }
969 connected_to_flrig = false;
970 }
971 } catch (XmlRpcException *err) {
972 if (xcvr_name != "") {
973 xcvr_name = "";
974 Fl::awake(xmlrpc_rig_show_xcvr_name);
975 Fl::awake(no_rig_init);
976 LOG_ERROR("rig.get_xcvr FAILED");
977 }
978 connected_to_flrig = false;
979 }
980 return false;
981 }
982
983 //======================================================================
984 // xmlrpc read polling thread
985 //======================================================================
986 static bool run_flrig_thread = true;
987 static int poll_interval = 100; // 1 second
988
989 //----------------------------------------------------------------------
990 // Set QSY to true if xmlrpc client connection is OK
991 //----------------------------------------------------------------------
992
flrig_setQSY(void *)993 void flrig_setQSY(void *)
994 {
995 if (!wf) return;
996 wf->setQSY(true);
997 }
998
flrig_connection()999 void flrig_connection()
1000 {
1001 XmlRpcValue noArgs, result;
1002 try {
1003 bool ret;
1004 {
1005 guard_lock flrig_lock(&mutex_flrig);
1006 ret = flrig_client->execute("system.listMethods", noArgs, result, timeout);
1007 }
1008 if (ret) {
1009 int nargs = result.size();
1010 string method_str = "\nMethods:\n";
1011 for (int i = 0; i < nargs; i++)
1012 method_str.append(" ").append(result[i]).append("\n");
1013 LOG_VERBOSE("%s", method_str.c_str());
1014 connected_to_flrig = true;
1015 poll_interval = 20; // every 200 msec
1016 flrig_get_xcvr();
1017 Fl::awake(flrig_setQSY);
1018 } else {
1019 LOG_VERBOSE("%s", "Waiting for flrig");
1020 connected_to_flrig = false;
1021 poll_interval = 200; // every 2 seconds
1022 }
1023 } catch (...) {
1024 LOG_ERROR("%s", "failure in flrig_client");
1025 }
1026 }
1027
connect_to_flrig()1028 void connect_to_flrig()
1029 {
1030 XmlRpc::setVerbosity(xmlrpc_verbosity);
1031 if (flrig_client) {
1032 delete flrig_client;
1033 flrig_client = (XmlRpcClient *)0;
1034 }
1035 try {
1036 flrig_client = new XmlRpcClient(
1037 progdefaults.flrig_ip_address.c_str(),
1038 atol(progdefaults.flrig_ip_port.c_str()));
1039 LOG_VERBOSE("created flrig xmlrpc client %s, %ld",
1040 progdefaults.flrig_ip_address.c_str(),
1041 atol(progdefaults.flrig_ip_port.c_str()));
1042 flrig_connection();
1043 } catch (...) {
1044 LOG_ERROR("Cannot create flrig xmlrpc client %s, %s",
1045 progdefaults.flrig_ip_address.c_str(),
1046 progdefaults.flrig_ip_port.c_str());
1047 }
1048 }
1049
flrig_thread_loop(void * d)1050 void * flrig_thread_loop(void *d)
1051 {
1052 int poll = poll_interval;
1053 while (run_flrig_thread) {
1054
1055 MilliSleep(10);
1056
1057 if (connected_to_flrig) {
1058 if (new_ptt > -1) {
1059 exec_flrig_ptt();
1060 continue;
1061 }
1062 }
1063
1064 if (--poll == 0) {
1065 poll = poll_interval;
1066 if (progdefaults.fldigi_client_to_flrig) {
1067 if (!flrig_client)
1068 connect_to_flrig();
1069 else {
1070 if (!connected_to_flrig)
1071 flrig_connection();
1072 else {
1073 if (progdefaults.flrig_keys_modem) flrig_get_ptt();
1074 if (trx_state == STATE_RX) {
1075 flrig_get_frequency();
1076 flrig_get_smeter();
1077 flrig_get_notch();
1078 flrig_get_wpm();
1079
1080 if (modes_posted)
1081 flrig_get_mode();
1082 else
1083 flrig_get_modes();
1084
1085 if (bws_posted)
1086 flrig_get_bw();
1087 else
1088 flrig_get_bws();
1089 }
1090 else {
1091 flrig_get_pwrmeter();
1092 flrig_get_wpm();
1093 }
1094 }
1095 }
1096 }
1097 }
1098 }
1099 return NULL;
1100 }
1101
FLRIG_start_flrig_thread()1102 void FLRIG_start_flrig_thread()
1103 {
1104 flrig_thread = new pthread_t;
1105 poll_interval = 100; // every second
1106 if (pthread_create(flrig_thread, NULL, flrig_thread_loop, NULL)) {
1107 LOG_ERROR("%s", "flrig_thread create");
1108 exit(EXIT_FAILURE);
1109 }
1110 }
1111
stop_flrig_thread()1112 void stop_flrig_thread()
1113 {
1114 if (!flrig_client) return;
1115 LOG_INFO("%s", "lock mutex_flrig");
1116 pthread_mutex_lock(&mutex_flrig);
1117 run_flrig_thread = false;
1118 pthread_mutex_unlock(&mutex_flrig);
1119 LOG_INFO("%s", "wait for joined thread");
1120 pthread_join(*flrig_thread, NULL);
1121 LOG_INFO("%s", "flrig thread closed");
1122 LOG_INFO("%s", "flrig_client->close()");
1123 flrig_client->close();
1124 }
1125
reconnect_to_flrig()1126 void reconnect_to_flrig()
1127 {
1128 flrig_client->close();
1129 guard_lock flrig_lock(&mutex_flrig);
1130 delete flrig_client;
1131 flrig_client = (XmlRpcClient *)0;
1132 connected_to_flrig = false;
1133 }
1134
1135 unsigned long st, et;
1136
xmlrpc_send_command(std::string cmd)1137 void xmlrpc_send_command(std::string cmd)
1138 {
1139 if (!connected_to_flrig) return;
1140
1141 XmlRpcValue val, result;
1142 try {
1143 guard_lock flrig_lock(&mutex_flrig);
1144 val = std::string(cmd);
1145 flrig_client->execute("rig.cat_string", val, result, timeout);
1146 std::string ans = std::string(result);
1147 } catch (...) {}
1148 return;
1149 }
1150
xmlrpc_priority(std::string cmd)1151 void xmlrpc_priority(std::string cmd)
1152 {
1153 if (!connected_to_flrig) return;
1154
1155 XmlRpcValue val, result;
1156 try {
1157 guard_lock flrig_lock(&mutex_flrig);
1158 val = std::string(cmd);
1159 flrig_client->execute("rig.cat_priority", val, result, 0.20);//timeout);
1160 } catch (...) {}
1161 return;
1162 }
1163
xmlrpc_shutdown_flrig()1164 void xmlrpc_shutdown_flrig()
1165 {
1166 if (!connected_to_flrig) return;
1167
1168 XmlRpcValue val, result;
1169 try {
1170 guard_lock flrig_lock(&mutex_flrig);
1171 if (!flrig_client->execute("rig.shutdown", XmlRpcValue(), result, timeout)) {
1172 LOG_ERROR("%s", "rig.shutdown failed");
1173 } else {
1174 LOG_VERBOSE("%s", "rig.shutdown OK");
1175 }
1176 } catch (...) {}
1177 }
1178
flrig_cwio_ptt(int on)1179 void flrig_cwio_ptt(int on)
1180 {
1181 if (!connected_to_flrig) return;
1182
1183 XmlRpcValue val, result;
1184 try {
1185 guard_lock flrig_lock(&mutex_flrig);
1186 val = (int)on;
1187 flrig_client->execute("rig.cwio_send", val, result, 0.20);//timeout);
1188 } catch (...) {
1189 }
1190 return;
1191 }
1192
flrig_cwio_send_text(string s)1193 void flrig_cwio_send_text(string s)
1194 {
1195 if (!connected_to_flrig) return;
1196
1197 XmlRpcValue val, result;
1198 try {
1199 guard_lock flrig_lock(&mutex_flrig);
1200 val = std::string(s);
1201 flrig_client->execute("rig.cwio_text", val, result, 0.20);//timeout);
1202 } catch (...) {
1203 }
1204 return;
1205 }
1206
1207