Logo Search packages:      
Sourcecode: tucnak2 version File versions  Download package

cwdaemon.c

/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2006  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"


struct cwdaemon *cwda;

struct cwdaemon *init_cwdaemon(){
    struct cwdaemon *cwda;
    int fds[2];

  /*  sound(880);
    sleep(1);
    sound(0);
    sleep(1);
    sound(1760);
    sleep(1);
    sound(0);
    sleep(1);  */
    cwda = g_new0(struct cwdaemon, 1);
    
    switch(cfg->cwda_type){
        case CWD_PARPORT:
#ifdef HAVE_LINUX_PPDEV_H
            /* ppdev.h */
            cwda->init    = parport_init;
            cwda->free    = parport_free;
            cwda->reset   = parport_reset;
            cwda->text    = cwdaemon_text;
            cwda->sspeed  = cwdaemon_speed;
            cwda->sweight = cwdaemon_weight;
            cwda->cw      = parport_cw;
            cwda->ptt     = parport_ptt;
            cwda->ssbway  = parport_ssbway;
#elif defined(__CYGWIN__)
            /* inpout.h */
            cwda->init    = parport_init;
            cwda->free    = parport_free;
            cwda->reset   = parport_reset;
            cwda->text    = cwdaemon_text;
            cwda->sspeed  = cwdaemon_speed;
            cwda->sweight = cwdaemon_weight;
            cwda->cw      = parport_cw;
            cwda->ptt     = parport_ptt;
            cwda->ssbway  = parport_ssbway;
#else
            log_addf("Support for ppdev/inpout isn't compiled in");
            dbg("Support for ppdev/inpout isn't compiled in\n");
#endif            
            break;
            
        case CWD_TTYS:
            cwda->init    = ttys_init;
            cwda->free    = ttys_free;
            cwda->reset   = ttys_reset;
            cwda->text    = cwdaemon_text;
            cwda->sspeed  = cwdaemon_speed;
            cwda->sweight = cwdaemon_weight;
            cwda->cw      = ttys_cw;
            cwda->ptt     = ttys_ptt;
            cwda->ssbway  = ttys_ssbway;
            break;
            case CWD_DAVAC4:
#ifdef HAVE_LIBFTDI
            cwda->init    = davac4_init;
            cwda->free    = davac4_free;
            cwda->reset   = davac4_reset;
            cwda->text    = cwdaemon_text;
            cwda->sspeed  = cwdaemon_speed;
            cwda->sweight = cwdaemon_weight;
            cwda->cw      = davac4_cw;
            cwda->ptt     = davac4_ptt;
            cwda->ssbway  = davac4_ssbway;
            cwda->monitor = davac4_monitor;
#else             
            log_addf("Support for davac4 isn't compiled in, check for libftdi");
            dbg("Support for davac4 isn't compiled in, check for libftdi");
#endif
            break;
            
        case CWD_CWD:
            cwda->init    = cwd_init;
            cwda->free    = cwd_free;
            cwda->reset   = cwd_reset;
            cwda->text    = cwd_text;
            cwda->sspeed  = cwd_speed;
            cwda->sweight = cwd_weight;
            cwda->cw      = cwd_cw;
            cwda->ptt     = cwd_ptt;
            cwda->ssbway  = cwd_ssbway;
            cwda->echo    = cwd_echo;
            break;
                
    }
    cwda->speed=cfg->cwda_speed;
    cwda->weight=cfg->cwda_weight;
    
    
    /*dbg("init_cwdaemon\n"); */
    if (pipe(fds)) internal("Can't create pipe");
    cwda->pipe_read=fds[0];
    cwda->pipe_write=fds[1];
    cwda->code=g_string_sized_new(100);
    cwda->thread=g_thread_create(cwdaemon_thread_func, (gpointer)cwda, TRUE, NULL);
    if (cwda->init) cwda->init(cwda);
/*    cwdaemon_cw_string(cwda, "cq cq de ok1zia"); */
    /*cwdaemon_cw_string(cwda, "cq"); */
    return cwda;
}

void free_cwdaemon(struct cwdaemon *cwda){
    char c;

    if (!cwda) return;
    cq_abort(1);

    c=0;
    write(cwda->pipe_write, &c, 1);
    g_thread_join(cwda->thread);
    close(cwda->pipe_write);
    close(cwda->pipe_read);
    g_string_free(cwda->code, 1);
    if (cwda->free) cwda->free(cwda);
    g_free(cwda);
    cwda=NULL;
}

struct cwelem{
    struct timeval tv;
    int on,last;
};

#define MAXCWQUEUE 20
struct cwelem cwqueue[MAXCWQUEUE+1]; 
int qi;

void cwenqueue(struct cwdaemon *cwda){
    char s[256], *c, ch;
    int i;
    struct timeval tv;
    
    if (cwda->tune > 0){
        gettimeofday(&tv, NULL);
        i = 0;
        cwqueue[i].tv.tv_sec=tv.tv_sec;       
        cwqueue[i].tv.tv_usec=tv.tv_usec;       
        cwqueue[i].on=1;
        cwqueue[i].last=0;
        tv.tv_usec+=(cwda->tune==2?3:1)*(1200000/cwda->speed+cwda->weight*500);
        while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
        i++;
        cwqueue[i].tv.tv_sec=tv.tv_sec;       
        cwqueue[i].tv.tv_usec=tv.tv_usec;       
        cwqueue[i].on=0;
        cwqueue[i].last=0;
        tv.tv_usec+=1200000/cwda->speed-cwda->weight*500;
        while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
        i++;

        cwqueue[i].tv.tv_sec=tv.tv_sec;
        cwqueue[i].tv.tv_usec=tv.tv_usec;
        cwqueue[i].on=0;
        cwqueue[i].last=1;
        qi=0;
        return;
    }
    
    while(1){
        ch=*cwda->code->str;
        
        if (!ch) {
            qi=-1;
            strcpy(s, "CW;e\n");
            write(tpipe->threadpipe_write, s, strlen(s));
            return;
        }
        g_string_erase(cwda->code, 0, 1);
        switch(ch){
            case ' ': strcpy(s, " ");      break;
            case 'A': strcpy(s, ".-");     break;
            case 'B': strcpy(s, "-...");   break;          
            case 'C': strcpy(s, "-.-.");   break;          
            case 'D': strcpy(s, "-..");    break;          
            case 'E': strcpy(s, ".");      break;          
            case 'F': strcpy(s, "..-.");   break;          
            case 'G': strcpy(s, "--.");    break;          
            case 'H': strcpy(s, "....");   break;          
            case 'I': strcpy(s, "..");     break;          
            case 'J': strcpy(s, ".---");   break;          
            case 'K': strcpy(s, "-.-");    break;          
            case 'L': strcpy(s, ".-..");   break;          
            case 'M': strcpy(s, "--");     break;          
            case 'N': strcpy(s, "-.");     break;          
            case 'O': strcpy(s, "---");    break;          
            case 'P': strcpy(s, ".--.");   break;          
            case 'Q': strcpy(s, "--.-");   break;          
            case 'R': strcpy(s, ".-.");    break;          
            case 'S': strcpy(s, "...");    break;          
            case 'T': strcpy(s, "-");      break;          
            case 'U': strcpy(s, "..-");    break;          
            case 'V': strcpy(s, "...-");   break;          
            case 'W': strcpy(s, ".--");    break;          
            case 'X': strcpy(s, "-..-");   break;          
            case 'Y': strcpy(s, "-.--");   break;          
            case 'Z': strcpy(s, "--..");   break;          
            case '0': strcpy(s, "-----");  break;          
            case '1': strcpy(s, ".----");  break;          
            case '2': strcpy(s, "..---");  break;          
            case '3': strcpy(s, "...--");  break;          
            case '4': strcpy(s, "....-");  break;          
            case '5': strcpy(s, ".....");  break;          
            case '6': strcpy(s, "-....");  break;          
            case '7': strcpy(s, "--...");  break;          
            case '8': strcpy(s, "---..");  break;          
            case '9': strcpy(s, "----.");  break;          
            case '?': strcpy(s, "..--.."); break;          
            case '/': strcpy(s, "-..-.");  break;          
            case ',': strcpy(s, "--..--"); break;          
            case '=': strcpy(s, "-...-");  break;          
            case '@': strcpy(s, ".--.-."); break;          
            case '-': strcpy(s, "-....-"); break;          
            case '+': strcpy(s, ".-.-.");  break;          
            case '.': strcpy(s, ".-.-.-"); break;          
            case ';': strcpy(s, "-.-.-."); break;          
            case '!': strcpy(s, ".-...");  break;          
            default: continue;
        }
        break;        
    }
    
    /*dbg("enqueue %c '%s'\n", ch, s);*/
    
    gettimeofday(&tv, NULL);
    i=0;
    for (c=s; ; c++){
        if (*c=='.'){
            cwqueue[i].tv.tv_sec=tv.tv_sec;       
            cwqueue[i].tv.tv_usec=tv.tv_usec;       
            cwqueue[i].on=1;
            cwqueue[i].last=0;
            tv.tv_usec+=1200000/cwda->speed+cwda->weight*500;
            while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
            i++;
            cwqueue[i].tv.tv_sec=tv.tv_sec;       
            cwqueue[i].tv.tv_usec=tv.tv_usec;       
            cwqueue[i].on=0;
            cwqueue[i].last=0;
            tv.tv_usec+=1200000/cwda->speed-cwda->weight*500;
            while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
            i++;
        }
        if (*c=='-'){
            cwqueue[i].tv.tv_sec=tv.tv_sec;       
            cwqueue[i].tv.tv_usec=tv.tv_usec;       
            cwqueue[i].on=1;
            cwqueue[i].last=0;
            tv.tv_usec+=3*(1200000/cwda->speed+cwda->weight*500);
            while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
            i++;
            cwqueue[i].tv.tv_sec=tv.tv_sec;       
            cwqueue[i].tv.tv_usec=tv.tv_usec;       
            cwqueue[i].on=0;
            cwqueue[i].last=0;
            tv.tv_usec+=1200000/cwda->speed-cwda->weight*500;
            while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
            i++;
        }
        if (*c=='\0'){
            cwqueue[i].tv.tv_sec=tv.tv_sec;       
            cwqueue[i].tv.tv_usec=tv.tv_usec;       
            cwqueue[i].on=2;
            cwqueue[i].last=0;
            tv.tv_usec+=2*(1200000/cwda->speed-cwda->weight*500);
            while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
            i++;
            break;
        }
        if (*c==' '){
            cwqueue[i].tv.tv_sec=tv.tv_sec;       
            cwqueue[i].tv.tv_usec=tv.tv_usec;       
            cwqueue[i].on=0;
            cwqueue[i].last=0;
            tv.tv_usec+=5*(1200000/cwda->speed-cwda->weight*500);
            while (tv.tv_usec>=1000000) {tv.tv_usec-=1000000;tv.tv_sec++; }
            i++;
        }
    }
    cwqueue[i].tv.tv_sec=tv.tv_sec;
    cwqueue[i].tv.tv_usec=tv.tv_usec;
    cwqueue[i].on=0;
    cwqueue[i].last=1;
    qi=0;

/*    for(i=0;;i++){
        dbg("    %2d %d %2d.%06d\n", i, cwqueue[i].on, cwqueue[i].tv.tv_sec, cwqueue[i].tv.tv_usec);
        if (cwqueue[i].last) break;
    }*/
}

gpointer cwdaemon_thread_func(gpointer data){
    fd_set rd;
    struct timeval *tv, interval, now;
    int ret, i;
    char buf[1030], s[256];
    struct cwdaemon *cwda;

    cwda=(struct cwdaemon*)data;

    qi=-1;
    while(1){
        FD_ZERO(&rd);
        FD_SET(cwda->pipe_read, &rd);

        if (qi<0){
            tv=NULL;
            /*dbg("\nselect()\n");*/
        }else{
            /*dbg("\n");*/
            gettimeofday(&interval, NULL);
            /*dbg("now=%02d.%06d  cwqueue[%d]=%02d.%06d\n",interval.tv_sec, interval.tv_usec, qi, cwqueue[qi].tv.tv_sec, cwqueue[qi].tv.tv_usec); */
            interval.tv_usec=cwqueue[qi].tv.tv_usec-interval.tv_usec;
            interval.tv_sec=cwqueue[qi].tv.tv_sec-interval.tv_sec;
            while(interval.tv_usec<0) { interval.tv_usec+=1000000; interval.tv_sec--; }
            if (interval.tv_sec<0) {interval.tv_sec=0;interval.tv_usec=0;}
            tv=&interval;
            /*dbg("select(%2d.%06d)\n", interval.tv_sec%100, interval.tv_usec); */
        }
        
        ret=select(cwda->pipe_read+1, &rd, NULL, NULL, tv);
        gettimeofday(&now, NULL);
        if (!ret){   /* timeout */
           /* dbg("timeout\n");*/
            goto check_queue;
        }
        if (FD_ISSET(cwda->pipe_read, &rd)){
            /*dbg("event on fd\n");*/
            ret=read(cwda->pipe_read, buf, 1024);
            if (ret<=0){
                strcpy(s, "CW;!\n");
                /*dbg("%s\n", s);*/
                write(tpipe->threadpipe_write, s, strlen(s));
                break;
            }
            buf[ret]='\0';
            /*dbg("cwdaemon_thread_func: read %d '", ret);
            for (i=0;i<ret;i++) dbg("\\%02x", buf[i]);
            dbg("'\n", buf);*/
            for (i=0;i<ret;i++){
                if (buf[i]>=' ') {
                    g_string_append_c(cwda->code, upcase(buf[i]));
                    continue;
                }
                switch(buf[i]){
                    case '\0':
                        if (cwda->cw) cwda->cw(cwda, 0);
                        if (cfg->cwda_spk) sound(0);
                        return NULL;
                    case 1: 
                        cwenqueue(cwda);
                        break;
                    case 3: 
                        if (cwda->cw) cwda->cw(cwda, 0);
                        if (cfg->cwda_spk) sound(0);
                        qi=-1;
                        g_string_truncate(cwda->code, 0);
                        break;
                    default:  
                        break;
                }
            }
            if (qi<0 && *cwda->code->str){
                dbg("cwenqueue 1 tune=%d\n", cwda->tune);
                cwenqueue(cwda);
            }
        }
check_queue:
        if (qi<0) continue;
        if (cwqueue[qi].last){
            /*dbg("cwenqueue 2\n");*/
            cwenqueue(cwda);
            goto check_queue;
        }
        if (cwqueue[qi].tv.tv_sec>now.tv_sec) continue;
        if (cwqueue[qi].tv.tv_usec==now.tv_sec){
            if (cwqueue[qi].tv.tv_usec>now.tv_usec) continue;
        }
        /*dbg("playing %d.\n", qi);*/

        if (cwqueue[qi].on==1){
            if (cwda->cw) cwda->cw(cwda, 1);
            if (cfg->cwda_spk) sound(800);
        }else{ 
            if (cwda->cw) cwda->cw(cwda, 0);
            if (cfg->cwda_spk) sound(0);
        }
        qi++;
        continue;
        if (cwda->cw) cwda->cw(cwda, 0);
        if (cfg->cwda_spk) sound(0);
        
    }

    return NULL;
}

void cwdaemon_read_handler(struct cwdaemon *cwda, char *s){
    
    if (gses->last_cq_timer_id){ /* CQ was abortet while playing */
        kill_timer(gses->last_cq_timer_id);
        gses->last_cq_timer_id = 0;
    }

/*    dbg("cwdaemon_read_handler   rcvd: '%s'\n", s);*/
    switch(s[0]){
        case '!':  /* error */
            cq_abort(ssbd->recording); /*abort recording only if it is in progress */
            log_addf("cwdaemon: %s", s+1);
            break;
        case 'e':  /* cw text played */
              if (!gses || !gses->last_cq) break; /* zdravime uW 2004 :-) */
            if (gses->last_cq->cw_repeat) 
                cq_cw_wait(gses->last_cq);
            else{
                gses->last_cq->type=MOD_NONE;
                cq_abort(ssbd->recording);
            }
            peer_tx(aband, 0);
            redraw_later();
            break;
    }
}


void cq_cw_wait(struct cq *cq){
    dbg("cq_cw_wait\n");
    ssbd_abort(ssbd,0);
    cwdaemon_ptt(cwda, 0);
    cwdaemon_ssbway(cwda, 0); /* microphone */
    peer_tx(aband, 0);
    dbg("installing wait timer\n");
    gses->last_cq_timer_id = install_timer(cq->cw_ts*100, cq_timer_cw2, (union cba_t)cq);
}

void cq_timer_cw2(union cba_t cq){
    
    dbg("cq_timer_cw2\n");
    cq_run_cw(cq.cq);
}


void cwdaemon_send_defaults(struct cwdaemon *cwda, int speed){
    cwda->sspeed(cwda, cwda->speed);
    cwda->sweight(cwda, cwda->weight);
    if (cfg->cwda_type == CWD_CWD) cwd_tone(cwda, cfg->cwda_spk?800:0);
}

void cwdaemon_abort(struct cwdaemon *cwda){
    
    if (!cwda) return;
    if (cwda->reset) cwda->reset(cwda);
    cwda->tune = 0;
    write(cwda->pipe_write, "\x03", 1);
}

/* called from SEGV handler */
void cwdaemon_safe_abort(struct cwdaemon *cwda){
    if (!cwda) return;
    if (cwda->reset) cwda->reset(cwda);
}



int cwdaemon_text(struct cwdaemon *cwda, char *text){
    
    if (!cwda) return 0;
    
    /*dbg("cwdaemon_cw_string('%s')\n", text);*/
    write(cwda->pipe_write, text, strlen(text));
    return 0;
}

void cwdaemon_ptt(struct cwdaemon *cwda, int ptt){
    
    if (!cwda || !cwda->ptt) return;
    /*dbg("ptt %d\n", ptt);*/
    cwda->ptt(cwda, ptt);
}

/* 0=microphone, 1=soundcard */
void cwdaemon_ssbway(struct cwdaemon *cwda, int ssbway){
    /*dbg("cwdaemon_ssbway(%d)\n", ssbway);*/
    
    if (!cwda || !cwda->ssbway) return;
    
    cwda->ssbway(cwda, ssbway);
}

int cwdaemon_speed(struct cwdaemon *cwda, int wpm){
    
    if (!cwda) return 0;
    
    cwda->speed=wpm;
    return 0;
}

void cwdaemon_qrq(struct cwdaemon *cwda, int qrq){
    
    if (!cwda) return;

    if (cwda->speed+qrq > 80)
        cwda->speed=80;
    else
        cwda->speed+=qrq;
    if (cwda->sspeed) cwda->sspeed(cwda, cwda->speed);
}

void cwdaemon_qrs(struct cwdaemon *cwda, int qrs){
    
    if (!cwda) return;

    if (cwda->speed-qrs < 10)
        cwda->speed=10;
    else
        cwda->speed-=qrs;
    if (cwda->sspeed) cwda->sspeed(cwda, cwda->speed);
}

int cwdaemon_weight(struct cwdaemon *cwda, int weight){
    
    if (!cwda) return 0;
    
    cwda->weight=weight;
    return 0;
}

void cwdaemon_tune(struct cwdaemon *cwda, int tune){

    if (!cwda) return;
    
    cwda->tune = tune;
    dbg("cwdaemon_tune(%d)\n", tune);
    if (tune>0)
        write(cwda->pipe_write, "\x01", 1);
    else 
        cwdaemon_abort(cwda);
}


/*********** cwdaemon ***********************************/
int cwd_init(struct cwdaemon *cwda){
    int on;
    struct sockaddr_in sin;

    cwda->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (cwda->sock < 0) goto err;

    on=1;
    if (setsockopt(cwda->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))){
        dbg("Can't set SO_REUSEADDR\n");
        goto err;
    }
    
    if (fcntl(cwda->sock, F_SETFL, O_NONBLOCK)){
        dbg("Can't set O_NONBLOCK\n");
        goto err;
    }
    
    memset(&sin, 0, sizeof(struct sockaddr_in));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(cfg->cwda_udp_port);
    if (!cfg->cwda_hostname) cfg->cwda_hostname = g_strdup("");
    inet_aton(cfg->cwda_hostname, &sin.sin_addr);
    
    if (connect(cwda->sock, (struct sockaddr *)&sin, sizeof(sin))){
        dbg("Can't connect\n");
        goto err;
    }
    set_handlers(cwda->sock, cwd_read_handler, NULL, NULL, (union cba_t)cwda);

    
    cwdaemon_send_defaults(cwda, cwda->speed);
    return 0;

err:;
    if (cwda->sock>=0) close(cwda->sock);
    cwda->sock = -1;
      return 1;
}

int cwd_free(struct cwdaemon *cwda){
    dbg("cwd_free(%p) sock=%d\n", cwda, cwda?cwda->sock:-1234);
    if (cwda->sock>=0) {
        cwdaemon_abort(cwda);
        set_handlers(cwda->sock, NULL, NULL, NULL, CBA0);
        close(cwda->sock);
    }
      return 0;
}

void cwd_read_handler(union cba_t cba){
    char s[1024];
    struct sockaddr_in sin;
    socklen_t socklen;
    int rcvd;          
    struct cwdaemon *cwda;

    dbg("cwd_read_handler\n");
    cwda = cba.cwda;
#if 0    
    if (!ctest) {
        /* we must clear kernel queue */
        recvfrom(cwda->sock, s, sizeof(s)-1, 0, 
            (struct sockaddr *)&sin, &socklen);
        return;
    }
#endif    
    memset(s, 0, sizeof(s));
    socklen = sizeof(sin);
    rcvd=recvfrom(cwda->sock, s, sizeof(s)-1, 0, 
            (struct sockaddr *)&sin, &socklen);
    /*dbg("  received '%s' = %d  last_cq_timer_id=%d \n", s, rcvd, ctest->last_cq_timer_id);*/
    if (rcvd<=0) return;

    dbg("   rcvd: '%s'\n", s);
    switch(s[0]){
        case '!':  /* error */
            log_addf("cwdaemon: %s", s+1);
            write(tpipe->threadpipe_write, "CW;!\n", 5);
            break;
        case 'h':  /* cw text played */
            dbg("cwdaemon text played\n");
            write(tpipe->threadpipe_write, "CW;e\n", 5);
            break;
    }
}
int cwd_reset(struct cwdaemon *cwda){
    if (!cwda || cwda->sock<0) return 0;

    send(cwda->sock, "\0330", 3, 0);  /* reset */
      return 0;
}

int cwd_text(struct cwdaemon *cwda, char *text){
    if (!cwda || cwda->sock<0) return 0;

    send(cwda->sock, text, strlen(text)+1, 0);  /* reset */
    return 0;
}

int cwd_cw(struct cwdaemon *cwda, int onoff){
      return 0;
}

int cwd_ptt(struct cwdaemon *cwda, int onoff){
    char s[16];
    
    if (!cwda || cwda->sock<0) return 0;
    sprintf(s,"\033a%d", onoff);
    send(cwda->sock, s, strlen(s)+1, 0);
      return 0;
}

int cwd_ssbway(struct cwdaemon *cwda, int onoff){
    char s[16];
    
    if (!cwda || cwda->sock<0) return 0;
    sprintf(s,"\033b%d", onoff);
    send(cwda->sock, s, strlen(s)+1, 0);
      return 0;
}

int cwd_echo(struct cwdaemon *cwda){
    char s[16];
    
    if (!cwda || cwda->sock<0) return 0;

    sprintf(s,"\033h%d", -1);
    send(cwda->sock, s, strlen(s)+1, 0);
    return 0;
}

int cwd_speed(struct cwdaemon *cwda, int wpm){
    char s[16];
    
    if (cwda->sock<0) return 0;

    /*dbg("speed=%d\n", wpm);*/
    sprintf(s,"\0332%d", wpm);
    send(cwda->sock, s, strlen(s)+1, 0);
    return 0;
}

int cwd_weight(struct cwdaemon *cwda, int weight){
    char s[16];
    
    if (cwda->sock<0) return 0;

    sprintf(s,"\0337%d", weight);
    send(cwda->sock, s, strlen(s)+1, 0);
    return 0;
}

void cwd_tone(struct cwdaemon *cwda, int tone){
    char s[16];
    
    if (cwda->sock<0) return;

    dbg("TONE\n");
    sprintf(s,"\0333%d", tone);
    send(cwda->sock, s, strlen(s)+1, 0);
}

/*********** CQ ***********************************/

        
struct cq *init_cq(void){
    struct cq *cq;

    cq = g_new0(struct cq, 1);
    g_ptr_array_add(cfg->cqs, cq);
    return cq;
}

struct cq *get_cq_by_number(GPtrArray *cqs, int nr){
    struct cq *cq;
    int i;

    for (i=0; i<cqs->len; i++){
        cq = (struct cq *)g_ptr_array_index(cqs, i);
        if (cq->nr==nr) return cq;
    }
    return NULL;   
}



void free_cq (struct cq *cq){
    if (cq->cw_str)   g_free(cq->cw_str);
    if (cq->ssb_file) g_free(cq->ssb_file);
    g_free(cq);        
}

/**************** CW *************************/
int cq_run_cw(struct cq *cq){
    gchar *raw;

    dbg("cq_run_cw\n");
    ssbd_abort(ssbd,1); /*aborts playing or recording */

    cq->type=MOD_CW_CW;
    redraw_later();
    if (!cq->cw_str) {
        return -1;
    }
    raw = convert_cq(cq);
    if (!raw) return -1;

/*    if (cwda->sspeed){
        if (cq->cw_speed) 
            cwda->sspeed(cwda, cq->cw_speed);
        else
            cwda->sspeed(cwda, cwda->speed);
    }
    if (cwda->sweight){
        cwda->sweight(cwda, cwda->weight);
    }
 */
    if (cq->cw_speed) 
        cwdaemon_send_defaults(cwda, cq->cw_speed);
    else
        cwdaemon_send_defaults(cwda, cwda->speed);

    if (cwda->text) cwda->text(cwda, raw);
    if (cwda->echo) cwda->echo(cwda);
    peer_tx(aband, 2);
    g_free(raw);

    gses->last_cq = cq;
    gses->last_cq_timer_id = 0;
    return 0;
}

void cq_timer_cw(union cba_t cq){
    cwdaemon_abort(cwda);
    cq_run_cw(cq.cq);
}


/*************** SSB *************************/
int cq_run_ssb(struct cq *cq){
      int ret;

    dbg("cq_run_ssb\n");
    cq->type=MOD_SSB_SSB;
    cwdaemon_ptt(cwda, 1);
    cwdaemon_ssbway(cwda, 1); /* soundcard */
    
      CONDGFREE(ssbd->pfilename);
    ssbd->pfilename=convert_esc(cq->ssb_file, NULL, CE_NONE);
    if (!ssbd->pfilename) return -1;
    ret=ssbd_play_file(ssbd, ssbd->pfilename);

    gses->last_cq = cq;
    gses->last_cq_timer_id = 0;
    peer_tx(aband, 2);
    redraw_later();
    return ret;
}
            
/*void cq_timer_ssb1(union cba_t cq){
    
    dbg("cq_timer_ssb1\n");
    cq_ssb_wait(cq.cq); 
} */

void cq_ssb_wait(struct cq *cq){
    /*dbg("cq_ssb_wait\n");*/
    ssbd_abort(ssbd,0);
    cwdaemon_ptt(cwda, 0);
    cwdaemon_ssbway(cwda, 0); /* microphone */
    peer_tx(aband, 0);
    gses->last_cq_timer_id = install_timer(cq->ssb_ts*100, cq_timer_ssb2, (union cba_t)cq);
}

void cq_timer_ssb2(union cba_t cq){
    
    /*dbg("cq_timer_ssb2\n");*/
    cq_run_ssb(cq.cq);
}


/****************** common **********************/
int cq_run_by_number(int no){
    int ret;
    struct cq *cq;
    
    dbg("cq_run_by_number(%d), mode=%s\n", no, get_mode()==MOD_CW_CW?"CW":"SSB");
    
    if (no<0 || no>=cfg->cqs->len) return -1;
       
    cq = (struct cq *)g_ptr_array_index(cfg->cqs, no);
    cq_abort(1);
    
    /*if (gses->last_cq_timer_id0){
        kill_timer(gses->last_cq_timer_id);
        gses->last_cq_timer_id = 0;
    } */
    
    
    if (get_mode() == MOD_CW_CW){
        /*dbg(" speed=%d repeat=%d ts=%d '%s'\n", cq->cw_speed, cq->cw_repeat, cq->cw_ts, cq->cw_allowifundef, cq->cw_str);*/
        ret=cq_run_cw(cq);
    }else if (get_mode() == MOD_SSB_SSB){
        /*dbg(" repeat=%d ts=%d '%s'\n", cq->ssb_repeat, cq->ssb_ts, cq->ssb_file);*/
        ret=cq_run_ssb(cq);
    }else
        ret=-1;        

    if (ret!=0) cq_abort(ssbd->recording);

    return ret;
}


int cq_abort(int abort_rec){
/*    dbg(" cq_abort(%d)\n", abort_rec);*/
    
    if (gses) gses->last_cq=NULL;
    if (gses && gses->last_cq_timer_id){
        kill_timer(gses->last_cq_timer_id);
        gses->last_cq_timer_id = 0;
    }
    
    cwdaemon_abort(cwda);
    redraw_later();
    
    if (!abort_rec && ssbd_recording(ssbd)) return 0;

    ssbd_abort(ssbd,abort_rec);
    return 0;
}

gchar *conv_nr(gchar *str){
    char *c;
    static char out[20];

    safe_strncpy0(out, str, 20);
    for (c=out; *c=='0'; c++) *c='t';
    return out;
}

gchar *conv_rst(gchar *str){
    char *c;
    static char out[20];

    safe_strncpy0(out, str, 20);
    for (c=out; *c!='\0';c++){
        if (*c=='9') *c='n';
    }
    return out;
}



/* convert $XX to string */
/* /home/ja/ssbd/tmp/rec/$N_%Y%m%d_%H%M%S.wav */

#define SFT_LEN 1024
gchar *convert_esc(gchar *format, int *undef, int flags){ 
    GString *gs;
    char *c, *ret;
    int dummyint;
    time_t now;
    struct tm utc;
    char sft_buf[SFT_LEN+1];
    
    if (!undef) undef=&dummyint;
    *undef=0;
    
    time(&now);
    gmtime_r(&now, &utc);
    if (!format) format="";
    strftime(sft_buf, SFT_LEN, format, &utc);    
    
    gs = g_string_new("");
    if (flags&CE_ONLY_STRFTIME){
        g_string_append(gs, sft_buf); 
        goto x;
    }
    
    for (c=sft_buf; *c!='\0'; c++){
        if (*c=='~' && c==sft_buf){
            g_string_append(gs, getenv("HOME"));
            continue;
        }
        if (*c!='$') {
            g_string_append_c(gs, *c);
            continue;
        }
        c++;
        switch (lowcase(*c)){
            case '\0':
                goto brk2;
                break;
            case '$':
                g_string_append_c(gs, '$');
                break;
            case 'c':
                if (ctest && TMPQ.callsign) g_string_append(gs, TMPQ.callsign);
                else *undef=1;
                break;    
            case 'd':
                if (ctest) g_string_append (gs, ctest->cdate);
                        else g_string_append(gs, "00000000");
                break;
            case 'n':
                if (ctest && TMPQ.qsonrr)   g_string_append(gs, conv_nr(TMPQ.qsonrr));
                else *undef=1;
                break;    
            case 'o':
                if (aband && aband->operator) g_string_append(gs, aband->operator);
                        else if (cfg->pcall) g_string_append(gs, cfg->pcall);
                else *undef=1;
                break;   
            case 'r':
                if (ctest && TMPQ.rstr)     g_string_append(gs, conv_rst(TMPQ.rstr));
                else *undef=1;
                break; 
            case 's': 
                g_string_sprintfa(gs, "%d", ssbd->serno);
                break;
            case 't':
                if (ctest) g_string_append(gs, ctest->directory);
                        else g_string_append_printf(gs, "%s/tucnak/00000000", getenv("HOME"));
                break;
            case 'v':
                if (ssbd->callsign) {
                    char *d;
                    for (d=ssbd->callsign; *d!='\0'; d++){
                        if (*d=='/')
                            g_string_append_c(gs, '_');
                        else
                            g_string_append_c(gs, *d);
                    }
                }
                else *undef=1;
                break;
            case 'w':
                if (ctest && TMPQ.locator)  g_string_append(gs, TMPQ.locator);
                else *undef=1;
                break;
            case 'x':
                if (ctest && TMPQ.exc)      g_string_append(gs, TMPQ.exc);
                else *undef=1;
                break;    
            case 'm':
                c++;
                switch(lowcase(*c)){
                    case '\0':
                        goto brk2;
                        break;
                    case 'c':
                        if (ctest && ctest->pcall) g_string_append(gs, ctest->pcall);
                                    else if (cfg->pcall) g_string_append(gs, cfg->pcall);
                        else *undef=1;
                        break;    
                    case 'n':
                        if (ctest && TMPQ.qsonrs)  g_string_append(gs, conv_nr(TMPQ.qsonrs));
                        else *undef=1;
                        break;    
                    case 'r':
                        if (ctest && TMPQ.rsts)    g_string_append(gs, conv_rst(TMPQ.rsts));
                        else *undef=1;
                        break;    
                    case 'w':
                        if (ctest && ctest->pwwlo) g_string_append(gs, ctest->pwwlo);
                                    else if (cfg->pwwlo) g_string_append(gs, cfg->pwwlo);
                        else *undef=1;
                        break;
                    case 'x':
                        if (ctest && ctest->pexch) g_string_append(gs, ctest->pexch);
                                    else if (cfg->pexch) g_string_append(gs, cfg->pexch);
                        else *undef=1;
                        break;    
                }
                break;
        }        
            
brk2:;        
    }
x:;    
    ret = g_strdup(gs->str);
    ret = optimize_path(ret);
    g_string_free(gs, TRUE);
    
    return ret;
}


gchar *convert_cq(struct cq *cq){
    gchar *ret;
    int undef;

    ret=convert_esc(cq->cw_str, &undef, CE_NONE);
    
    if (!cq->cw_allowifundef && undef){
        g_free(ret);
        return NULL;
    }
    return(ret);
}
    
#define FREE_Cx if (c1) {mem_free(c1); c1=NULL;}\
                if (c2) {mem_free(c2); c2=NULL;}\
                if (c3) {mem_free(c3); c3=NULL;}\
                if (c4) {mem_free(c4); c4=NULL;}\
                if (c5) {mem_free(c5); c5=NULL;}

gchar *optimize_path(gchar *src){

    int first, last, i;
    gchar **items, *c;
    GString *gs;

    if (!src) return NULL;
    if (src[0]=='\0') return src;
    if (strcmp(src, ".")==0) return src;
    if (strcmp(src, "./")==0) return src;
    
    first=src[0]=='/';
    last=src[0]&&src[strlen(src)-1]=='/';
    items=g_strsplit(src, "/", 0); 
    if (!items) return src;

    gs=g_string_sized_new(strlen(src));
    g_free(src);
    src=NULL;
    if (first) g_string_append_c(gs, '/');

    for (i=0; items[i]; i++){
        if (strcmp(items[i], ".")==0){
            continue;
        }
        if (items[i+1] && strcmp(items[i+1], "..")==0){
            i++;
            continue;
        }
        if (strlen(items[i])==0) continue;
        g_string_append(gs, items[i]);
        if (items[i+1]) g_string_append_c(gs, '/');
    }
    if (last && (!gs->str[0] || (gs->str[0] && gs->str[strlen(gs->str)-1]!='/'))) 
        g_string_append_c(gs, '/');

    c=g_strdup(gs->str);
    g_string_free(gs, TRUE);
    g_strfreev(items);
    return c;
    
}

Generated by  Doxygen 1.6.0   Back to index