Fixed compilier warnings. Especialy signedness of char buffers as well as unused code on arm platform and main functions without return value
Revision 1.6 2006/08/31 19:14:44 haraldkipp Not all platforms do have devDebug0. Use board.h to determine the correct driver.
Revision 1.5 2006/07/21 09:06:36 haraldkipp Exclude AVR specific parts from building for other platforms. This does not imply, that all samples are working on all platforms.
Revision 1.4 2006/05/15 12:51:47 haraldkipp Player start timeout increased.
Revision 1.3 2004/05/11 17:22:12 drsung Deprecated header file removed.
Revision 1.2 2003/11/04 17:46:52 haraldkipp Adapted to Ethernut 2
Revision 1.1 2003/07/21 17:50:48 haraldkipp First check in
Shoutcast radio application..
00001 /* 00002 * Copyright (C) 2003-2006 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 * 00032 */ 00033 00071 #include <stdlib.h> 00072 #include <string.h> 00073 #include <stdio.h> 00074 #include <io.h> 00075 00076 #include <dev/board.h> 00077 #include <dev/debug.h> 00078 #include <dev/term.h> 00079 #include <dev/hd44780.h> 00080 #include <dev/vs1001k.h> 00081 #ifdef ETHERNUT2 00082 #include <dev/lanc111.h> 00083 #else 00084 #include <dev/nicrtl.h> 00085 #endif 00086 00087 #include <sys/heap.h> 00088 #include <sys/thread.h> 00089 #include <sys/timer.h> 00090 00091 #include <netinet/tcp.h> 00092 #include <arpa/inet.h> 00093 #include <net/route.h> 00094 00095 #include <pro/dhcp.h> 00096 00097 #include <sys/bankmem.h> 00098 #include <dev/irsony.h> 00099 00100 #include "config.h" 00101 #include "display.h" 00102 #include "scanner.h" 00103 #include "player.h" 00104 00105 #if defined(__AVR__) 00106 00107 /* 00108 * TCP buffer size. 00109 */ 00110 static u_short tcpbufsiz = 4288; 00111 00112 /* 00113 * Maximum segment size, choose 536 up to 1460. Note, that segment 00114 * sizes above 536 may result in fragmented packets. Remember, that 00115 * Ethernut doesn't support TCP fragmentation. 00116 */ 00117 static u_short mss = 536; 00118 00119 /* 00120 * Socket receive timeout. 00121 */ 00122 static u_long rx_to = 1000; 00123 00124 /* 00125 * Connect to a radio station. 00126 */ 00127 static TCPSOCKET *ConnectStation(RADIOSTATION * rsp) 00128 { 00129 TCPSOCKET *sock; 00130 int rc; 00131 00132 /* Create a socket. TODO: A failure is fatal and should restart 00133 the system. */ 00134 if ((sock = NutTcpCreateSocket()) == 0) 00135 return sock; 00136 00137 /* Set socket options. Failures are ignored. */ 00138 if (NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss))) 00139 printf("Sockopt MSS failed\n"); 00140 if (NutTcpSetSockOpt(sock, SO_RCVTIMEO, &rx_to, sizeof(rx_to))) 00141 printf("Sockopt TO failed\n"); 00142 if (NutTcpSetSockOpt(sock, SO_RCVBUF, &tcpbufsiz, sizeof(tcpbufsiz))) 00143 printf("Sockopt rxbuf failed\n"); 00144 00145 /* Connect the stream server. */ 00146 printf("[CNCT %s:%u]", inet_ntoa(rsp->rs_ip), rsp->rs_port); 00147 if ((rc = NutTcpConnect(sock, rsp->rs_ip, rsp->rs_port)) == 0) { 00148 printf("[CNCTD]"); 00149 /* Process header from server. */ 00150 if (ScanStreamHeader(sock, rsp) == 0) { 00151 /* TODO: Failed to start the player is fatal. */ 00152 if (PlayerStart(sock, rsp->rs_metaint, 30000)) { 00153 NutTcpCloseSocket(sock); 00154 sock = 0; 00155 } 00156 } else { 00157 NutTcpCloseSocket(sock); 00158 sock = 0; 00159 } 00160 } else { 00161 printf("[CERR=%d]\n", NutTcpError(sock)); 00162 NutTcpCloseSocket(sock); 00163 sock = 0; 00164 } 00165 return sock; 00166 } 00167 00168 /* 00169 * Disconnect from a radio station. 00170 */ 00171 static void DisconnectStation(TCPSOCKET * sock) 00172 { 00173 if (PlayerStop(3000)) { 00174 printf("[PPFAIL]"); 00175 } 00176 printf("Disconnecting\n"); 00177 NutTcpCloseSocket(sock); 00178 } 00179 00180 /* 00181 * Get next command from user interface. 00182 * 00183 * We are supporting the remote control only for now. 00184 */ 00185 static u_short UserInput(void) 00186 { 00187 u_short rc; 00188 static u_short old = 0xFFFF; 00189 00190 if ((rc = (u_short) NutIrGet(500)) == 0xFFFF) 00191 old = rc; 00192 else if (rc == old || (rc >> 7) != IR_DEVICE) 00193 rc = 0xFFFF; 00194 else { 00195 old = rc; 00196 rc &= 0x7F; 00197 if (rc == IRCMD_VOL_UP || rc == IRCMD_VOL_DN) 00198 old = 0xFFFF; 00199 } 00200 return rc; 00201 } 00202 00203 /* 00204 * If we got a background scanner 00205 */ 00206 static void StationList(void) 00207 { 00208 u_char cf = 1; 00209 u_char rs = radio.rc_cstation; 00210 u_short ircode; 00211 00212 DisplayMessage(0, 1, "Stations"); 00213 DisplayEntry(rs); 00214 while (cf) { 00215 /* 00216 * Process user input. 00217 */ 00218 if ((ircode = UserInput()) != 0xFFFF) { 00219 switch (ircode) { 00220 case IRCMD_CHAN_UP: 00221 if (++rs >= MAXNUM_STATIONS) 00222 rs = 0; 00223 DisplayEntry(rs); 00224 break; 00225 case IRCMD_CHAN_DN: 00226 if (rs) 00227 rs--; 00228 else 00229 rs = MAXNUM_STATIONS - 1; 00230 DisplayEntry(rs); 00231 break; 00232 case IRCMD_SELECT: 00233 radio.rc_rstation = rs; 00234 default: 00235 cf = 0; 00236 break; 00237 } 00238 } 00239 } 00240 DisplayStatus(DIST_FORCE); 00241 } 00242 00246 static void UserInterface(void) 00247 { 00248 u_char ief; 00249 u_short ircode; 00250 TCPSOCKET *sock = 0; 00251 00252 for (;;) { 00253 00254 /* 00255 * Process user input. 00256 */ 00257 if ((ircode = UserInput()) != 0xFFFF) { 00258 radio.rc_off = 0; 00259 switch (ircode) { 00260 case IRCMD_CHAN_1: 00261 radio.rc_rstation = 1; 00262 break; 00263 case IRCMD_CHAN_2: 00264 radio.rc_rstation = 2; 00265 break; 00266 case IRCMD_CHAN_3: 00267 radio.rc_rstation = 3; 00268 break; 00269 case IRCMD_CHAN_4: 00270 radio.rc_rstation = 4; 00271 break; 00272 case IRCMD_CHAN_5: 00273 radio.rc_rstation = 5; 00274 break; 00275 case IRCMD_CHAN_6: 00276 radio.rc_rstation = 6; 00277 break; 00278 case IRCMD_CHAN_7: 00279 radio.rc_rstation = 7; 00280 break; 00281 case IRCMD_CHAN_8: 00282 radio.rc_rstation = 8; 00283 break; 00284 case IRCMD_CHAN_9: 00285 radio.rc_rstation = 9; 00286 break; 00287 case IRCMD_CHAN_UP: 00288 radio.rc_rstation = NEXT_STATION; 00289 break; 00290 case IRCMD_CHAN_DN: 00291 radio.rc_rstation = PREV_STATION; 00292 break; 00293 case IRCMD_VOL_UP: 00294 player.psi_start = 1; 00295 if (radio.rc_rvolume < 245) 00296 radio.rc_rvolume += 10; 00297 break; 00298 case IRCMD_VOL_DN: 00299 player.psi_start = 1; 00300 if (radio.rc_rvolume > 10) 00301 radio.rc_rvolume -= 10; 00302 break; 00303 case IRCMD_MUTE: 00304 radio.rc_rmute = !radio.rc_rmute; 00305 break; 00306 case IRCMD_OFF: 00307 radio.rc_off = 1; 00308 DisplayMessage(0, 0, "Shutdown..."); 00309 DisplayMessage(1, 0, ""); 00310 PlayerStop(1000); 00311 ConfigSave(); 00312 radio.rc_cstation = PREV_STATION; 00313 DisplayMessage(0, 0, ""); 00314 break; 00315 case IRCMD_VTEXT: 00316 StationList(); 00317 break; 00318 default: 00319 DisplayMessage(0, 1, "Code %u", ircode); 00320 ief = VsPlayerInterrupts(0); 00321 printf("%lu kBytes used, %lu kBytes free\n", NutSegBufUsed() / 1024UL, NutSegBufAvailable() / 1024UL); 00322 VsPlayerInterrupts(ief); 00323 break; 00324 } 00325 } 00326 00327 if (radio.rc_off) { 00328 NutSleep(500); 00329 continue; 00330 } 00331 00332 /* 00333 * Handle station changes. 00334 */ 00335 if (radio.rc_rstation != radio.rc_cstation) { 00336 /* Disconnect current stream. */ 00337 if (sock) { 00338 DisconnectStation(sock); 00339 sock = 0; 00340 } 00341 00342 /* If scanning, move to the next/previous station. */ 00343 if (radio.rc_rstation == NEXT_STATION) { 00344 if (++radio.rc_cstation >= MAXNUM_STATIONS) 00345 radio.rc_rstation = 0; 00346 } else if (radio.rc_rstation == PREV_STATION) { 00347 if (radio.rc_cstation) 00348 radio.rc_cstation--; 00349 else 00350 radio.rc_cstation = MAXNUM_STATIONS - 1; 00351 } else { 00352 radio.rc_cstation = radio.rc_rstation; 00353 } 00354 00355 DisplayMessage(0, 1, "Station %03u", radio.rc_cstation); 00356 00357 /* Check for valid IP address and port. */ 00358 if (station[radio.rc_cstation].rs_ip && station[radio.rc_cstation].rs_port) { 00359 if (station[radio.rc_cstation].rs_scandead) { 00360 DisplayStatus(DIST_DEAD); 00361 } else { 00362 DisplayStatus(DIST_CONNECTING); 00363 if ((sock = ConnectStation(&station[radio.rc_cstation])) != 0) { 00364 radio.rc_rstation = radio.rc_cstation; 00365 DisplayStatus(DIST_CONNECTED); 00366 } else { 00367 DisplayStatus(DIST_DEAD); 00368 } 00369 } 00370 } else { 00371 DisplayStatus(DIST_DEAD); 00372 } 00373 } else if (radio.rc_cmute != radio.rc_rmute) { 00374 00375 radio.rc_cmute = radio.rc_rmute; 00376 if (radio.rc_cmute) { 00377 DisplayMessage(0, 1, "Mute"); 00378 VsSetVolume(255, 255); 00379 } else { 00380 DisplayMessage(0, 1, "Volume %u", radio.rc_cvolume); 00381 VsSetVolume(255 - radio.rc_cvolume, 255 - radio.rc_cvolume); 00382 } 00383 } else if (radio.rc_cvolume != radio.rc_rvolume) { 00384 DisplayMessage(0, 1, "Volume %u", radio.rc_rvolume); 00385 VsSetVolume(255 - radio.rc_rvolume, 255 - radio.rc_rvolume); 00386 radio.rc_cvolume = radio.rc_rvolume; 00387 radio.rc_rmute = 0; 00388 } else if (player.psi_metaupdate) { 00389 DisplayStatus(DIST_FORCE); 00390 player.psi_metaupdate = 0; 00391 } 00392 } 00393 } 00394 00395 #endif /* __AVR__ */ 00396 00397 /* 00398 * Main entry of the Internet Radio Application. 00399 */ 00400 int main(void) 00401 { 00402 #if defined(__AVR__) 00403 /* Unique MAC address of the Ethernut Board. */ 00404 u_char mac[6] = { 0x00, 0x06, 0x98, 0x00, 0x00, 0x00 }; 00405 /* Unique IP address of the Ethernut Board. Ignored if DHCP is used. */ 00406 u_long ip_addr = inet_addr("192.168.192.100"); 00407 /* IP network mask of the Ethernut Board. Ignored if DHCP is used. */ 00408 u_long ip_mask = inet_addr("255.255.255.0"); 00409 /* Gateway IP address for the Ethernut Board. Ignored if DHCP is used. */ 00410 u_long ip_gate = inet_addr("192.168.192.3"); 00411 /* Baudrate for debug output. */ 00412 #endif 00413 u_long baud = 115200; 00414 00415 /* 00416 * Assign stdout to the debug device. 00417 */ 00418 NutRegisterDevice(&DEV_DEBUG, 0, 0); 00419 freopen(DEV_DEBUG_NAME, "w", stdout); 00420 _ioctl(_fileno(stdout), UART_SETSPEED, &baud); 00421 00422 /* 00423 * Load configuration and display banner. 00424 */ 00425 if (ConfigLoad()) 00426 ConfigResetFactory(); 00427 00428 #if defined(__AVR__) 00429 /* 00430 * Initialize the MP3 device early to avoid noice, caused 00431 * by floating, tri-stated port lines. 00432 */ 00433 if (NutSegBufInit(8192) == 0) { 00434 printf("Can't init segbuf\n"); 00435 for (;;); 00436 } 00437 PlayerInit(); 00438 00439 /* 00440 * Initialize the LCD. 00441 */ 00442 NutRegisterDevice(&devLcd, 0, 0); 00443 if (DisplayInit("lcd")) { 00444 printf("Display failure\n"); 00445 for (;;); 00446 } 00447 00448 /* 00449 * Initialize IR remote control. 00450 */ 00451 NutIrInitSony(); 00452 00453 /* 00454 * LAN configuration using EEPROM values or DHCP/ARP method. 00455 * If it fails, use fixed values. 00456 */ 00457 if (NutRegisterDevice(&DEV_ETHER, 0x8300, 5)) 00458 puts("Registering device failed"); 00459 if (NutDhcpIfConfig("eth0", 0, 60000)) { 00460 puts("EEPROM/DHCP/ARP config failed"); 00461 NutNetIfConfig("eth0", mac, ip_addr, ip_mask); 00462 NutIpRouteAdd(0, 0, ip_gate, &DEV_ETHER); 00463 } 00464 puts("ready\n"); 00465 00466 VsSetVolume(255 - radio.rc_rvolume, 255 - radio.rc_rvolume); 00467 VsBeep(2, 100); 00468 00469 /* 00470 * Start the background scanner. 00471 */ 00472 //ScannerInit(); 00473 00474 /* 00475 * Call the user interface.. 00476 */ 00477 for (;;) { 00478 UserInterface(); 00479 } 00480 #endif /* __AVR__ */ 00481 00482 for (;;) 00483 NutSleep(1000); 00484 00485 return 0; 00486 }