/*- * Copyright (c) 1999 Thomas Runge (coto@core.de) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "lcd_net.h" #include "radio.h" static char buffer[MAXMSG]; extern XtAppContext app_con; extern int sockfd; extern int lcd_stereo; extern int lcd_fieldstrength; static XtIntervalId timerId; static int width, height, cellw, cellh; static int lcd_net_handle(); static void lcd_net_handler(XtPointer clientData, XtIntervalId *id); static int lcd_net_read(char *buffer, int nbytes); static int lcd_net_writen(const char *buffer, int nbytes); static void lcd_net_update_values(); static void lcd_net_updateLCD(XtPointer, XtIntervalId*); void sig_pipe_handler() { if(debug) printf("got SIGPIPE!\n"); lcd_net_stop(); } int lcd_net_init(const char *host, u_short port, const char **neterror) { int sock; struct sockaddr_in serv_addr; struct hostent *he; unsigned long arg; width = 20; height = 4; cellw = 5; cellh = 8; signal(SIGPIPE, (void*) sig_pipe_handler); he = gethostbyname(host); if(!he) { *neterror = hstrerror(h_errno); return(-1); } bzero((char*) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr = *(struct in_addr *) he->h_addr_list[0]; serv_addr.sin_port = htons(port); if(debug) printf("lcd_net: socket\n"); if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { *neterror = hstrerror(h_errno); return(-1); } if(debug) printf("lcd_net: connect\n"); if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { *neterror = hstrerror(h_errno); return(-1); } arg = 1; if(ioctl(sock, FIONBIO, &arg) == -1) fprintf(stderr, "lcd_net error setting socket to non blocking mode: %s\n", strerror(errno)); return(sock); } int lcd_net_start() { sprintf(buffer, "hello\n"); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "client_set name %s %s\n", APPNAME, APPVERSION); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "screen_add %s\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "screen_set %s name %s\n", APPNAME, APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_add %s title title\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_set %s title %s-%s\n", APPNAME, APPNAME, APPVERSION); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_add %s stationlabel string\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_add %s freqlabel string\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_add %s station string\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_add %s freq string\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); /* check for display height before */ sprintf(buffer, "widget_add %s stereo string\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); /* check for display height before */ sprintf(buffer, "widget_add %s fsindic string\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); /* check for display height before */ sprintf(buffer, "widget_add %s fstrength hbar\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_set %s stationlabel 1 2 Station:\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_set %s freqlabel 1 3 {Freq :}\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_set %s fsindic 1 4 {Sig: }\n", APPNAME); lcd_net_writen(buffer, strlen(buffer)); lcd_net_update_values(); XtAppAddTimeOut(app_con, 250, lcd_net_handler, (XtPointer)NULL); timerId = XtAppAddTimeOut(app_con, 250, lcd_net_updateLCD, (XtPointer)NULL); return(1); } int lcd_net_stop() { int res = close(sockfd); sockfd = 0; sprintf(buffer, "lost connection to LCD server."); lcdDisconnectCB(buffer); return(res); } static void lcd_net_update_values() { if(!sockfd) return; sprintf(buffer, "widget_set %s station 10 2 {%s}\n", APPNAME, global_station_name); lcd_net_writen(buffer, strlen(buffer)); sprintf(buffer, "widget_set %s freq 10 3 {%3.2f MHz}\n", APPNAME, frequency/100.); lcd_net_writen(buffer, strlen(buffer)); /* check for display height before */ sprintf(buffer, "widget_set %s stereo 15 4 %s\n", APPNAME, lcd_stereo ? "stereo" : "mono"); lcd_net_writen(buffer, strlen(buffer)); /* check for display height before */ sprintf(buffer, "widget_set %s fstrength 6 4 %d\n", APPNAME, lcd_fieldstrength * cellw); lcd_net_writen(buffer, strlen(buffer)); } static void lcd_net_updateLCD(XtPointer clientData, XtIntervalId *id) { static int old_freq = -1; static int old_stereo = -1; static int old_fieldstrength = -1; if(!sockfd) return; if(old_freq != frequency || old_stereo != lcd_stereo || old_fieldstrength != lcd_fieldstrength) { lcd_net_update_values(); old_freq = frequency; old_stereo = lcd_stereo; old_fieldstrength = lcd_fieldstrength; } timerId = XtAppAddTimeOut(app_con, 250, lcd_net_updateLCD, (XtPointer)NULL); } static void lcd_net_handler(XtPointer clientData, XtIntervalId *id) { if(sockfd) { lcd_net_handle(); XtAppAddTimeOut(app_con, 250, lcd_net_handler, (XtPointer)NULL); } } static int lcd_net_handle() { int res; res = lcd_net_read(buffer, MAXMSG); switch(res) { case -2: /* no data to read */ break; case -1: /* socket related problem */ perror("socket"); lcd_net_stop(); return(False); break; case 0: /* server died or connection lost */ fprintf(stderr, "connection to LCD server down.\n"); lcd_net_stop(); return(False); break; default: if(!strncmp(buffer, "huh", 3)) { fprintf(stderr, "server replied an error: %s\n", buffer); break; } if(!strncmp(buffer, "listen", 6)) { timerId = XtAppAddTimeOut(app_con, 250, lcd_net_updateLCD, (XtPointer)NULL); break; } if(!strncmp(buffer, "ignore", 6)) { if(timerId) XtRemoveTimeOut(timerId); break; } if(!strncmp(buffer, "connect", 7)) { char *tmp; tmp = strtok(buffer, " "); while(tmp) { if(!strcmp(tmp, "wid")) { tmp = strtok(NULL, " "); if(!tmp) break; width = atoi(tmp); } if(!strcmp(tmp, "hgt")) { tmp = strtok(NULL, " "); if(!tmp) break; height = atoi(tmp); } if(!strcmp(tmp, "cellwid")) { tmp = strtok(NULL, " "); if(!tmp) break; cellw = atoi(tmp); } if(!strcmp(tmp, "cellhgt")) { tmp = strtok(NULL, " "); if(!tmp) break; cellh = atoi(tmp); } tmp = strtok(NULL, " "); } if(debug) printf("got lcd. w: %d h: %d cw: %d ch: %d\n", width, height, cellw, cellh); break; } if(!strncmp(buffer, "bye", 3)) { fprintf(stderr, "LCD server will go, quitting.\n"); lcd_net_stop(); break; } printf("unhandled message: %s\n", buffer); } return(True); } static int lcd_net_read(char *buf, int nbytes) { int nread; nread = read(sockfd, buf, nbytes); if(nread == -1 && errno == EWOULDBLOCK) /* assume non blocking socket */ return(-2); return(nread); } static int lcd_net_writen(const char *buf, int nbytes) { int nleft, nwritten = 0; nleft = nbytes; while(nleft > 0) { nwritten = write(sockfd, buf, nleft); if(nwritten <= 0) return(nwritten); nleft -= nwritten; buf+= nwritten; } return(nbytes-nleft); }