/*
    Tucnak - VHF contest log
    Copyright (C) 2012-2023 Ladislav Vaiz <ok1zia@nagano.cz>

    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.

*/

#include "header.h"

#include "ac.h"
#include "bfu.h"
#include "dsp.h"
#include "httpd.h"
#include "inputln.h"
#include "kbd.h"
#include "main.h"
#include "menu.h"
#include "net.h"
#include "pa.h"
#include "qsodb.h"
#include "rc.h"
#include "sdr.h"
#include "tsdl.h"

int httpd_enable, httpd_show_priv, httpd_show_links;
char httpd_port_str[EQSO_LEN], httpd_refresh_str[EQSO_LEN];

void refresh_httpd_opts(void *arg){
    cfg->httpd_enable = httpd_enable;
    STORE_SINT(cfg, httpd_port);
    cfg->httpd_show_priv = httpd_show_priv;
    STORE_SINT(cfg, httpd_refresh);
    cfg->httpd_show_links = httpd_show_links;

	free_httpd(httpd);
	httpd = init_httpd();
	progress(NULL);

#ifdef AUTOSAVE
    menu_save_rc(NULL);
#endif
}

void menu_httpd_opts(void *arg){
    struct dialog *d;
    int i;

    httpd_enable = cfg->httpd_enable;
    g_snprintf(httpd_port_str, EQSO_LEN, "%d", cfg->httpd_port);
    httpd_show_priv = cfg->httpd_show_priv;
    g_snprintf(httpd_refresh_str, EQSO_LEN, "%d", cfg->httpd_refresh);
    httpd_show_links = cfg->httpd_show_links;

    d = (struct dialog *)g_malloc(sizeof(struct dialog) + 20 * sizeof(struct dialog_item));
    memset(d, 0, sizeof(struct dialog) + 20 * sizeof(struct dialog_item));
    d->title = VTEXT(T_HTTPD_OPTIONS);//VTEXT(T_RIGOPTS); 
    d->fn = dlg_pf_fn;
    d->refresh = (void (*)(void *))refresh_httpd_opts;
    d->y0 = 1;

    d->items[i = 0].type = D_CHECKBOX;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&httpd_enable;
    d->items[i].msg = CTEXT(T_ENABLE);//CTEXT(T_RIG_QRG_R2T);
    d->items[i].wrap = 1;

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = httpd_port_str;
    d->items[i].maxl = 7;
    d->items[i].fn   = check_number;
    d->items[i].gid  = 1;
    d->items[i].gnum  = 65535;
    d->items[i].msg  = CTEXT(T_TCP_PORT2);//CTEXT(T_RIG_MODEL);
    d->items[i].wrap = 1;

    d->items[++i].type = D_CHECKBOX;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&httpd_show_priv;
    d->items[i].msg = CTEXT(T_PRIVATE);//CTEXT(T_RIG_QRG_R2T);
    d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = httpd_refresh_str;
    d->items[i].maxl = 7;
    d->items[i].fn   = check_number;
    d->items[i].gid  = 0;
    d->items[i].gnum  = 999;
    d->items[i].msg  = CTEXT(T_REFRESH);//CTEXT(T_RIG_MODEL);
    d->items[i].wrap = 1;

    d->items[++i].type = D_CHECKBOX;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&httpd_show_links;
    d->items[i].msg = CTEXT(T_LINKS);
    d->items[i].wrap = 2;
    
    d->items[++i].type = D_BUTTON;   /* 6 */
    d->items[i].gid = B_ENTER;
    d->items[i].fn = ok_dialog;
    d->items[i].text = VTEXT(T_OK);
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ESC;
    d->items[i].fn = cancel_dialog;
    d->items[i].text = VTEXT(T_CANCEL);
    d->items[i].align = AL_BUTTONS;
    d->items[i].wrap = 1;

    d->items[++i].type = D_END;
    do_dialog(d, getml(d, NULL));

}



/* open contest from net */

int load_def, load_cw, load_name, load_qrv;

void refresh_load_from_net(void *arg){
	int load_opts = 0;
    int tok = 0, menui = 0, no = GPOINTER_TO_INT(arg);
	char *peers3, *peer, *id, *tname, *c;

	if (load_def)  load_opts |= LO_DEF;
	if (load_cw)   load_opts |= LO_CW;
	if (load_name) load_opts |= LO_NAME;
	if (load_qrv)  load_opts |= LO_QRV;

	
	peers3 = g_strdup(gnet->peers3->str);
	while ((peer = z_tokenize(peers3, &tok)) != NULL){
		int tok2 = 0;
		id = z_tokenize(peer, &tok2);
		/*op =*/ z_tokenize(peer, &tok2);
		/*rwbands =*/ z_tokenize(peer, &tok2);
		/*cdate =*/ z_tokenize(peer, &tok2);
		/*pcall =*/ z_tokenize(peer, &tok2);
		tname = z_tokenize(peer, &tok2);
        if (!tname) continue;
		if (menui == no){
			c = g_strdup_printf("R3 %s;%s;%d\n", id, gnet->myid, load_opts);
			rel_write_all(c);
			g_free(c);
			break;
		}
        menui++;
	}
    g_free(peers3);
}

void load_from_net(void *arg){
    struct dialog *d;
    int i, tok = 0, menui = 0;
	char *peers3, *peer, *id;
	int no = GPOINTER_TO_INT(arg);

	load_def = 1;
	load_cw = 1;
	load_name = 1;
	load_qrv = 1;

	peers3 = g_strdup(gnet->peers3->str);
	while ((peer = z_tokenize(peers3, &tok)) != NULL){
		int tok2 = 0;
		id = z_tokenize(peer, &tok2);
		if (menui == no){
			char *myid = g_strdup(gnet->myid);
			char *peerid = g_strdup(id);
			z_strip_from(myid, ':');
			z_strip_from(peerid, ':');
			
			if (strcmp(myid, peerid) == 0){
				load_def = 0;
				load_cw = 0;
				load_name = 0;
				load_qrv = 0;
			}
			g_free(myid);
			g_free(peerid);
			break;
		}
        menui++;
	}
    g_free(peers3);

    d = (struct dialog *)g_malloc(sizeof(struct dialog) + 20 * sizeof(struct dialog_item));
    memset(d, 0, sizeof(struct dialog) + 20 * sizeof(struct dialog_item));
    d->title = VTEXT(T_LOAD_FROM_NET);//VTEXT(T_RIGOPTS); 
    d->fn = dlg_pf_fn;
	d->refresh = (void (*)(void *))refresh_load_from_net;
	d->refresh_data = arg;
    d->y0 = 1;

    d->items[i = 0].type = D_CHECKBOX;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&load_def;
    d->items[i].msg = CTEXT(T_LOAD_DEF);
    d->items[i].wrap = 1;

	d->items[++i].type = D_CHECKBOX;  
	d->items[i].gid = 0;
	d->items[i].gnum = 1;
	d->items[i].dlen = sizeof(int);
	d->items[i].data = (char *)&load_cw;
	d->items[i].msg = CTEXT(T_LOAD_CWDB);
	d->items[i].wrap = 1;

	d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 0;
    d->items[i].gnum = 2;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&load_name;
    d->items[i].msg = CTEXT(T_LOAD_NAMEDB);
    d->items[i].wrap = 1;

	d->items[++i].type = D_CHECKBOX;      
    d->items[i].gid = 0;
    d->items[i].gnum = 2;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&load_qrv;
    d->items[i].msg = CTEXT(T_LOAD_QRVDB);
    d->items[i].wrap = 2;
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ENTER;
    d->items[i].fn = ok_dialog;
    d->items[i].text = VTEXT(T_OK);
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ESC;
    d->items[i].fn = cancel_dialog;
    d->items[i].text = VTEXT(T_CANCEL);
    d->items[i].align = AL_BUTTONS;
    d->items[i].wrap = 1;

    d->items[++i].type = D_END;
    do_dialog(d, getml(d, NULL));

}

int robands_data[26];

void refresh_robands(void *arg){
    int i;
    
    if (!ctest) return;
    for (i = 0; i < ctest->bands->len; i++){
        struct band *b;
        if (i == 26) break;

        b = (struct band *)g_ptr_array_index(ctest->bands, i);
        b->readonly = robands_data[i];
        il_readonly(b->il, b->readonly);
    }
}

void robands(void *arg){
    struct dialog *d;
    int i;

    if (!ctest) return;
    if (!ctest->bands->len) return;

    d = (struct dialog *)g_malloc(sizeof(struct dialog) + 30 * sizeof(struct dialog_item));
    memset(d, 0, sizeof(struct dialog) + 30 * sizeof(struct dialog_item));
    d->title = VTEXT(T_READONLY_BANDS);//VTEXT(T_RIGOPTS); 
    d->fn = dlg_pf_fn;
	d->refresh = (void (*)(void *))refresh_robands;
	d->refresh_data = arg;
    d->y0 = 1;

    for (i = 0; i < ctest->bands->len; i++){
        struct band *b;
        if (i == 26) break;

        b = (struct band *)g_ptr_array_index(ctest->bands, i);
        robands_data[i] = b->readonly;
        d->items[i].type = D_CHECKBOX;      
        d->items[i].gid = 0;
        d->items[i].gnum = 1;
        d->items[i].dlen = sizeof(int);
        d->items[i].data = (char *)&robands_data[i];
        d->items[i].msg = b->bandname;
        d->items[i].wrap = 1;
    }
    i--;
    d->items[i].wrap++;
    
    d->items[++i].type = D_BUTTON; 
    d->items[i].gid = B_ENTER;
    d->items[i].fn = ok_dialog;
    d->items[i].text = VTEXT(T_OK);
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ESC;
    d->items[i].fn = cancel_dialog;
    d->items[i].text = VTEXT(T_CANCEL);
    d->items[i].align = AL_BUTTONS;
    d->items[i].wrap = 1;

    d->items[++i].type = D_END;
    do_dialog(d, getml(d, NULL));
}

//-----------------------------------------------------------------------------
void choose_mode(void *itdata, void *menudata)
{
    enum modes m = (enum modes)GPOINTER_TO_INT(itdata);
    set_mode(m);
	default_rst_to_tmpqsos(aband);
	redraw_later();
}

void menu_set_mode(void *itdata, void *menudata)
{
    struct menu_item *mi = NULL;
	int sel = 0;

    if (!(mi = new_menu(0))) return;

	add_to_menu(&mi, CTEXT(T_SSB), "S", "S", MENU_FUNC choose_mode, GINT_TO_POINTER(MOD_SSB_SSB), 0);
	if (gses->mode == MOD_SSB_SSB) sel = 0;

	add_to_menu(&mi, CTEXT(T_CW), "C", "C", MENU_FUNC choose_mode, GINT_TO_POINTER(MOD_CW_CW), 0);
	if (gses->mode == MOD_CW_CW) sel = 1;

	add_to_menu(&mi, CTEXT(T_AM), "A", "A", MENU_FUNC choose_mode, GINT_TO_POINTER(MOD_AM_AM), 0);
	if (gses->mode == MOD_AM_AM) sel = 2;

	add_to_menu(&mi, CTEXT(T_FM), "F", "F", MENU_FUNC choose_mode, GINT_TO_POINTER(MOD_FM_FM), 0);
	if (gses->mode == MOD_FM_FM) sel = 3;

	add_to_menu(&mi, CTEXT(T_RTTY), "R", "R", MENU_FUNC choose_mode, GINT_TO_POINTER(MOD_RTTY_RTTY), 0);
	if (gses->mode == MOD_RTTY_RTTY) sel = 4;

    set_window_ptr(gses->win, (term->x - 6 - 6) / 2, (term->y - 2 - 5) / 2);

	do_menu_selected(mi, NULL, sel);
}


//---- AS --------------------------------------------------------------------


int ac_enable, ac_provider;
char ac_osn_username[MAX_STR_LEN], ac_osn_password[MAX_STR_LEN];
char ac_osn_minutes_str[EQSO_LEN];
char ac_filename[MAX_STR_LEN], new_ac_filename[MAX_STR_LEN];
char ac_adsbone_minutes_str[EQSO_LEN];
char ac_centerwwl[EQSO_LEN];
char ac_kfactor_str[DBL_LEN];
char ac_arwidth_str[DBL_LEN];   
char ac_minelev_str[DBL_LEN];   
char ac_maxelev_str[DBL_LEN];   
char ac_mindur_str[DBL_LEN];       
char ac_maxdelta_str[DBL_LEN];  
char ac_minalt_str[DBL_LEN];
int ac_imperial;
char kst_maxqrb_str[MAX_STR_LEN];

// AC filename
int ac_filename_index = -1;

void ac_opts_fn(struct dialog_data* dlg)
{
    if (strlen(new_ac_filename) > 0 && ac_filename_index >= 0) {
        g_strlcpy(dlg->items[ac_filename_index].cdata, new_ac_filename, MAX_STR_LEN);
        dlg->items[ac_filename_index].cpos = strlen(new_ac_filename);
        strcpy(new_ac_filename, "");
    }
    input_field_fn_i(dlg, ac_filename_index);
}

void refresh_as_filename(void* xxx, char* filename) {
    g_strlcpy(new_ac_filename, filename, MAX_STR_LEN);
    redraw_later();
}

static int dlg_as_filename(struct dialog_data* dlg, struct dialog_item_data* di) {
    zfiledlg_open(zfiledlg, zsel, refresh_as_filename, di, "", "json");
    return 0;
}


void refresh_ac_opts(void *arg){
    STORE_INT(cfg, ac_enable);
    STORE_INT(cfg, ac_provider);
    STORE_STR(cfg, ac_osn_username);
    STORE_STR(cfg, ac_osn_password);
    STORE_SINT(cfg, ac_osn_minutes);
    STORE_SINT(cfg, ac_adsbone_minutes);
    STORE_STR(cfg, ac_filename);
    z_unix(cfg->ac_filename);
    STORE_STR(cfg, ac_centerwwl);
    STORE_SDBL(cfg, ac_kfactor);
    STORE_SDBL(cfg, ac_arwidth);
    STORE_SDBL(cfg, ac_minelev);
    STORE_SDBL(cfg, ac_maxelev);
    STORE_SINT(cfg, ac_mindur);
    STORE_SDBL(cfg, ac_maxdelta);
	STORE_SINT(cfg, ac_minalt);
	STORE_INT(cfg, ac_imperial);
	STORE_SINT(cfg, kst_maxqrb);


	free_acs(gacs);
	gacs = init_acs();
	resize_terminal(NULL);
	progress(NULL);

#ifdef AUTOSAVE
    menu_save_rc(NULL);
#endif
}


void menu_ac_opts(void *arg){
    struct dialog *d;
    int i;

    LOAD_INT(cfg, ac_enable);
    LOAD_INT(cfg, ac_provider);
    LOAD_STR(cfg, ac_osn_username);
    LOAD_STR(cfg, ac_osn_password);
    LOAD_SINT(cfg, ac_osn_minutes);
    LOAD_SINT(cfg, ac_adsbone_minutes);
    g_snprintf(ac_filename, MAX_STR_LEN, "%s", cfg->ac_filename);
    z_wokna(ac_filename);
    LOAD_STR(cfg, ac_centerwwl);
    g_snprintf(ac_kfactor_str, DBL_LEN, "%3.3f", cfg->ac_kfactor);
    g_snprintf(ac_arwidth_str, DBL_LEN, "%3.1f", cfg->ac_arwidth);
    g_snprintf(ac_minelev_str, DBL_LEN, "%3.1f", cfg->ac_minelev);
    g_snprintf(ac_maxelev_str, DBL_LEN, "%3.1f", cfg->ac_maxelev);
    g_snprintf(ac_mindur_str,  DBL_LEN, "%d", cfg->ac_mindur);
    g_snprintf(ac_maxdelta_str, DBL_LEN, "%3.1f", cfg->ac_maxdelta);
    g_snprintf(ac_minalt_str, DBL_LEN, "%d", cfg->ac_minalt);
    LOAD_INT(cfg, ac_imperial);
	LOAD_SINT(cfg, kst_maxqrb);


    d = (struct dialog *)g_malloc(sizeof(struct dialog) + 30 * sizeof(struct dialog_item));
    memset(d, 0, sizeof(struct dialog) + 30 * sizeof(struct dialog_item));
    d->title = VTEXT(T_AC_OPTIONS);
    d->fn = dlg_pf_fn;
    d->fn2 = ac_opts_fn;
    d->refresh = (void (*)(void *))refresh_ac_opts;
    d->y0 = 1;

    d->items[i = 0].type = D_CHECKBOX;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&ac_enable;
    d->items[i].msg = CTEXT(T_ENABLE_AC);
    d->items[i].wrap = 1;
    /////////////////////////////////////////////////////////////
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
    d->items[i].gnum = AC_AIRSCATTER_DK;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char*)&ac_provider;
    d->items[i].msg = TRANSLATE("Airscatter.dk");
    d->items[i].wrap = 1;

    /////////////////////////////////////////////////////////////
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
    d->items[i].gnum = AC_ADSBONE;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char*)&ac_provider;
    d->items[i].msg = TRANSLATE("ADS-B One");

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = ac_adsbone_minutes_str;
    d->items[i].maxl = 4;
    d->items[i].gid = 1;
    d->items[i].gnum = 60;
    d->items[i].msg = TRANSLATE("Interval [minutes]");
    d->items[i].wrap = 1;
    /////////////////////////////////////////////////////////////
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
    d->items[i].gnum = AC_FILE;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char*)&ac_provider;
    d->items[i].msg = TRANSLATE("File (Firefox)");

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = ac_filename;
    d->items[i].maxl = 42;
    d->items[i].msg = TRANSLATE("Feed filename");//CTEXT(T_AC_URL);
    d->items[i].tabcompl = 1;
    ac_filename_index = i;
#ifdef Z_HAVE_SDL
    if (sdl) {
        d->items[++i].type = D_BUTTON;
        d->items[i].fn = dlg_as_filename;
        d->items[i].text = CTEXT(T_RIG_CHOOSE);
    }
    d->items[i].wrap++;
#endif
    /////////////////////////////////////////////////////////////
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
    d->items[i].gnum = AC_OSN;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char*)&ac_provider;
    d->items[i].msg = TRANSLATE("OpenSkyNetwork");

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = ac_osn_username;
    d->items[i].maxl = 10;
    d->items[i].msg = TRANSLATE("Username");

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = ac_osn_password;
    d->items[i].maxl = 10;
    d->items[i].msg = TRANSLATE("Password");

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = ac_osn_minutes_str;
    d->items[i].maxl = 4;
    d->items[i].gid = 2;
    d->items[i].gnum = 60;
    d->items[i].msg = TRANSLATE("Interval [minutes]");
    d->items[i].wrap = 1;

//////////////////////////////////////////////////////
    d->items[i].wrap++;
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = ac_centerwwl;
    d->items[i].maxl = 8;
    d->items[i].msg = TRANSLATE("Alternative center WWL");
    d->items[i].wrap = 1;

    d->items[++i].type = D_FIELD;
    d->items[i].maxl = 7;
    d->items[i].dlen = DBL_LEN;
    d->items[i].data = (char *)&ac_kfactor_str;
    d->items[i].msg = CTEXT(T_K_FACTOR);
    d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;      
    d->items[i].dlen = DBL_LEN;
    d->items[i].maxl = DBL_LEN - 4;
    d->items[i].data = (char *)&ac_arwidth_str;
    d->items[i].msg = CTEXT(T_AC_AREA_WIDTH);
    d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;      
    d->items[i].dlen = DBL_LEN;
    d->items[i].data = (char *)&ac_minelev_str;
    d->items[i].msg = CTEXT(T_AC_EL_ANGLE);
    d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;      
    d->items[i].dlen = DBL_LEN;
    d->items[i].data = (char *)&ac_maxelev_str;
    d->items[i].msg = CTEXT(T_AC_MAX_EL_ANGLE);
    d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;      
    d->items[i].dlen = DBL_LEN;
    d->items[i].maxl = DBL_LEN - 11;
    d->items[i].data = (char *)&ac_mindur_str;
    d->items[i].msg = CTEXT(T_AC_MIN_DURATION);
    d->items[i].wrap = 1;
    
    /*d->items[++i].type = D_FIELD;      
    d->items[i].dlen = DBL_LEN;
    d->items[i].data = (char *)&ac_maxdelta_str;
    d->items[i].msg = CTEXT(T_AC_MAX_DIFF);
    d->items[i].wrap = 1;*/
    
    d->items[++i].type = D_FIELD;      
    d->items[i].dlen = 6;
    d->items[i].data = (char *)&ac_minalt_str;
    d->items[i].fn   = check_number;
    d->items[i].gid  = 0;
    d->items[i].gnum = 20000;
    d->items[i].msg = TRANSLATE("Minimal AS altitude [m]");
    d->items[i].wrap = 1;

	d->items[++i].type = D_CHECKBOX;
	d->items[i].gid = 0;
	d->items[i].gnum = 1;
	d->items[i].dlen = sizeof(int);
	d->items[i].data = (char *)&ac_imperial;
	d->items[i].msg = TRANSLATE("Display AS in imperial units");
	d->items[i].wrap = 1;

	d->items[++i].type = D_FIELD;
	d->items[i].dlen = MAX_STR_LEN;
	d->items[i].data = (char*)&kst_maxqrb_str;
	d->items[i].maxl = 6;
	d->items[i].msg = TRANSLATE("Maximal QRB for KST [km]");// CTEXT(T_KST_MAXQRB);
	d->items[i].wrap = 2;



    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ENTER;
    d->items[i].fn = ok_dialog;
    d->items[i].text = VTEXT(T_OK);
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ESC;
    d->items[i].fn = cancel_dialog;
    d->items[i].text = VTEXT(T_CANCEL);
    d->items[i].align = AL_BUTTONS;
    d->items[i].wrap = 1;

    d->items[++i].type = D_END;
    do_dialog(d, getml(d, NULL));

}

/**************************** SDR ****************************************/

int sdr_enable, sdr_rec_dsp_type, sdr_play_dsp_type;
char sdr_speed_str[EQSO_LEN];
char sdr_af_speed_str[EQSO_LEN];
char sdr_block_str[EQSO_LEN];
char sdr_cw_low_str[EQSO_LEN], sdr_cw_high_str[EQSO_LEN], sdr_ssb_low_str[EQSO_LEN], sdr_ssb_high_str[EQSO_LEN];

// HAVE_ALSA
char sdr_pcm_rec[MAX_STR_LEN];
char sdr_pcm_play[MAX_STR_LEN];

int sdr_pa_rec, sdr_pa_play;
char sdr_pa_rec_src[MAX_STR_LEN], sdr_pa_play_src[MAX_STR_LEN];

#ifdef HAVE_SNDFILE
char sdr_sndfilename[MAX_STR_LEN], sdr_af_filename[MAX_STR_LEN];
#endif
char new_sdr_sndfilename[MAX_STR_LEN], new_sdr_af_filename[MAX_STR_LEN];
char sdr_remoterx[MAX_STR_LEN];

int sdr_sndfilename_index = -1, sdr_af_filename_index = -1;
int sdr_samplerate_index = -1;
int sdr_af_samplerate_index = -1;


#ifdef HAVE_PORTAUDIO


static void pa_rec_src_func(void *arg){
    int active = GPOINTER_TO_INT(arg);

    const PaDeviceInfo *di = Pa_GetDeviceInfo(active);
    g_snprintf(sdr_pa_rec_src, MAX_STR_LEN, "%d: %s", active, di->name);
    sdr_pa_rec = active;
    redraw_later();
}

static int dlg_pa_rec_src(struct dialog_data *dlg, struct dialog_item_data *di){
    int i, max, sel = 0, n;
    struct menu_item *mi;

    max = Pa_GetDeviceCount();
    mi = new_menu(1);
    n = 0;

	for (i = 0; i < max; i++){
    	const PaDeviceInfo *di = Pa_GetDeviceInfo(i);
		if (di->maxInputChannels <= 0) continue;
        add_to_menu(&mi, g_strdup_printf("%d: %s", i, di->name), "", "", MENU_FUNC pa_rec_src_func, GINT_TO_POINTER(i), 0);
		if (i == sdr_pa_rec) sel = n;
        n++;
    }
    do_menu_selected(mi, NULL, sel);
	return 0;
}

static void pa_play_src_func(void *arg){
    int active = GPOINTER_TO_INT(arg);

    const PaDeviceInfo *di = Pa_GetDeviceInfo(active);
    g_snprintf(sdr_pa_play_src, MAX_STR_LEN, "%d: %s", active, di->name);
    sdr_pa_play = active;
    redraw_later();
}

static int dlg_pa_play_src(struct dialog_data *dlg, struct dialog_item_data *di){
    int i, max, sel = 0, n;
    struct menu_item *mi;

    max = Pa_GetDeviceCount();
    mi = new_menu(1);
    n = 0;

	for (i = 0; i < max; i++){
    	const PaDeviceInfo *di = Pa_GetDeviceInfo(i);
		if (di->maxOutputChannels <= 0) continue;
        add_to_menu(&mi, g_strdup_printf("%d: %s", i, di->name), "", "", MENU_FUNC pa_play_src_func, GINT_TO_POINTER(i), 0);
		if (i == sdr_pa_play) sel = n;
        n++;
    }
    do_menu_selected(mi, NULL, sel);
	return 0;
}
#endif

#ifdef HAVE_SNDFILE

// IQ filename
void refresh_sdr_sndfilename(void *xxx, char *filename){
	g_strlcpy(new_sdr_sndfilename, filename, MAX_STR_LEN);
	redraw_later();
}

static int dlg_sdr_sndfilename(struct dialog_data *dlg, struct dialog_item_data *di){
	zfiledlg_open(zfiledlg, zsel, refresh_sdr_sndfilename, di, "", "wav");
	return 0;
}

// AF filename
void refresh_sdr_af_filename(void *xxx, char *filename){
	g_strlcpy(new_sdr_af_filename, filename, MAX_STR_LEN);
	redraw_later();
}

static int dlg_sdr_af_filename(struct dialog_data *dlg, struct dialog_item_data *di){
	zfiledlg_open(zfiledlg, zsel, refresh_sdr_af_filename, di, "", "wav");
	return 0;
}
#endif



void sdr_opts_fn(struct dialog_data *dlg)
{
	if (strlen(new_sdr_sndfilename)>0 && sdr_sndfilename_index >= 0){
        g_strlcpy(dlg->items[sdr_sndfilename_index].cdata, new_sdr_sndfilename, MAX_STR_LEN);
		dlg->items[sdr_sndfilename_index].cpos = strlen(new_sdr_sndfilename);
        strcpy(new_sdr_sndfilename, "");
    }
	if (strlen(new_sdr_af_filename)>0 && sdr_af_filename_index >= 0){
        g_strlcpy(dlg->items[sdr_af_filename_index].cdata, new_sdr_af_filename, MAX_STR_LEN);
		dlg->items[sdr_af_filename_index].cpos = strlen(new_sdr_af_filename);
        strcpy(new_sdr_af_filename, "");
    }
	input_field_fn_i(dlg, sdr_sndfilename_index);
	input_field_fn_i(dlg, sdr_af_filename_index);
}


void refresh_sdr_opts(void *arg){
	int i;

    STORE_INT(cfg, sdr_enable);
    STORE_INT(cfg, sdr_rec_dsp_type);
    STORE_STR(cfg, sdr_pcm_rec);
    STORE_INT(cfg, sdr_pa_rec);
    STORE_INT(cfg, sdr_play_dsp_type);
    STORE_STR(cfg, sdr_pcm_play);
    STORE_INT(cfg, sdr_pa_play);
    STORE_SINT(cfg, sdr_speed);
    STORE_SINT(cfg, sdr_af_speed);
    STORE_SINT(cfg, sdr_block);
    STORE_SDBL(cfg, sdr_cw_low);
    STORE_SDBL(cfg, sdr_cw_high);
    STORE_SDBL(cfg, sdr_ssb_low);
    STORE_SDBL(cfg, sdr_ssb_high);

#ifdef HAVE_SNDFILE
	STORE_STR(cfg, sdr_sndfilename);
	z_unix(sdr_sndfilename);
	STORE_STR(cfg, sdr_af_filename);
	z_unix(sdr_af_filename);
#endif
	STORE_STR(cfg, sdr_remoterx);

#if defined(USE_SDR) && defined(Z_HAVE_SDL)
    if (sdl){
        free_sdr(gsdr);
        gsdr = init_sdr();
        for (i = 0; i < gses->subwins->len; i++){
            struct subwin *sw = (struct subwin *)g_ptr_array_index(gses->subwins, i);
            if (sw->type != SWT_SDR) continue;
            sdr_resize(gsdr, sw);
        }
    }
#endif


	progress(NULL);

#ifdef AUTOSAVE
    menu_save_rc(NULL);
#endif
}

int sdr_check_range(struct dialog_data *dlg, struct dialog_item_data *di){
	double low, high;

	if (check_double(dlg, di)) return 1;
	
	
	low = atof(di->cdata);
	high = atof((di+1)->cdata);
	if (low > high) {
		msg_box(NULL, VTEXT(T_BAD_NUMBER), AL_CENTER, VTEXT(T_BAD_NUMBER_RANGE), NULL, 1, VTEXT(T_CANCEL), NULL, B_ENTER | B_ESC);
        return 1;
	}
	return 0;
}

int check_sdr_af_speed(struct dialog_data *dlg, struct dialog_item_data *di){
	int speed, af_speed, mod;

	if (check_number(dlg, di)) return 1;
	
				   
	speed = atoi(dlg->items[sdr_samplerate_index].cdata);
	af_speed = atoi(dlg->items[sdr_af_samplerate_index].cdata);
	if (af_speed > speed) {
		msg_box(NULL, VTEXT(T_BAD_NUMBER), AL_CENTER, VTEXT(T_AF_SRATE_GREATER_SRATE), NULL, 1, VTEXT(T_CANCEL), NULL, B_ENTER | B_ESC);
        return 1;
	}
	mod = speed % af_speed;
	if (mod != 0) {
		msg_box(NULL, VTEXT(T_BAD_NUMBER), AL_CENTER, VTEXT(T_SRATE_DIVISIBLE), NULL, 1, VTEXT(T_CANCEL), NULL, B_ENTER | B_ESC);
        return 1;
	}
	return 0;
}

void menu_sdr_opts(void *arg){
    struct dialog *d;
    int i;
#ifdef HAVE_PORTAUDIO
    const PaDeviceInfo *di;

	if (!pa_initialised) {
		Pa_Initialize();
		pa_initialised = 1;
	}
#endif

    LOAD_INT(cfg, sdr_enable);
    LOAD_INT(cfg, sdr_rec_dsp_type);
    LOAD_STR(cfg, sdr_pcm_rec);
    LOAD_INT(cfg, sdr_pa_rec);

	LOAD_INT(cfg, sdr_play_dsp_type);
    LOAD_STR(cfg, sdr_pcm_play);
    LOAD_INT(cfg, sdr_pa_play);

    LOAD_SINT(cfg, sdr_speed);
    LOAD_SINT(cfg, sdr_af_speed);
    LOAD_SINT(cfg, sdr_block);
    LOAD_SDBL(cfg, sdr_cw_low);
    LOAD_SDBL(cfg, sdr_cw_high);
    LOAD_SDBL(cfg, sdr_ssb_low);
    LOAD_SDBL(cfg, sdr_ssb_high);
#ifdef HAVE_ALSA
   
#if !defined(HAVE_PORTAUDIO) && !defined(HAVE_SNDFILE)
	sdr_play_dsp_type = DSPT_ALSA;
	sdr_rec_dsp_type = DSPT_ALSA;
#endif
#endif

#ifdef HAVE_PORTAUDIO
	if (cfg->sdr_pa_rec < 0) cfg->sdr_pa_rec = Pa_GetDefaultInputDevice();
    di = Pa_GetDeviceInfo(cfg->sdr_pa_rec);
    if (di)
        g_snprintf(sdr_pa_rec_src, MAX_STR_LEN, "%d: %s", cfg->sdr_pa_rec, di->name);
    else
        safe_strncpy0(sdr_pa_rec_src, VTEXT(T_NO_DEVICE), MAX_STR_LEN);
	
    if (cfg->sdr_pa_play < 0) cfg->sdr_pa_play = Pa_GetDefaultOutputDevice();
    di = Pa_GetDeviceInfo(cfg->sdr_pa_play);
    if (di)
        g_snprintf(sdr_pa_play_src, MAX_STR_LEN, "%d: %s", cfg->sdr_pa_play, di->name);
    else
        safe_strncpy0(sdr_pa_play_src, VTEXT(T_NO_DEVICE), MAX_STR_LEN);
#if !defined(HAVE_ALSA) && !defined(HAVE_SNDFILE)
	sdr_play_dsp_type = DSPT_PORTAUDIO;
	sdr_rec_dsp_type = DSPT_PORTAUDIO;
#endif
#endif

#ifdef HAVE_SNDFILE
	LOAD_STR(cfg, sdr_sndfilename);
	z_wokna(sdr_sndfilename);
	LOAD_STR(cfg, sdr_af_filename);
	z_wokna(sdr_af_filename);
#endif
	strcpy(new_sdr_sndfilename, "");
	strcpy(new_sdr_af_filename, "");
	LOAD_STR(cfg, sdr_remoterx);

    d = (struct dialog *)g_malloc(sizeof(struct dialog) + 50 * sizeof(struct dialog_item));
    memset(d, 0, sizeof(struct dialog) + 50 * sizeof(struct dialog_item));
    d->title = VTEXT(T_SDR_OPTIONS);
    d->fn = dlg_pf_fn;
    d->fn2 = sdr_opts_fn;
    d->refresh = (void (*)(void *))refresh_sdr_opts;
    d->y0 = 1;

	d->items[i=0].type = D_CHECKBOX;  
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_enable;
    d->items[i].msg = CTEXT(T_ENABLE);
	d->items[i].wrap = 2;

	d->items[++i].type = D_TEXT; 
	d->items[i].msg = CTEXT(T_IQ_SOURCE);

#ifdef HAVE_ALSA
    d->items[++i].type = D_CHECKBOX;  
    d->items[i].gid = 1;
    d->items[i].gnum = DSPT_ALSA;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_rec_dsp_type;
    d->items[i].msg = CTEXT(T_ALSA);
#endif
    
#ifdef HAVE_PORTAUDIO
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
    d->items[i].gnum = DSPT_PORTAUDIO;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_rec_dsp_type;
    d->items[i].msg = CTEXT(T_PORTAUDIO);
#endif

#ifdef HAVE_SNDFILE
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
	d->items[i].gnum = DSPT_SNDFILE;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_rec_dsp_type;
    d->items[i].msg = CTEXT(T_WAV_FILE);
#endif

#ifdef HAVE_LIBRTLSDR
	d->items[++i].type = D_CHECKBOX;
	d->items[i].gid = 1;
	d->items[i].gnum = DSPT_RTLSDR;
	d->items[i].dlen = sizeof(int);
	d->items[i].data = (char *)&sdr_rec_dsp_type;
	d->items[i].msg = TRANSLATE("RTL-SDR");//CTEXT(T_WAV_FILE);
#endif

	d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 1;
	d->items[i].gnum = DSPT_SDRC;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_rec_dsp_type;
    d->items[i].msg = TRANSLATE("Remote RX");

    d->items[i].wrap++;  //-------------------------------------
	
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_speed_str;
    d->items[i].maxl = 9;
    d->items[i].fn   = check_number;
    d->items[i].gid  = 8000;
    d->items[i].gnum = 3200000;
    d->items[i].msg = CTEXT(T_SAMPLERATE); 
	d->items[i].wrap = 1;
	sdr_samplerate_index = i;

	  // ----------------------------------------------------------

#ifdef HAVE_ALSA
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_pcm_rec;
    d->items[i].maxl = 15;
    d->items[i].msg = CTEXT(T_PCM_REC);
	d->items[i].wrap = 1;
    
/*  d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_alsa_mixer;
    d->items[i].maxl = 15;
    d->items[i].msg = CTEXT(T_ALSA_MIXER);
    
    d->items[++i].type = D_BUTTON;  
    d->items[i].gid  = 0;
    d->items[i].fn   = dlg_alsa_src;
    d->items[i].text = sdr_alsa_src;
    d->items[i].msg = CTEXT(T_CAPTURE);   */
#endif
#ifdef HAVE_PORTAUDIO
	d->items[++i].type = D_BUTTON;  
    d->items[i].gid  = 0;
    d->items[i].fn   = dlg_pa_rec_src;
    d->items[i].text = sdr_pa_rec_src;
    d->items[i].msg = CTEXT(T_PA_REC);
	d->items[i].wrap = 1;
#endif


    
#ifdef HAVE_SNDFILE
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = sdr_sndfilename;
    d->items[i].maxl = 40;
    d->items[i].msg = CTEXT(T_WAV_FILE_NAME);
	d->items[i].tabcompl = 1;
	sdr_sndfilename_index = i;

#ifdef Z_HAVE_SDL
	if (sdl){
		d->items[++i].type = D_BUTTON;  
		d->items[i].fn   = dlg_sdr_sndfilename;
		d->items[i].text = CTEXT(T_RIG_CHOOSE);
	}
	d->items[i].wrap++;
#endif
#endif

	d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_remoterx;
    d->items[i].maxl = 39;
    d->items[i].msg = TRANSLATE("Remote RX host");
	d->items[i].wrap = 1;

	d->items[i].wrap++;	  // ========================================================

	
	d->items[++i].type = D_TEXT;  
	d->items[i].msg = CTEXT(T_AF_OUTPUT);

#ifdef HAVE_ALSA
    d->items[++i].type = D_CHECKBOX;  
    d->items[i].gid = 2;
    d->items[i].gnum = DSPT_ALSA;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_play_dsp_type;
    d->items[i].msg = CTEXT(T_ALSA);
#endif
    
#ifdef HAVE_PORTAUDIO
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 2;
    d->items[i].gnum = DSPT_PORTAUDIO;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_play_dsp_type;
    d->items[i].msg = CTEXT(T_PORTAUDIO);
#endif

#ifdef HAVE_SNDFILE
    d->items[++i].type = D_CHECKBOX;
    d->items[i].gid = 2;
	d->items[i].gnum = DSPT_SNDFILE;
    d->items[i].dlen = sizeof(int);
    d->items[i].data = (char *)&sdr_play_dsp_type;
    d->items[i].msg = CTEXT(T_WAV_FILE);
#endif

	
    d->items[i].wrap++;  // ------------------------------------------------
	
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_af_speed_str;
    d->items[i].maxl = 7;
    d->items[i].fn   = check_sdr_af_speed;
    d->items[i].gid  = 8000;
    d->items[i].gnum = 192000;
    d->items[i].msg = CTEXT(T_AF_SAMPLE_RATE); 
	d->items[i].wrap = 1;
	sdr_af_samplerate_index = i;
		
	d->items[i].wrap = 1;  // ----------------------------------------------------------

#ifdef HAVE_ALSA
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_pcm_play;
    d->items[i].maxl = 15;
    d->items[i].msg = CTEXT(T_PCM_PLAY);
	d->items[i].wrap = 1;
#endif
#ifdef HAVE_PORTAUDIO
	d->items[++i].type = D_BUTTON;  
    d->items[i].gid  = 0;
    d->items[i].fn   = dlg_pa_play_src;
    d->items[i].text = sdr_pa_play_src;
    d->items[i].msg = CTEXT(T_PA_PLAY);
	d->items[i].wrap = 1;
#endif
 #ifdef HAVE_SNDFILE
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = sdr_af_filename;
    d->items[i].maxl = 40;
    d->items[i].msg = CTEXT(T_WAV_FILE_NAME);
	d->items[i].tabcompl = 1;
	sdr_af_filename_index = i;

#ifdef Z_HAVE_SDL
	if (sdl){
		d->items[++i].type = D_BUTTON;  
		d->items[i].fn   = dlg_sdr_af_filename;
		d->items[i].text = CTEXT(T_RIG_CHOOSE);
	}
	d->items[i].wrap++;
#endif
#endif

	
	d->items[i].wrap++;	  // ========================================================

    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_block_str;
    d->items[i].maxl = 7;
    d->items[i].fn   = check_number;
    d->items[i].gid  = 128;
    d->items[i].gnum = 9999999;
    d->items[i].msg = CTEXT(T_BLOCK_SIZE); 
	d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_cw_low_str;
    d->items[i].maxl = 7;
    d->items[i].fn   = sdr_check_range;
    d->items[i].gid  = -10000;
    d->items[i].gnum = +10000;
    d->items[i].msg = CTEXT(T_CW_FILTER); 
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_cw_high_str;
    d->items[i].maxl = 6;
    d->items[i].fn   = check_double;
    d->items[i].gid  = -10000;
    d->items[i].gnum = +10000;
    d->items[i].msg = CTEXT(T_TO_HZ); 
	d->items[i].wrap = 1;// ------------------------------------------------
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_ssb_low_str;
    d->items[i].maxl = 7;
    d->items[i].fn   = sdr_check_range;
    d->items[i].gid  = -10000;
    d->items[i].gnum = +10000;
    d->items[i].msg = CTEXT(T_SSB_FILTER); 
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = sdr_ssb_high_str;
    d->items[i].maxl = 6;
    d->items[i].fn   = check_double;
    d->items[i].gid  = -10000;
    d->items[i].gnum = +10000;
    d->items[i].msg = CTEXT(T_TO_HZ); 
	d->items[i].wrap = 1; // ------------------------------------------------
    
    
    

	d->items[i].wrap++;
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ENTER;
    d->items[i].fn = ok_dialog;
    d->items[i].text = VTEXT(T_OK);
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ESC;
    d->items[i].fn = cancel_dialog;
    d->items[i].text = VTEXT(T_CANCEL);
    d->items[i].align = AL_BUTTONS;
    d->items[i].wrap = 1;

    d->items[++i].type = D_END;
    do_dialog(d, getml(d, NULL));

}

