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
00034
00046 #include <cfg/lcd.h>
00047
00048 #include <stdio.h>
00049 #include <io.h>
00050 #include <stdlib.h>
00051 #include <string.h>
00052
00053 #include <dev/term.h>
00054 #include <dev/vscodec.h>
00055
00056 #include <sys/thread.h>
00057 #include <sys/timer.h>
00058 #include <sys/event.h>
00059
00060 #include <arpa/inet.h>
00061
00062 #include "config.h"
00063 #include "logmsg.h"
00064 #include "favlist.h"
00065 #include "webradio.h"
00066 #include "shoutcast.h"
00067 #include "xmlserv.h"
00068 #include "buttons.h"
00069 #include "userif.h"
00070
00071 #ifndef UI_THREAD_STACK
00072 #ifdef AT91SAM7X_EK
00073 #define UI_THREAD_STACK 512
00074 #else
00075 #define UI_THREAD_STACK 2048
00076 #endif
00077 #endif
00078
00079 #ifndef UI_REFRESH_RATE
00080 #define UI_REFRESH_RATE 300
00081 #endif
00082
00089 #ifndef LCD_VCOLS
00090 #ifdef AT91SAM7X_EK
00091 #define LCD_VCOLS 40
00092 #else
00093 #define LCD_VCOLS 160
00094 #endif
00095 #endif
00096
00097 typedef struct {
00099 char dln_status[LCD_VCOLS + 1];
00101 char dln_msg[LCD_VCOLS + 1];
00102 #if USE_DISPLAY || USE_TERM
00103 u_int dln_step;
00104 u_int dln_len;
00105 #endif
00106 u_int dln_msgticks;
00107 } DISPLAYLINE;
00108
00109 typedef struct {
00110 #if USE_DISPLAY || USE_TERM
00111
00112 FILE *dpi_stream;
00114 char dpi_buff[LCD_COLS + 1];
00115 #endif
00116 DISPLAYLINE dpi_line[LCD_ROWS];
00117 } DISPLAYINFO;
00118
00119 static DISPLAYINFO display;
00120
00121
00122 #if USE_DISPLAY || USE_TERM
00123 #ifndef LCD_SCROLL_GAP
00124 #define LCD_SCROLL_GAP (LCD_COLS / 2)
00125 #endif
00126 #endif
00127
00131 static void DisplayRefresh(void)
00132 {
00133 #if USE_DISPLAY || USE_TERM
00134 u_int ln;
00135 u_int cn;
00136 DISPLAYLINE *dlp;
00137 char *line;
00138
00139 for (ln = 0; ln < LCD_ROWS; ln++) {
00140 dlp = &display.dpi_line[ln];
00141
00142
00143
00144
00145 if (dlp->dln_msgticks) {
00146
00147 line = dlp->dln_msg;
00148 dlp->dln_msgticks--;
00149 } else {
00150
00151 line = dlp->dln_status;
00152 }
00153
00154
00155
00156
00157 if (dlp->dln_len != strlen(line)) {
00158 dlp->dln_len = strlen(line);
00159 dlp->dln_step = 0;
00160 }
00161
00162
00163 fprintf(display.dpi_stream, ESC_POS "%c" "\x20", ln + 32);
00164
00165 if (dlp->dln_len <= LCD_COLS) {
00166
00167 fputs(line, display.dpi_stream);
00168 if (dlp->dln_len < LCD_COLS) {
00169 fputs(ESC_CLREOL, display.dpi_stream);
00170 }
00171 }
00172 else {
00173 for (cn = 0; cn < LCD_COLS; cn++) {
00174 if (dlp->dln_step + cn < dlp->dln_len) {
00175 display.dpi_buff[cn] = line[dlp->dln_step + cn];
00176 }
00177 else if (dlp->dln_step + cn < dlp->dln_len + LCD_SCROLL_GAP) {
00178 display.dpi_buff[cn] = ' ';
00179 }
00180 else {
00181 display.dpi_buff[cn] = line[dlp->dln_step + cn - (dlp->dln_len + LCD_SCROLL_GAP)];
00182 }
00183 }
00184 fputs(display.dpi_buff, display.dpi_stream);
00185
00186
00187 dlp->dln_step++;
00188 if (dlp->dln_step >= dlp->dln_len + LCD_SCROLL_GAP) {
00189 dlp->dln_step = 0;
00190 }
00191 }
00192 }
00193 #endif
00194 }
00195
00201 static void UserIfShowStationConf(RADIOSTATION * scp)
00202 {
00203 display.dpi_line[0].dln_status[0] = 0;
00204 if (scp && scp->rs_name && scp->rs_name[0]) {
00205 strncpy(display.dpi_line[0].dln_status, scp->rs_name, LCD_VCOLS);
00206 }
00207 }
00208
00216 static void UserIfShowStationInfo(STATIONINFO * sip)
00217 {
00218 display.dpi_line[0].dln_status[0] = 0;
00219 if (sip) {
00220 if (sip->si_name && sip->si_name[0]) {
00221 strncpy(display.dpi_line[0].dln_status, sip->si_name, LCD_VCOLS);
00222 } else {
00223 UserIfShowStationConf(sip->si_scp);
00224 }
00225 }
00226 }
00227
00228 #if USE_DISPLAY || USE_TERM
00229
00233 static void UserIfMainMenu(void)
00234 {
00235 char key;
00236 u_int tmocnt = 0;
00237 int want = 0;
00238
00239 for (;;) {
00240 UserIfShowStationConf(&favlist[want]);
00241 strcpy(display.dpi_line[1].dln_status, "Prev Select Next");
00242 DisplayRefresh();
00243
00244
00245 if ((key = ButtonRead(UI_REFRESH_RATE)) == 0) {
00246
00247
00248 if (++tmocnt > 20) {
00249 want = -1;
00250 }
00251 }
00252 else {
00253 tmocnt = 0;
00254 if (key == KEYCODE_DOWN) {
00255
00256 want = FavListSearch(want, -1);
00257 }
00258 else if (key == KEYCODE_UP) {
00259
00260 want = FavListSearch(want, 1);
00261 }
00262 else if (key == KEYCODE_SELECT) {
00263
00264 break;
00265 }
00266 }
00267 }
00268 if (want > 0) {
00269 if (FavListCopy(want, TOP_FAVORITE) == 0) {
00270 UserIfShowMessage(1, 5, "Please wait");
00271 }
00272 }
00273 }
00274 #endif
00275
00281 THREAD(UserIfThread, arg)
00282 {
00283 char key;
00284
00285 #if USE_DISPLAY || USE_TERM
00286 fputs(ESC_CURSOROFF, display.dpi_stream);
00287 #endif
00288 NutThreadSetPriority(128);
00289
00290 for (;;) {
00291 key = ButtonRead(UI_REFRESH_RATE);
00292 if (key == KEYCODE_SELECT) {
00293 #if USE_DISPLAY || USE_TERM
00294 UserIfMainMenu();
00295 #endif
00296 }
00297 else {
00298 if (key) {
00299 if (key == KEYCODE_DOWN) {
00300 if (webradio.wr_gain > AUDIO_DAC_MIN_GAIN) {
00301 webradio.wr_gain--;
00302 }
00303 }
00304 else if (key == KEYCODE_UP) {
00305 if (webradio.wr_gain < AUDIO_DAC_MAX_GAIN) {
00306 webradio.wr_gain++;
00307 }
00308 }
00309 UserIfShowMessage(1, 2, "Volume %d dB", webradio.wr_gain);
00310 webradio.wr_cfgupd = 10;
00311 if (webradio.wr_rip == NULL ||
00312 webradio.wr_rip->ri_decoder == -1 ||
00313 _ioctl(webradio.wr_rip->ri_decoder, AUDIO_SET_PLAYGAIN, &webradio.wr_gain) != 0) {
00314 LogMsg(LOG_ERROR, "No volume control\n");
00315 }
00316 XmlRefresh();
00317 }
00318 DisplayRefresh();
00319 }
00320 }
00321 }
00322
00331 void UserIfShowMessage(u_char row, u_char secs, CONST char *fmt, ...)
00332 {
00333 va_list ap;
00334
00335 va_start(ap, fmt);
00336 if (secs) {
00337 vsprintf(display.dpi_line[row].dln_msg, fmt, ap);
00338 display.dpi_line[row].dln_msgticks = secs * (1000 / UI_REFRESH_RATE);
00339 } else
00340 vsprintf(display.dpi_line[row].dln_status, fmt, ap);
00341 va_end(ap);
00342 }
00343
00349 void UserIfShowStatus(u_char status)
00350 {
00351 if (webradio.wr_status != status) {
00352 if (status == DIST_FORCE)
00353 status = webradio.wr_status;
00354 else
00355 webradio.wr_status = status;
00356
00357 if (status == DIST_NONE) {
00358 strcpy(display.dpi_line[0].dln_status, "Internet Radio");
00359 strcpy(display.dpi_line[1].dln_status, "Version ");
00360 strcat(display.dpi_line[1].dln_status, VERSION);
00361 } else if (status == DIST_DEAD) {
00362 UserIfShowStationConf(&favlist[LAST_FAVORITE]);
00363 UserIfShowMessage(1, 2, "Not available");
00364 } else if (status == DIST_CONNECTING) {
00365 UserIfShowStationConf(&favlist[LAST_FAVORITE]);
00366 strcpy(display.dpi_line[1].dln_status, "Connecting...");
00367 } else if (status == DIST_CONNECTED) {
00368 UserIfShowStationInfo(webradio.wr_sip);
00369 display.dpi_line[1].dln_status[0] = '\0';
00370 if (webradio.wr_rip) {
00371 SHOUTCASTINFO *sci = (SHOUTCASTINFO *) webradio.wr_rip->ri_bcast;
00372 if (sci) {
00373 if (sci->sci_metatitle && sci->sci_metatitle[0]) {
00374 strncpy(display.dpi_line[1].dln_status, sci->sci_metatitle, LCD_VCOLS);
00375 }
00376 else if (webradio.wr_sip && webradio.wr_sip->si_genre) {
00377 strncpy(display.dpi_line[1].dln_status, webradio.wr_sip->si_genre, LCD_VCOLS);
00378 }
00379 }
00380 }
00381 }
00382 LogMsg(LOG_USERIF, "Display %d.0 '%s'\n", status, display.dpi_line[0].dln_status);
00383 LogMsg(LOG_USERIF, "Display %d.1 '%s'\n", status, display.dpi_line[1].dln_status);
00384 XmlRefresh();
00385 }
00386 }
00387
00396 char * UserIfGetDisplayText(char *buff, size_t siz)
00397 {
00398 if (siz) {
00399 siz--;
00400 buff[siz] = '\0';
00401 if (siz) {
00402 if (display.dpi_line[1].dln_msgticks) {
00403 #if (USE_DISPLAY == 0) && (USE_TERM == 0)
00404 display.dpi_line[1].dln_msgticks = 0;
00405 #endif
00406 strncpy(buff, display.dpi_line[1].dln_msg, siz);
00407 } else {
00408 strncpy(buff, display.dpi_line[1].dln_status, siz);
00409 siz -= strlen(buff);
00410 if (siz > 4 && display.dpi_line[0].dln_status[0]) {
00411 strcat(buff, " ");
00412 strncpy(buff + strlen(buff), display.dpi_line[0].dln_status, siz - 4);
00413 }
00414 }
00415 }
00416 }
00417 return buff;
00418 }
00419
00427 int UserIfInit(char *name)
00428 {
00429
00430 ButtonInit();
00431
00432 #if USE_DISPLAY
00433 if ((display.dpi_stream = fopen(name, "w")) == 0) {
00434 return -1;
00435 }
00436 #elif USE_TERM
00437 display.dpi_stream = stdout;
00438 #endif
00439
00440 if (NutThreadCreate("displ", UserIfThread, 0, UI_THREAD_STACK) == 0) {
00441 #if USE_DISPLAY
00442 fclose(display.dpi_stream);
00443 #endif
00444 #if USE_DISPLAY || USE_TERM
00445 display.dpi_stream = NULL;
00446 #endif
00447 return -1;
00448 }
00449 webradio.wr_status = DIST_NONE;
00450 UserIfShowStatus(DIST_FORCE);
00451
00452 return 0;
00453 }