00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00045 #include <cfg/lcd.h>
00046
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050
00051 #include <dev/term.h>
00052
00053 #include <sys/thread.h>
00054 #include <sys/timer.h>
00055 #include <sys/event.h>
00056
00057 #include <arpa/inet.h>
00058
00059 #include "config.h"
00060 #include "webradio.h"
00061 #include "shoutcast.h"
00062 #include "mp3player.h"
00063 #include "tlv320dac.h"
00064 #include "buttons.h"
00065 #include "userif.h"
00066
00073 #ifndef LCD_VCOLS
00074 #ifdef AT91SAM7X_EK
00075 #define LCD_VCOLS 40
00076 #else
00077 #define LCD_VCOLS 80
00078 #endif
00079 #endif
00080
00081 #ifndef LCD_SCROLL_GAP
00082 #define LCD_SCROLL_GAP (LCD_COLS / 2)
00083 #endif
00084
00085 #ifndef UI_REFRESH_RATE
00086 #define UI_REFRESH_RATE 300
00087 #endif
00088
00089 #ifndef UI_THREAD_STACK
00090 #ifdef AT91SAM7X_EK
00091 #define UI_THREAD_STACK 512
00092 #else
00093 #define UI_THREAD_STACK 2048
00094 #endif
00095 #endif
00096
00097 typedef struct {
00098 char dln_status[LCD_VCOLS + 1];
00099 char dln_msg[LCD_VCOLS + 1];
00100 u_int dln_step;
00101 u_int dln_len;
00102 u_int dln_msgticks;
00103 } DISPLAYLINE;
00104
00105 typedef struct {
00106 FILE *dpi_stream;
00107 u_int dpi_scrolling;
00108 char *dpi_sptr;
00109 char dpi_buff[LCD_COLS + 1];
00110 DISPLAYLINE dpi_line[LCD_ROWS];
00111 } DISPLAYINFO;
00112
00113 static DISPLAYINFO display;
00114
00118 static void DisplayRefresh(void)
00119 {
00120 u_int ln;
00121 u_int cn;
00122 DISPLAYLINE *dlp;
00123 char *line;
00124
00125 for (ln = 0; ln < LCD_ROWS; ln++) {
00126 dlp = &display.dpi_line[ln];
00127
00128
00129
00130
00131 if (dlp->dln_msgticks) {
00132
00133 line = dlp->dln_msg;
00134 dlp->dln_msgticks--;
00135 } else {
00136
00137 line = dlp->dln_status;
00138 }
00139
00140
00141
00142
00143 if (dlp->dln_len != strlen(line)) {
00144 dlp->dln_len = strlen(line);
00145 dlp->dln_step = 0;
00146 }
00147
00148
00149 fprintf(display.dpi_stream, ESC_POS "%c" "\x20", ln + 32);
00150
00151 if (dlp->dln_len <= LCD_COLS) {
00152
00153 fputs(line, display.dpi_stream);
00154 if (dlp->dln_len < LCD_COLS) {
00155 fputs(ESC_CLREOL, display.dpi_stream);
00156 }
00157 }
00158 else {
00159 for (cn = 0; cn < LCD_COLS; cn++) {
00160 if (dlp->dln_step + cn < dlp->dln_len) {
00161 display.dpi_buff[cn] = line[dlp->dln_step + cn];
00162 }
00163 else if (dlp->dln_step + cn < dlp->dln_len + LCD_SCROLL_GAP) {
00164 display.dpi_buff[cn] = ' ';
00165 }
00166 else {
00167 display.dpi_buff[cn] = line[dlp->dln_step + cn - (dlp->dln_len + LCD_SCROLL_GAP)];
00168 }
00169 }
00170 fputs(display.dpi_buff, display.dpi_stream);
00171
00172
00173 dlp->dln_step++;
00174 if (dlp->dln_step >= dlp->dln_len + LCD_SCROLL_GAP) {
00175 dlp->dln_step = 0;
00176 }
00177 }
00178 }
00179 }
00180
00186 static void UserIfShowStationConf(STATIONCONF * scp)
00187 {
00188 if (scp->rs_port) {
00189 if (scp->rs_symbol && scp->rs_symbol[0]) {
00190 strncpy(display.dpi_line[0].dln_status, scp->rs_symbol, LCD_VCOLS);
00191 } else {
00192 strncpy(display.dpi_line[0].dln_status, inet_ntoa(scp->rs_ip), LCD_VCOLS);
00193 }
00194 } else {
00195 display.dpi_line[0].dln_status[0] = 0;
00196 }
00197 }
00198
00206 static void UserIfShowStationInfo(STATIONINFO * sip)
00207 {
00208 if (sip) {
00209 if (sip->si_name && sip->si_name[0]) {
00210 strncpy(display.dpi_line[0].dln_status, sip->si_name, LCD_VCOLS);
00211 } else {
00212 UserIfShowStationConf(sip->si_scp);
00213 }
00214 } else {
00215 display.dpi_line[0].dln_status[0] = 0;
00216 }
00217 }
00218
00223 void UserIfMainMenu(void)
00224 {
00225 char key;
00226 u_int tmocnt = 0;
00227 u_char want = radio.rc_cstation;
00228
00229 for (;;) {
00230 UserIfShowStationConf(&station[want]);
00231 strcpy(display.dpi_line[1].dln_status, "Prev Select Next");
00232 DisplayRefresh();
00233
00234
00235 if ((key = ButtonRead(UI_REFRESH_RATE)) == 0) {
00236
00237
00238 if (++tmocnt > 20) {
00239 want = radio.rc_cstation;
00240 break;
00241 }
00242 }
00243 else {
00244 tmocnt = 0;
00245 if (key == KEYCODE_DOWN) {
00246
00247 want = StationSelect(want, -1);
00248 }
00249 else if (key == KEYCODE_UP) {
00250
00251 want = StationSelect(want, 1);
00252 }
00253 else if (key == KEYCODE_SELECT) {
00254
00255 break;
00256 }
00257 }
00258 }
00259 if (want != radio.rc_cstation) {
00260 UserIfShowMessage(1, 5, "Please wait");
00261 radio.rc_rstation = want;
00262 }
00263 }
00264
00270 THREAD(UserIfThread, arg)
00271 {
00272 char key;
00273
00274 fputs(ESC_CURSOROFF, display.dpi_stream);
00275 NutThreadSetPriority(128);
00276
00277 for (;;) {
00278 key = ButtonRead(UI_REFRESH_RATE);
00279 if (key == KEYCODE_SELECT) {
00280 UserIfMainMenu();
00281 }
00282 else {
00283 if (key) {
00284 if (key == KEYCODE_DOWN) {
00285 if (radio.rc_rvolume > DAC_MIN_VOLUME) {
00286 radio.rc_rvolume--;
00287 }
00288 }
00289 else if (key == KEYCODE_UP) {
00290 if (radio.rc_rvolume < DAC_MAX_VOLUME) {
00291 radio.rc_rvolume++;
00292 }
00293 }
00294 UserIfShowMessage(1, 2, "Volume %d dB", radio.rc_rvolume);
00295 }
00296 DisplayRefresh();
00297 }
00298 }
00299 }
00300
00309 void UserIfShowMessage(u_char row, u_char secs, CONST char *fmt, ...)
00310 {
00311 va_list ap;
00312
00313 va_start(ap, fmt);
00314 if (secs) {
00315 vsprintf(display.dpi_line[row].dln_msg, fmt, ap);
00316 display.dpi_line[row].dln_msgticks = secs * (1000 / UI_REFRESH_RATE);
00317 } else
00318 vsprintf(display.dpi_line[row].dln_status, fmt, ap);
00319 va_end(ap);
00320 }
00321
00327 void UserIfShowStatus(u_char status)
00328 {
00329 if (radio.rc_cstatus != status) {
00330 if (status == DIST_FORCE)
00331 status = radio.rc_cstatus;
00332 else
00333 radio.rc_cstatus = status;
00334
00335 if (status == DIST_NONE) {
00336 strcpy(display.dpi_line[0].dln_status, "Internet Radio");
00337 strcpy(display.dpi_line[1].dln_status, "Version ");
00338 strcat(display.dpi_line[1].dln_status, VERSION);
00339 } else if (status == DIST_DEAD) {
00340 UserIfShowStationConf(&station[radio.rc_cstation]);
00341 UserIfShowMessage(1, 2, "not available");
00342 } else if (status == DIST_CONNECTING) {
00343 UserIfShowStationConf(&station[radio.rc_cstation]);
00344 strcpy(display.dpi_line[1].dln_status, "Connecting...");
00345 } else if (status == DIST_CONNECTED) {
00346 UserIfShowStationInfo(radio.rc_sip);
00347 if (radio.rc_rip) {
00348 SHOUTCASTINFO *sci = (SHOUTCASTINFO *) radio.rc_rip->ri_bcast;
00349 if (sci) {
00350 if (sci->sci_metatitle && sci->sci_metatitle[0]) {
00351 strncpy(display.dpi_line[1].dln_status, sci->sci_metatitle, LCD_VCOLS);
00352 }
00353 else if (radio.rc_sip && radio.rc_sip->si_genre && radio.rc_sip->si_genre[0]) {
00354 strncpy(display.dpi_line[1].dln_status, radio.rc_sip->si_genre, LCD_VCOLS);
00355 }
00356 }
00357 }
00358 }
00359 }
00360 }
00361
00369 int UserIfInit(char *name)
00370 {
00371
00372 ButtonInit();
00373
00374 if ((display.dpi_stream = fopen(name, "w")) == 0) {
00375 return -1;
00376 }
00377 display.dpi_scrolling = LCD_ROWS;
00378
00379 if (NutThreadCreate("displ", UserIfThread, 0, UI_THREAD_STACK) == 0) {
00380 fclose(display.dpi_stream);
00381 display.dpi_stream = NULL;
00382 return -1;
00383 }
00384 radio.rc_cstatus = DIST_NONE;
00385 UserIfShowStatus(DIST_FORCE);
00386
00387 return 0;
00388 }