diff --git a/src/changepars.c b/src/changepars.c index c2e2d416..95a83504 100644 --- a/src/changepars.c +++ b/src/changepars.c @@ -650,12 +650,12 @@ int changepars(void) { case 51: { /* FLDIGI - turn on/off */ if (digikeyer == FLDIGI) { if (fldigi_toggle()) { - fldigi_clear_connerr(); mvaddstr(13, 29, "FLDIGI ON"); } else { mvaddstr(13, 29, "FLDIGI OFF"); } refreshp(); + sleep(1); } break; } diff --git a/src/fldigixmlrpc.c b/src/fldigixmlrpc.c index a6830261..da1bc0b3 100644 --- a/src/fldigixmlrpc.c +++ b/src/fldigixmlrpc.c @@ -49,11 +49,9 @@ #include "tlf_curses.h" #include "ui_utils.h" -#define XMLRPCVERSION "1.0" - int fldigi_set_callfield = 0; -typedef struct xmlrpc_res_s { +typedef struct { int intval; const char *stringval; const unsigned char *byteval; @@ -76,12 +74,14 @@ static bool connerr = false; char thiscall[20] = ""; char tcomment[20] = ""; -pthread_mutex_t xmlrpc_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t xmlrpc_get_rx_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t xmlrpc_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t xmlrpc_get_rx_mutex = PTHREAD_MUTEX_INITIALIZER; /* - * Used XML RPC methods, and its formats of arguments + * Used Fldigi XML-RPC methods * ================================================== +Method Name Sig (ret:arg) Description +----------------------------------------------------- main.rx n:n - RX main.tx n:n - TX main.get_trx_state s:n - get RX/TX state, 's' could be "RX" | "TX" @@ -105,25 +105,30 @@ modem.set_carrier i:i - set carrier of modem text.get_rx 6:ii - (bytes:int|int) - get part content of RX window [start:length] tx.get_data 6:n - (bytes:) - get content of TX window since last query + + + * XML-RPC Format Specifiers (subset used by Fldigi) + * ================================================= + i 32 bit integer + d double precision floating point number + s string + 6 base64-encoded byte string + n nil + A array */ #ifdef HAVE_LIBXMLRPC -xmlrpc_env env; -xmlrpc_server_info *serverInfoP = NULL; +static xmlrpc_server_info *serverInfoP = NULL; +static xmlrpc_client *clientP = NULL; #endif -void fldigi_clear_connerr() { - pthread_mutex_lock(&xmlrpc_mutex); - connerr = false; - pthread_mutex_unlock(&xmlrpc_mutex); -} - bool fldigi_toggle(void) { bool ret; pthread_mutex_lock(&xmlrpc_mutex); use_fldigi = !use_fldigi; ret = use_fldigi; + connerr = false; pthread_mutex_unlock(&xmlrpc_mutex); return ret; } @@ -137,59 +142,187 @@ bool fldigi_isenabled(void) { return ret; } -void xmlrpc_res_init(xmlrpc_res *res) { #ifdef HAVE_LIBXMLRPC +static void xmlrpc_res_init(xmlrpc_res *res) { + res->intval = 0; res->stringval = NULL; res->byteval = NULL; -#endif } +static void xmlrpc_res_free(xmlrpc_res *res) { + if (res->byteval != NULL) { + free((void *)res->byteval); + } + res->byteval = NULL; + + if (res->stringval != NULL) { + free((void *)res->stringval); + } + res->stringval = NULL; +} + +static void xmlrpc_release() { + if (clientP != NULL) { + xmlrpc_client_destroy(clientP); + clientP = NULL; + } + if (serverInfoP != NULL) { + xmlrpc_server_info_free(serverInfoP); + serverInfoP = NULL; + } + initialized = false; +} + +// set up local xmlrpc client +// env contains error information +static void fldigi_xmlrpc_setup(xmlrpc_env *env) { + xmlrpc_client_setup_global_const(env); + if (env->fault_occurred) { + return; + } + + clientP = NULL; + xmlrpc_client_create(env, XMLRPC_CLIENT_NO_FLAGS, + PACKAGE_NAME, PACKAGE_VERSION, NULL, 0, &clientP); + if (env->fault_occurred) { + return; + } + + serverInfoP = xmlrpc_server_info_new(env, fldigi_url); + if (env->fault_occurred) { + return; + } +} +#endif int fldigi_xmlrpc_init() { + int rc = 0; #ifdef HAVE_LIBXMLRPC pthread_mutex_lock(&xmlrpc_mutex); - xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, PACKAGE_NAME, - XMLRPCVERSION, NULL, 0); - serverInfoP = xmlrpc_server_info_new(&env, fldigi_url); - if (env.fault_occurred != 0) { - serverInfoP = NULL; - initialized = false; - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; + + xmlrpc_env env; + xmlrpc_env_init(&env); + + fldigi_xmlrpc_setup(&env); + if (env.fault_occurred) { + xmlrpc_release(); + rc = -1; + } else { + initialized = true; } - initialized = true; + xmlrpc_env_clean(&env); + pthread_mutex_unlock(&xmlrpc_mutex); #endif - return 0; + return rc; } int fldigi_xmlrpc_cleanup() { #ifdef HAVE_LIBXMLRPC pthread_mutex_lock(&xmlrpc_mutex); - if (serverInfoP != NULL) { - xmlrpc_server_info_free(serverInfoP); - serverInfoP = NULL; - initialized = false; - } + xmlrpc_release(); pthread_mutex_unlock(&xmlrpc_mutex); #endif return 0; } #ifdef HAVE_LIBXMLRPC -int fldigi_xmlrpc_query(xmlrpc_res *local_result, xmlrpc_env *local_env, - char *methodname, char *format, ...) { - static unsigned int connerrcnt = 0; - xmlrpc_value *callresult; - xmlrpc_value *pcall_array = NULL; +// build parameter array for xmlrpc_client_call_server_params() +// returns: the array to be freed by the caller +// on error: NULL +static xmlrpc_value *build_param_array(xmlrpc_env *local_env, + char *format, va_list argptr) { + + xmlrpc_value *pcall_array = xmlrpc_array_new(local_env); + xmlrpc_value *va_param = NULL; - va_list argptr; - int restype; - size_t bytesize = 0; - int ret; + while (*format != '\0') { + if (*format == 's') { + char *s = va_arg(argptr, char *); + va_param = xmlrpc_string_new(local_env, s); + if (local_env->fault_occurred) { + break; + } + xmlrpc_array_append_item(local_env, pcall_array, va_param); + } else if (*format == 'i') { + int d = va_arg(argptr, int); + va_param = xmlrpc_int_new(local_env, d); + xmlrpc_array_append_item(local_env, pcall_array, va_param); + } else if (*format == 'd') { + double f = va_arg(argptr, double); + va_param = xmlrpc_double_new(local_env, f); + xmlrpc_array_append_item(local_env, pcall_array, va_param); + } + + if (local_env->fault_occurred) { + break; + } + + xmlrpc_DECREF(va_param); + va_param = NULL; + + format++; + } + + if (local_env->fault_occurred) { + if (va_param != NULL) { + xmlrpc_DECREF(va_param); + } + xmlrpc_DECREF(pcall_array); + return NULL; + } + + return pcall_array; +} + +static int parse_call_result(xmlrpc_env *local_env, xmlrpc_value *callresult, + xmlrpc_res *result) { + + int restype = xmlrpc_value_type(callresult); + if (restype == XMLRPC_TYPE_DEAD) { + return -1; + } + + if (result == NULL) { // we are not interested in the result... + return 0; + } + + size_t bytesize; + + switch (restype) { + // int + case XMLRPC_TYPE_INT: + xmlrpc_read_int(local_env, callresult, + &result->intval); + break; + // string + case XMLRPC_TYPE_STRING: + xmlrpc_read_string(local_env, callresult, + &result->stringval); + break; + // byte stream + case XMLRPC_TYPE_BASE64: + xmlrpc_read_base64(local_env, callresult, + &bytesize, &result->byteval); + result->intval = (int)bytesize; + break; + } + + return 0; +} + +// call a remote Fldigi method +// result has to be passed uninitalized and then freed by the caller +// alternatively, a NULL result can be passed for a void method +// returns: 0 +// on error: -1 +static int fldigi_xmlrpc_query(xmlrpc_res *result, char *methodname, + char *format, ...) { + + static unsigned int connerrcnt = 0; pthread_mutex_lock(&xmlrpc_mutex); @@ -218,129 +351,70 @@ int fldigi_xmlrpc_query(xmlrpc_res *local_result, xmlrpc_env *local_env, connerrcnt = 0; } - local_result->stringval = NULL; - local_result->byteval = NULL; - - if (!connerr && use_fldigi) { - va_start(argptr, format); - xmlrpc_env_init(local_env); - pcall_array = xmlrpc_array_new(local_env); - while (*format != '\0') { - if (*format == 's') { - char *s = va_arg(argptr, char *); - va_param = xmlrpc_string_new(local_env, s); - if (local_env->fault_occurred) { - va_end(argptr); - connerr = true; - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; - } - xmlrpc_array_append_item(local_env, pcall_array, va_param); - if (local_env->fault_occurred) { - va_end(argptr); - connerr = true; - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; - } - xmlrpc_DECREF(va_param); - } else if (*format == 'd') { - int d = va_arg(argptr, int); - va_param = xmlrpc_int_new(local_env, d); - xmlrpc_array_append_item(local_env, pcall_array, va_param); - if (local_env->fault_occurred) { - va_end(argptr); - connerr = true; - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; - } - xmlrpc_DECREF(va_param); - } else if (*format == 'f') { - double f = va_arg(argptr, double); - va_param = xmlrpc_double_new(local_env, f); - xmlrpc_array_append_item(local_env, pcall_array, va_param); - if (local_env->fault_occurred) { - va_end(argptr); - connerr = true; - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; - } - xmlrpc_DECREF(va_param); - } - format++; - } + if (!use_fldigi || connerr) { + pthread_mutex_unlock(&xmlrpc_mutex); + return -1; + } - va_end(argptr); + if (result != NULL) { + xmlrpc_res_init(result); + } - callresult = xmlrpc_client_call_server_params(local_env, serverInfoP, - methodname, pcall_array); - if (local_env->fault_occurred) { - // error till xmlrpc_call - connerr = true; - xmlrpc_DECREF(pcall_array); - xmlrpc_env_clean(local_env); - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; - } + xmlrpc_env local_env; + xmlrpc_env_init(&local_env); - restype = xmlrpc_value_type(callresult); - if (restype == 0xDEAD) { - xmlrpc_DECREF(callresult); - xmlrpc_DECREF(pcall_array); - xmlrpc_env_clean(local_env); - pthread_mutex_unlock(&xmlrpc_mutex); - return -1; - } + va_list argptr; + va_start(argptr, format); + xmlrpc_value *pcall_array = build_param_array(&local_env, format, argptr); + va_end(argptr); - local_result->intval = 0; + if (pcall_array == NULL) { + connerr = true; + xmlrpc_env_clean(&local_env); + pthread_mutex_unlock(&xmlrpc_mutex); + return -1; + } - switch (restype) { - // int - case XMLRPC_TYPE_INT: - xmlrpc_read_int(local_env, callresult, - &local_result->intval); - break; - // string - case XMLRPC_TYPE_STRING: - xmlrpc_read_string(local_env, callresult, - &local_result->stringval); - break; - // byte stream - case XMLRPC_TYPE_BASE64: - xmlrpc_read_base64(local_env, callresult, - &bytesize, &local_result->byteval); - local_result->intval = (int)bytesize; - break; - } + xmlrpc_value *callresult = NULL; + xmlrpc_client_call2(&local_env, clientP, serverInfoP, + methodname, pcall_array, &callresult); - xmlrpc_DECREF(callresult); + if (local_env.fault_occurred) { + connerr = true; + if (callresult != NULL) { + xmlrpc_DECREF(callresult); + } xmlrpc_DECREF(pcall_array); + xmlrpc_env_clean(&local_env); + pthread_mutex_unlock(&xmlrpc_mutex); + return -1; } - if (!connerr && use_fldigi) - ret = 0; - else - ret = -1; + + int rc = parse_call_result(&local_env, callresult, result); + + xmlrpc_DECREF(callresult); + xmlrpc_DECREF(pcall_array); + xmlrpc_env_clean(&local_env); + pthread_mutex_unlock(&xmlrpc_mutex); - return ret; + return rc; } #endif /* command fldigi to RX now */ void fldigi_to_rx() { #ifdef HAVE_LIBXMLRPC - xmlrpc_res result; - xmlrpc_env env; - fldigi_xmlrpc_query(&result, &env, "main.rx", ""); - fldigi_xmlrpc_query(&result, &env, "text.clear_tx", ""); + fldigi_xmlrpc_query(NULL, "main.rx", ""); + fldigi_xmlrpc_query(NULL, "text.clear_tx", ""); #endif } #ifdef HAVE_LIBXMLRPC static int cancel_tx() { xmlrpc_res result; - xmlrpc_env env; // check the RX/TX status - int rc = fldigi_xmlrpc_query(&result, &env, "main.get_trx_state", ""); + int rc = fldigi_xmlrpc_query(&result, "main.get_trx_state", ""); if (rc != 0) { return -1; } @@ -348,16 +422,11 @@ static int cancel_tx() { // if state is TX, stop it // if the RX success, clear the previous message from TX text window if (strcmp(result.stringval, "TX") == 0) { - free((void *)result.stringval); - result.stringval = NULL; - fldigi_to_rx(); - sleep(2); } - if (result.stringval != NULL) { - free((void *)result.stringval); - } + + xmlrpc_res_free(&result); return 0; } #endif @@ -372,9 +441,6 @@ int fldigi_send_text(char *line) { return 0; // nothing to send } - xmlrpc_res result; - xmlrpc_env env; - char *message = g_malloc0(len + 1 + 2); // worst case: "^r" added, +2 chars // scan line for Ctrl-T/Ctrl-R, remove them and set flags accordingly @@ -410,7 +476,7 @@ int fldigi_send_text(char *line) { } // add message to TX window - rc = fldigi_xmlrpc_query(&result, &env, "text.add_tx", "s", message); + rc = fldigi_xmlrpc_query(NULL, "text.add_tx", "s", message); g_free(message); if (rc != 0) { return -1; @@ -418,7 +484,7 @@ int fldigi_send_text(char *line) { if (start_tx) { /* switch to TX (immediate) */ - rc = fldigi_xmlrpc_query(&result, &env, "main.tx", ""); + rc = fldigi_xmlrpc_query(NULL, "main.tx", ""); } #endif return rc; @@ -433,25 +499,26 @@ int fldigi_get_rx_text(char *line, int len) { #ifdef HAVE_LIBXMLRPC int rc; xmlrpc_res result; - xmlrpc_env env; static int lastpos = 0; int textlen = 0; int retval = 0; int linelen = 0; pthread_mutex_lock(&xmlrpc_get_rx_mutex); - rc = fldigi_xmlrpc_query(&result, &env, "text.get_rx_length", ""); + rc = fldigi_xmlrpc_query(&result, "text.get_rx_length", ""); if (rc != 0) { pthread_mutex_unlock(&xmlrpc_get_rx_mutex); return -1; } textlen = result.intval; + xmlrpc_res_free(&result); + if (lastpos == 0) { lastpos = textlen; } else { if (lastpos < textlen) { - rc = fldigi_xmlrpc_query(&result, &env, "text.get_rx", "dd", + rc = fldigi_xmlrpc_query(&result, "text.get_rx", "ii", lastpos, textlen - lastpos >= len ? len - 1 : textlen - lastpos); @@ -469,12 +536,13 @@ int fldigi_get_rx_text(char *line, int len) { line[linelen] = '\0'; retval = linelen; } - if (result.byteval != NULL) { - free((void *)result.byteval); - } + + xmlrpc_res_free(&result); } } + lastpos = textlen; + pthread_mutex_unlock(&xmlrpc_get_rx_mutex); return retval; @@ -489,15 +557,15 @@ int fldigi_xmlrpc_get_carrier() { #ifdef HAVE_LIBXMLRPC int rc; xmlrpc_res result; - xmlrpc_env env; char fldigi_mode[6] = ""; - rc = fldigi_xmlrpc_query(&result, &env, "modem.get_carrier", ""); + rc = fldigi_xmlrpc_query(&result, "modem.get_carrier", ""); if (rc != 0) { return -1; } fldigi_var_carrier = (int)result.intval; + xmlrpc_res_free(&result); if (!trx_control || rigmode == RIG_MODE_NONE) { return 0; @@ -511,8 +579,8 @@ int fldigi_xmlrpc_get_carrier() { if (fldigi_var_carrier != CENTER_FREQ && abs(CENTER_FREQ - fldigi_var_carrier) > MAXSHIFT) { if (fldigi_var_shift_freq == 0) { - rc = fldigi_xmlrpc_query(&result, &env, - "modem.set_carrier", "d", + rc = fldigi_xmlrpc_query(&result, + "modem.set_carrier", "i", (xmlrpc_int32) CENTER_FREQ); if (rc != 0) { return -1; @@ -525,7 +593,7 @@ int fldigi_xmlrpc_get_carrier() { // determine mode shift (currently for plain RTTY only) int modeshift = 0; int signum = 0; - rc = fldigi_xmlrpc_query(&result, &env, "modem.get_name", ""); + rc = fldigi_xmlrpc_query(&result, "modem.get_name", ""); if (rc != 0) { return -1; } @@ -533,7 +601,7 @@ int fldigi_xmlrpc_get_carrier() { if (strcmp(result.stringval, "RTTY") == 0) { modeshift = 170 / 2; } - free((void *)result.stringval); + xmlrpc_res_free(&result); switch (rigmode) { case RIG_MODE_USB: @@ -571,15 +639,15 @@ int fldigi_xmlrpc_get_carrier() { } /* set the mode in Fldigi */ - rc = fldigi_xmlrpc_query(&result, &env, "rig.set_mode", "s", fldigi_mode); + rc = fldigi_xmlrpc_query(NULL, "rig.set_mode", "s", fldigi_mode); if (rc != 0) { return -1; } fldigi_var_carrier = signum * fldigi_var_carrier + modeshift; /* also set the freq value in Fldigi FREQ block */ - rc = fldigi_xmlrpc_query(&result, &env, - "rig.set_frequency", "f", + rc = fldigi_xmlrpc_query(NULL, + "rig.set_frequency", "d", (xmlrpc_double)(freq - fldigi_var_carrier)); if (rc != 0) { return -1; @@ -602,58 +670,51 @@ int fldigi_get_log_call() { #ifdef HAVE_LIBXMLRPC int rc; xmlrpc_res result; - xmlrpc_env env; - - xmlrpc_res_init(&result); - char tempstr[20]; int i, j; - - rc = fldigi_xmlrpc_query(&result, &env, "log.get_call", ""); + rc = fldigi_xmlrpc_query(&result, "log.get_call", ""); if (rc != 0) { return -1; - } else { - if (result.stringval != NULL) { - j = 0; - // accept only alphanumeric chars and '/' in callsign - // in case of QRM, there are many several metachar - for (i = 0; i < 20 && result.stringval[i] != '\0'; i++) { - if (isalnum(result.stringval[i]) || result.stringval[i] == '/') { - tempstr[j++] = result.stringval[i]; - } - } - tempstr[j] = '\0'; + } - // check the current call in Tlf; if the previous local callsign isn't empty, - // that means the OP clean up the callsign field, so it needs to clean in Fldigi too - if (current_qso.call[0] == '\0' && thiscall[0] != '\0') { - thiscall[0] = '\0'; - rc = fldigi_xmlrpc_query(&result, &env, "log.set_call", "s", ""); - if (rc != 0) { - return -1; - } + if (result.stringval != NULL) { + j = 0; + // accept only alphanumeric chars and '/' in callsign + // in case of QRM, there are many several metachar + for (i = 0; i < 20 && result.stringval[i] != '\0'; i++) { + if (isalnum(result.stringval[i]) || result.stringval[i] == '/') { + tempstr[j++] = result.stringval[i]; } - // otherwise, fill the callsign field in Tlf - else { - if (strlen(tempstr) >= 3) { - if (current_qso.call[0] == '\0') { - strcpy(current_qso.call, tempstr); - current_qso.call[strlen(tempstr)] = '\0'; - strcpy(thiscall, current_qso.call); - printcall(); - getctydata_pfx(current_qso.call); - searchlog(); - fldigi_set_callfield = 1; - } - } + } + tempstr[j] = '\0'; + + xmlrpc_res_free(&result); + + // check the current call in Tlf; if the previous local callsign isn't empty, + // that means the OP clean up the callsign field, so it needs to clean in Fldigi too + if (current_qso.call[0] == '\0' && thiscall[0] != '\0') { + thiscall[0] = '\0'; + rc = fldigi_xmlrpc_query(NULL, "log.set_call", "s", ""); + if (rc != 0) { + return -1; } } - free((void *)result.stringval); - if (result.byteval != NULL) { - free((void *)result.byteval); + // otherwise, fill the callsign field in Tlf + else { + if (strlen(tempstr) >= 3 && current_qso.call[0] == '\0') { + strcpy(current_qso.call, tempstr); + current_qso.call[strlen(tempstr)] = '\0'; + strcpy(thiscall, current_qso.call); + printcall(); + getctydata_pfx(current_qso.call); + searchlog(); + fldigi_set_callfield = 1; + } } } + + xmlrpc_res_free(&result); #endif return 0; } @@ -663,51 +724,48 @@ int fldigi_get_log_serial_number() { #ifdef HAVE_LIBXMLRPC int rc; xmlrpc_res result; - xmlrpc_env env; - - xmlrpc_res_init(&result); char tempstr[20]; int i, j; - rc = fldigi_xmlrpc_query(&result, &env, "log.get_exchange", ""); + rc = fldigi_xmlrpc_query(&result, "log.get_exchange", ""); if (rc != 0) { return -1; - } else { - if (result.stringval != NULL) { - j = 0; - // accept only alphanumeric chars - for (i = 0; i < 20 && result.stringval[i] != '\0'; i++) { - if (isalnum(result.stringval[i])) { - tempstr[j++] = result.stringval[i]; - } - } - tempstr[j] = '\0'; + } - // if the previous exchange isn't empty, but the current value is it, - // that means the OP cleaned up the field, so we need to clean up it in Fldigi - if (current_qso.comment[0] == '\0' && tcomment[0] != '\0') { - tcomment[0] = '\0'; - rc = fldigi_xmlrpc_query(&result, &env, "log.set_exchange", "s", ""); - if (rc != 0) { - return -1; - } + if (result.stringval != NULL) { + j = 0; + // accept only alphanumeric chars + for (i = 0; i < 20 && result.stringval[i] != '\0'; i++) { + if (isalnum(result.stringval[i])) { + tempstr[j++] = result.stringval[i]; } - // otherwise we need to fill the Tlf exchange field - else { - if (strlen(tempstr) > 0 && current_qso.comment[0] == '\0') { - strcpy(current_qso.comment, tempstr); - current_qso.comment[strlen(tempstr)] = '\0'; - strcpy(tcomment, current_qso.comment); - refresh_comment(); - } + } + tempstr[j] = '\0'; + + xmlrpc_res_free(&result); + + // if the previous exchange isn't empty, but the current value is it, + // that means the OP cleaned up the field, so we need to clean up it in Fldigi + if (current_qso.comment[0] == '\0' && tcomment[0] != '\0') { + tcomment[0] = '\0'; + rc = fldigi_xmlrpc_query(NULL, "log.set_exchange", "s", ""); + if (rc != 0) { + return -1; } } - free((void *)result.stringval); - if (result.stringval != NULL) { - free((void *)result.byteval); + // otherwise we need to fill the Tlf exchange field + else { + if (strlen(tempstr) > 0 && current_qso.comment[0] == '\0') { + strcpy(current_qso.comment, tempstr); + current_qso.comment[strlen(tempstr)] = '\0'; + strcpy(tcomment, current_qso.comment); + refresh_comment(); + } } } + + xmlrpc_res_free(&result); #endif return 0; } diff --git a/src/fldigixmlrpc.h b/src/fldigixmlrpc.h index 53a7e012..06185ecf 100644 --- a/src/fldigixmlrpc.h +++ b/src/fldigixmlrpc.h @@ -38,7 +38,6 @@ void fldigi_to_rx(); void xmlrpc_showinfo(); int fldigi_get_log_call(); int fldigi_get_log_serial_number(); -void fldigi_clear_connerr(); bool fldigi_toggle(void); bool fldigi_isenabled(void);