⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 webradio.c

📁 Internet Radio Internet Radio Internet Radio Internet Radio Internet Radio
💻 C
字号:
/*
 * Copyright (C) 2006-2007 by egnite Software GmbH. All rights reserved.
 * Copyright (C) 2008 by egnite GmbH. 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.
 * 3. Neither the name of the copyright holders nor the names of
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
 * COPYRIGHT OWNER 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.
 *
 * For additional information see http://www.ethernut.de/
 */

/*!
 * \file webradio.c
 * \brief Internet radio main file.
 *
 * \verbatim
 *
 * $Log$
 *
 * \endverbatim
 */


/*
 * Limited AT91SAM9260-EK MP3 player sample.
 *
 * Will sequentially play all MP3 files from an MMC's root directory.
 *
 * MultiMedia Cards only, no SD Cards (see arch/arm/dev/at91_mmc.c).
 * Root directory must contain MP3 files only.
 * Hardcoded for 180MHz CPU clock and 44.1kHz sampling rate (also see ./at73dac.c).
 */

#include <cfg/os.h>
#include <cfg/clock.h>
#include <dev/board.h>
#include <dev/st7036.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <io.h>

#include <sys/version.h>
#include <sys/confos.h>
#include <sys/confnet.h>
#include <sys/atom.h>
#include <sys/heap.h>
#include <sys/thread.h>
#include <sys/timer.h>
#include <sys/event.h>
#include <sys/socket.h>

#if defined(USE_SOFTWARE_CODEC)
#include <hxmp3/mp3dec.h>
#endif

#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <netdb.h>

#include <pro/dhcp.h>
#include <pro/sntp.h>
#include <pro/discover.h>

#include <dev/vscodec.h>

#include "config.h"
#include "logmsg.h"
#include "favlist.h"
#include "shoutcast.h"
#include "httpserv.h"
#include "xmlserv.h"
#include "userif.h"

/*
 * Unique MAC address of the Ethernut Board.
 *
 * Ignored if EEPROM contains a valid configuration.
 */
#define MY_MAC { 0x00, 0x06, 0x98, 0x30, 0x00, 0x39 }

/*
 * Unique IP address of the Ethernut Board.
 *
 * Ignored if DHCP is used.
 */
#define MY_IPADDR "192.168.192.39"

/*
 * IP network mask of the Ethernut Board.
 *
 * Ignored if DHCP is used.
 */
#define MY_IPMASK "255.255.255.0"

/*
 * Gateway IP address for the Ethernut Board.
 *
 * Ignored if DHCP is used.
 */
#define MY_IPGATE "192.168.192.1"

/*
 * Wether we should run a discovery responder.
 */
#if defined(AT91SAM9260_EK) || defined(ELEKTOR_IR1)
#define USE_DISCOVERY
#endif

/*
 * IP address of the host running a time daemon. 
 */
#if defined(AT91SAM9260_EK) || defined(ELEKTOR_IR1)
//#define MY_TIMED "130.149.17.21"
#endif

/*
 * Local timezone, -1 for Central Europe. 
 */
#ifndef MY_TZ
#define MY_TZ    -1
#endif


WEBRADIO webradio;

/*
 * Query a time server and optionally update the hardware clock.
 */
static int QueryTimeServer(void)
{
    int rc = -1;

#ifdef MY_TIMED
    int retries = 5;

    _timezone = MY_TZ * 60L * 60L;
    while (retries--) {
        time_t now;
        u_long timeserver = inet_addr(MY_TIMED);

        /* Query network time service and set the system time. */
        LogMsg(LOG_STARTUP, "Query time from %s...", MY_TIMED);
        if(NutSNTPGetTime(&timeserver, &now) == 0) {
            LogMsg(LOG_STARTUP, "OK\n");
            rc = 0;
            stime(&now);
            break;
        }
        else {
            LogMsg(LOG_STARTUP, "failed\n");
        }
    }
#endif

    return rc;
}

int InitEthernetDevice(void)
{
    u_long ip_addr = inet_addr(MY_IPADDR);
    u_long ip_mask = inet_addr(MY_IPMASK);
    u_long ip_gate = inet_addr(MY_IPGATE);
    u_char mac[6] = MY_MAC;

    for (;;) {
        LogMsg(LOG_STARTUP, "Register %s...", DEV_ETHER_NAME);
        if (NutRegisterDevice(&DEV_ETHER, 0x8300, 5) == 0) {
            LogMsg(LOG_STARTUP, "OK\n");
            break;
        }
        LogMsg(LOG_STARTUP, "No Ethernet, retry\n");
    }

    LogMsg(LOG_STARTUP, "Configure %s...", DEV_ETHER_NAME);
    if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) == 0) {
        LogMsg(LOG_STARTUP, "OK\n");
        return 0;
    }
    LogMsg(LOG_STARTUP, "initial boot...");
    if (NutDhcpIfConfig(DEV_ETHER_NAME, mac, 60000) == 0) {
        LogMsg(LOG_STARTUP, "OK\n");
        return 0;
    }
    LogMsg(LOG_STARTUP, "No DHCP...");
    NutNetIfConfig(DEV_ETHER_NAME, mac, ip_addr, ip_mask);
    /* Without DHCP we had to set the default gateway manually.*/
    if(ip_gate) {
        LogMsg(LOG_STARTUP, "hard coded gate...");
        NutIpRouteAdd(0, 0, ip_gate, &DEV_ETHER);
    }
    LogMsg(LOG_STARTUP, "OK\n");

    return 0;
}


/*!
 * \brief Main application routine.
 */
int main(void)
{
    u_long baud = 115200;
    u_long ipgate;
    int stream_idx = 0;
    u_int rstat;
    u_int ostat = 0;

    /*
     * Register and open the DBGU device, which we will use for debug 
     * output via stdout.
     */
    NutRegisterDevice(&DEV_DEBUG, 0, 0);
    freopen(DEV_DEBUG_NAME, "w", stdout);
    _ioctl(_fileno(stdout), UART_SETSPEED, &baud);

    /*
     * Display some general information.
     */
#ifdef LOG_ENABLE
#if LOG_ENABLE
    LogMsg((u_int)-1, "Internet Radio %s - Nut/OS %s\n", VERSION, NutVersionString());
#endif
#endif
    LogMsg(LOG_STARTUP, "%u bytes free\n", (u_int)NutHeapAvailable());
    LogMsg(LOG_STARTUP, "CPU Clock   : %lu\n", NutGetCpuClock());
    LogMsg(LOG_STARTUP, "Master Clock: %lu\n", At91GetMasterClock());

    if (NutLoadConfig() == 0) {
        LogMsg(LOG_STARTUP, "Hostname: %s\n", confos.hostname);
    }

    /*
     * Load configuration.
     */
    if (ConfigInit()) {
        /* No configuration memory, run with factory defaults. */
        ConfigResetFactory();
        FavListResetFactory();
    }
    else {
        if (ConfigLoad()) {
            /* No configuration info, use factory defaults. */
            ConfigResetFactory();
            ConfigSave();
        }
        if (FavListLoad()) {
            /* No favorites, use hard coded entries. */
            FavListResetFactory();
            FavListSave();
        }
    }

    /*
     * Register codec device.
     */
    if (NutRegisterDevice(&devVsCodec, 0, 0)) {
        LogMsg(LOG_ERROR, "No audio decoder\n");
        for(;;);
    }
#if USE_DISPLAY
    /*
     * Initialize the user interface, LCD and 3 buttons.
     */
    if (NutRegisterDevice(&devSbiLcd, 0, 0)) {
        LogMsg(LOG_ERROR, "Failed to register LCD\n");
    }
#endif

    if (UserIfInit("sbilcd")) {
        LogMsg(LOG_ERROR, "LCD init failure\n");
    }

    /* 
     * Initialize the Ethernet device and print our IP setting. 
     */
    InitEthernetDevice();
    NutIpRouteQuery(0, &ipgate);
    LogMsg(LOG_STARTUP, "IP Addr: %s\n", inet_ntoa(confnet.cdn_ip_addr));
    LogMsg(LOG_STARTUP, "IP Mask: %s\n", inet_ntoa(confnet.cdn_ip_mask));
    LogMsg(LOG_STARTUP, "IP Gate: %s\n", inet_ntoa(ipgate));
    LogMsg(LOG_STARTUP, "PrimDNS: %s\n", inet_ntoa(webradio.wr_pridns));
    LogMsg(LOG_STARTUP, "Sec DNS: %s\n", inet_ntoa(webradio.wr_secdns));
    if (confnet.cdn_cip_addr) {
        NutDnsConfig2(NULL, NULL, webradio.wr_pridns, webradio.wr_secdns);
    }

    /* 
     * Register a discovery responder. This optional feature
     * allows to discover all Nut/OS devices in a local network.
     */
#ifdef USE_DISCOVERY
    LogMsg(LOG_STARTUP, "Start Responder...");
    if (NutRegisterDiscovery((u_long)-1, 0, DISF_INITAL_ANN)) {
        LogMsg(LOG_STARTUP, "failed\n");
    }
    else {
        LogMsg(LOG_STARTUP, "OK\n");
    }
#endif

    /*
     * Try to get current date and time from an SNTP server.
     */
    if (QueryTimeServer() == 0) {
        time_t now = time(0);
        struct _tm *lot = localtime(&now);
        LogMsg(LOG_STARTUP, "Date: %02u.%02u.%u\n", lot->tm_mday, lot->tm_mon + 1, 1900 + lot->tm_year);
        LogMsg(LOG_STARTUP, "Time: %02u:%02u:%02u\n", lot->tm_hour, lot->tm_min, lot->tm_sec);
#ifdef USE_HTTPSERVER
        h_timevalid = 1;
#endif
    }

#ifdef USE_HTTPSERVER
    HttpServerStart();
    XmlServerStart();
#endif

    /*
     * Create all supported receiver instances.
     */
    webradio.wr_ritab[0] = ReceiverCreate(&rpiShoutcast);

    /*
     * Never ending station selection loop.
     */
    for (;;) {
        /*
         * Connect station.
         */
        UserIfShowStatus(DIST_CONNECTING);
        webradio.wr_sip = StationConnect(&favlist[1], stream_idx);
        if (webradio.wr_sip == NULL) {
            /* Connection failed. */
            UserIfShowStatus(DIST_DEAD);
            NutSleep(1000);
        } else {
            /* Station connected, start receiver. */
            webradio.wr_rip = ReceiverStart(webradio.wr_ritab, webradio.wr_sip);
            if (webradio.wr_rip == NULL) {
                /* Receiver start failed. */
                UserIfShowStatus(DIST_DEAD);
                NutSleep(1000);
            } else {
                /* Receiver running. */
                UserIfShowStatus(DIST_CONNECTED);
                /* Save the current station setting. */
                webradio.wr_favupd = 10;
                /* Monitor everything. */
                for (;;) {
                    NutSleep(1000);
                    if (favlist[TOP_FAVORITE].rs_streams) {
                        break;
                    }
                    /* Delayed favorites list storage. */
                    if (webradio.wr_favupd && --webradio.wr_favupd == 0) {
                        FavListSave();
                    }
                    /* Reboot? */
                    if (webradio.wr_reboot) {
                        webradio.wr_reboot--;
                        if (webradio.wr_reboot == 0) {
                            outr(RSTC_CR, RSTC_KEY | RSTC_PROCRST);
                        }
                        LogMsg(LOG_WARN, "Reboot in %ds\n", webradio.wr_reboot);
                    }
                    /* Still playing? */
                    rstat = ReceiverStatus(webradio.wr_rip);
                    if (rstat != ostat) {
                        if (rstat & (RSTAT_IDLE | RSTAT_STOP)) {
                            break;
                        }
                        UserIfShowStatus(DIST_FORCE);
                        ostat = rstat;
                    }
                }
                UserIfShowStatus(DIST_NONE);
                ReceiverStop(webradio.wr_rip);
            }
            StationDisconnect(webradio.wr_sip);
            webradio.wr_sip = NULL;
        }
        if (favlist[TOP_FAVORITE].rs_streams) {
            LogMsg(LOG_STATION, "Selected %s\n", favlist[TOP_FAVORITE].rs_name);
            FavListCopy(TOP_FAVORITE, LAST_FAVORITE);
            FavListSet(TOP_FAVORITE, NULL, NULL);
            stream_idx = 0;
        } else {
            if (++stream_idx >= favlist[LAST_FAVORITE].rs_streams) {
                stream_idx = 0;
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -