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

📄 player.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
字号:
/* * Copyright (C) 2003 by egnite Software 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 EGNITE SOFTWARE GMBH 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 EGNITE * SOFTWARE GMBH 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/ * *//*! * $Log: player.c,v $ * Revision 1.2  2003/09/29 16:34:26  haraldkipp * Include file sequence changed * * Revision 1.1  2003/07/21 17:50:48  haraldkipp * First check in * */#include <sys/heap.h>#include <sys/event.h>#include <sys/timer.h>#include <sys/thread.h>#include <dev/vs1001k.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include "player.h"#include <sys/bankmem.h>#define MAX_WAITSTREAM      20#define BIGBUF_WATERMARK    65535ULPLAYERINFO player;/* * Process embedded meta data. */static void ClearMetaData(void){    if (player.psi_metatitle) {        free(player.psi_metatitle);        player.psi_metatitle = 0;    }    if (player.psi_metaurl) {        free(player.psi_metaurl);        player.psi_metaurl = 0;    }}/* * Process embedded meta data. */static int ProcessMetaData(void){    u_char blks = 0;    u_short cnt;    int got;    int rc = 0;    u_char to_cnt = 0;    u_char *mbuf;    u_char *mn1;    u_char *mn2;    u_char *md1;    u_char *md2;    /*     * Wait for the lenght byte.     */    while (player.psi_status == PSI_RUNNING) {        if ((got = NutTcpReceive(player.psi_sock, &blks, 1)) == 1)            break;        if (got < 0 || to_cnt++ > MAX_WAITSTREAM) {            printf("[NoLen]");            return -1;        }    }    if (blks) {        if (blks > 32) {            printf("[Blks=%u]", blks);            return -1;        }        cnt = blks * 16;        if ((mbuf = malloc(cnt + 1)) == 0) {            printf("[NoMem]");            return -1;        }        /*         * Receive the metadata block.         */        while (player.psi_status == PSI_RUNNING) {            if ((got = NutTcpReceive(player.psi_sock, mbuf + rc, cnt)) < 0) {                printf("[RxFail]");                return -1;            }            if (got) {                to_cnt = 0;                if ((cnt -= got) == 0)                    break;                rc += got;                mbuf[rc] = 0;            } else if (to_cnt++ > MAX_WAITSTREAM) {                printf("[RxTo]");                return -1;            }        }        ClearMetaData();        printf("\nMeta='%s'\n", mbuf);        mn1 = mbuf;        while (mn1) {            if ((mn2 = strchr(mn1, ';')) != 0)                *mn2++ = 0;            if ((md1 = strchr(mn1, '=')) != 0) {                *md1++ = 0;                while (*md1 == ' ' || *md1 == '\'')                    md1++;                if ((md2 = strrchr(md1, '\'')) != 0)                    *md2 = 0;                if (strcasecmp(mn1, "StreamTitle") == 0 && player.psi_metatitle == 0) {                    player.psi_metatitle = malloc(strlen(md1) + 1);                    strcpy(player.psi_metatitle, md1);                } else if (strcasecmp(mn1, "StreamUrl") == 0 && player.psi_metaurl == 0) {                    player.psi_metaurl = malloc(strlen(md1) + 1);                    strcpy(player.psi_metaurl, md1);                }            }            mn1 = mn2;        }        free(mbuf);        player.psi_metaupdate = 1;    }    return 0;}/* * Background thread for playing stream. */THREAD(Player, arg){    size_t rbytes;    u_char *mp3buf;    u_char to_cnt = 0;    int got;    u_char ief;    /*     * Nut/OS threads run forever.     */    for (;;) {        /*         * Idle loop.         */        for (;;) {            /* Broadcast idle status. */            printf("[IDLE]");            ClearMetaData();            player.psi_status = PSI_IDLE;            NutEventBroadcast(&player.psi_stsevt);            /* Wait for start event. */            NutEventWait(&player.psi_cmdevt, 0);            printf("[EVT%u]", player.psi_status);            if (player.psi_status == PSI_START)                break;        }        /* Broadcast running event. */        printf("[RUN]");        player.psi_status = PSI_RUNNING;        player.psi_mp3left = player.psi_metaint;        NutEventBroadcast(&player.psi_stsevt);        /* Reset decoder buffer. */        ief = VsPlayerInterrupts(0);        NutSegBufReset();        VsPlayerInterrupts(ief);        /*         * Running loop.         */        while (player.psi_status == PSI_RUNNING) {            /*             * Query number of byte available in MP3 buffer. If it is             * zero, then the player may have stopped running.             */            ief = VsPlayerInterrupts(0);            mp3buf = NutSegBufWriteRequest(&rbytes);            VsPlayerInterrupts(ief);            if (rbytes < 1024) {                if (VsGetStatus() != VS_STATUS_RUNNING)                    VsPlayerKick();                if (rbytes == 0) {                    NutSleep(125);                    continue;                }            }            /* Do not read pass metadata. */            if (player.psi_metaint && rbytes > player.psi_mp3left)                rbytes = player.psi_mp3left;            /*             * Loop until MP3 buffer space is filled.             */            while (rbytes) {                /* Read data directly into the MP3 buffer. */                if ((got = NutTcpReceive(player.psi_sock, mp3buf, rbytes)) < 0) {                    /* This is fatal. Return to idle state. */                    printf("[RXFAIL]");                    player.psi_status = PSI_IDLE;                    break;                }                /*                  * Got some MP3 data.                  */                if (got) {                    /* Commit the buffer. */                    ief = VsPlayerInterrupts(0);                    mp3buf = NutSegBufWriteCommit(got);                    VsPlayerInterrupts(ief);                    /* Reset timeout counter and reduce number of buffer bytes. */                    to_cnt = 0;                    rbytes -= got;                    /* Process meta data. */                    if (player.psi_metaint) {                        player.psi_mp3left -= got;                        if (player.psi_mp3left == 0) {                            if (ProcessMetaData()) {                                printf("[METAFAIL]");                                //player.psi_status = PSI_IDLE;                                //break;                            }                            player.psi_mp3left = player.psi_metaint;                        }                    }                    /* Start early with large buffers. */                    if (VsGetStatus() != VS_STATUS_RUNNING) {                        ief = VsPlayerInterrupts(0);                        if ((NutSegBufUsed() > 2048 && player.psi_start) ||                            (NutSegBufUsed() > BIGBUF_WATERMARK && NutSegBufAvailable() < BIGBUF_WATERMARK))                            VsPlayerKick();                        else                            VsPlayerInterrupts(ief);                    }                    player.psi_start = 0;                }                /*                 * Got no MP3 data.                  */                else {                    printf("[T%u, %u]", to_cnt, NutHeapAvailable());                    NutSleep(100);                    if (to_cnt++ > MAX_WAITSTREAM) {                        /* If timeouts reach our limit, go back to idle state. */                        printf("[RXTO]");                        player.psi_status = PSI_IDLE;                        break;                    }                }                /*                 * If we won't yield the CPU, we may consume the complete                 * TCP buffer before being stopped in NutTcpReceive. That                 * would result in bumpy feeding.                 */                NutThreadYield();            }            /* If play loop is not entered, we may omit the watchdog                update here and force a system reset. */            NutThreadYield();        }        /* Flush decoder and wait until finished. */        printf("[FLUSH]");        VsPlayerFlush();        while (VsGetStatus() == VS_STATUS_RUNNING) {            NutSleep(63);        }        /* Reset the decoder. */        printf("[RESET]");        VsPlayerReset(0);    }}/*! * \brief Initialize the MP3 player. * * Initializes the decoder and the decoder buffer and starts the  * player background thread. */int PlayerInit(void){    /* Init decoder. */    if (VsPlayerInit() || VsPlayerReset(0))        return -1;    /* Start player thread. */    if (NutThreadCreate("player", Player, 0, 512) == 0)        return -1;    return 0;}/*! * \brief Stop MP3 player. * * Force player into idle mode. */int PlayerStop(u_long tmo){    while (player.psi_status != PSI_IDLE) {        printf("[STOP]");        player.psi_status = PSI_STOP;        NutEventPost(&player.psi_cmdevt);        if (NutEventWait(&player.psi_stsevt, tmo)) {            printf("[TOP]");            return -1;        }    }    printf("[STOPPED]");    return 0;}/*! * \brief Start MP3 player. * * If the player is currently running, it will be stopped first. */int PlayerStart(TCPSOCKET * sock, u_long metaint, u_long tmo){    if (PlayerStop(tmo))        return -1;    /* Clear event queue and send start command. */    NutEventBroadcast(&player.psi_stsevt);    printf("[START]");    player.psi_status = PSI_START;    player.psi_sock = sock;    player.psi_metaint = metaint;    NutEventPost(&player.psi_cmdevt);    /* The next event will be the result of our start command. */    if (NutEventWait(&player.psi_stsevt, tmo) || player.psi_status != PSI_RUNNING) {        printf("[TOS]");        return -1;    }    return 0;}

⌨️ 快捷键说明

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