playmp3.c

Go to the documentation of this file.
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 
00059 #include <dev/board.h>
00060 #include <dev/vs1001k.h>
00061 #include <dev/debug.h>
00062 #include <dev/urom.h>
00063 
00064 #include <sys/version.h>
00065 #include <sys/heap.h>
00066 #include <sys/event.h>
00067 #include <sys/timer.h>
00068 #include <sys/thread.h>
00069 #include <sys/bankmem.h>
00070 
00071 #include <stdlib.h>
00072 #include <string.h>
00073 #include <stdio.h>
00074 #include <io.h>
00075 #include <fcntl.h>
00076 #include <errno.h>
00077 
00078 #if defined(__AVR__)
00079 static int PlayMp3File(char *path);
00080 #endif
00081 
00105 int main(void)
00106 {
00107     /* Baudrate for debug output. */
00108     u_long baud = 115200;
00109 
00110     /*
00111      * Register our devices.
00112      */
00113     NutRegisterDevice(&devUrom, 0, 0);
00114     NutRegisterDevice(&DEV_DEBUG, 0, 0);
00115 
00116     /*
00117      * Assign stdout to the debug device.
00118      */
00119     freopen(DEV_DEBUG_NAME, "w", stdout);
00120     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00121 
00122     /*
00123      * Print a banner.
00124      */
00125     printf("\n\nPlay MP3 files on Nut/OS %s\n", NutVersionString());
00126 
00127 #if defined(__AVR__)
00128 
00129     /*
00130      * Initialize the MP3 buffer. The NutSegBuf routines provide a global
00131      * system buffer, which works with banked and non-banked systems.
00132      */
00133     if (NutSegBufInit(8192) == 0) {
00134         puts("NutSegBufInit: Fatal error");
00135     }
00136 
00137     /* 
00138      * Initialize the MP3 decoder hardware.
00139      */
00140     if (VsPlayerInit() || VsPlayerReset(0)) {
00141         puts("VsPlayer: Fatal error");
00142     }
00143 
00144     /*
00145      * Play the MP3 files in an endless loop. For each file set the volume 
00146      * of the left and right channel, call the local routine PlayMp3File() 
00147      * and sleep one second before playing the next sound file.
00148      */
00149     for (;;) {
00150         VsSetVolume(0, 254);
00151         PlayMp3File("UROM:sound1a.mp3");
00152         NutSleep(1000);
00153 
00154         VsSetVolume(0, 0);
00155         PlayMp3File("UROM:sound2a.mp3");
00156         NutSleep(1000);
00157 
00158         VsSetVolume(254, 0);
00159         PlayMp3File("UROM:sound3a.mp3");
00160         NutSleep(1000);
00161 
00162         VsSetVolume(0, 0);
00163         PlayMp3File("UROM:sound4a.mp3");
00164         NutSleep(1000);
00165     }
00166 #else /* !__AVR__ */
00167     for (;;);
00168 #endif /* !__AVR__ */
00169     return 0;
00170 }
00171 
00172 #if defined(__AVR__)
00173 
00174 /*
00175  * Play MP3 file from local file system.
00176  *
00177  * \param path Pathname of the MP3 file to play.
00178  *
00179  * \return 0 on success, -1 if opening the file failed.
00180  */
00181 static int PlayMp3File(char *path)
00182 {
00183     int fd;
00184     size_t rbytes;
00185     char  *mp3buf;
00186     int    got;
00187     u_char ief;
00188 
00189     /*
00190      * Open the MP3 file.
00191      */
00192     printf("Play %s: ", path);
00193     if ((fd = _open(path, _O_RDONLY | _O_BINARY)) == -1) {
00194         printf("Error %d\n", errno);
00195         return -1;
00196     }
00197     puts("OK");
00198 
00199     /* 
00200      * Reset decoder buffer.
00201      */
00202     printf("[B.RST]");
00203     ief = VsPlayerInterrupts(0);
00204     NutSegBufReset();
00205     VsPlayerInterrupts(ief);
00206 
00207     for (;;) {
00208         /*
00209          * Query number of byte available in MP3 buffer.
00210          */
00211         ief = VsPlayerInterrupts(0);
00212         mp3buf = NutSegBufWriteRequest(&rbytes);
00213         VsPlayerInterrupts(ief);
00214 
00215         /* 
00216          * Read data directly into the MP3 buffer. 
00217          */
00218         if (rbytes) {
00219             printf("[B.RD%d]", rbytes);
00220             if ((got = _read(fd, mp3buf, rbytes)) > 0) {
00221                 printf("[B.CMT%d]", got);
00222                 ief = VsPlayerInterrupts(0);
00223                 mp3buf = NutSegBufWriteCommit(got);
00224                 VsPlayerInterrupts(ief);
00225             } else {
00226                 printf("[EOF]");
00227                 break;
00228             }
00229         }
00230 
00231         /*
00232          * If the player is not running, kick it.
00233          */
00234         if (VsGetStatus() != VS_STATUS_RUNNING) {
00235             printf("[P.KICK]");
00236             VsPlayerKick();
00237         }
00238 
00239         /*
00240          * Allow background threads to take over.
00241          */
00242         NutThreadYield();
00243     }
00244 
00245     _close(fd);
00246 
00247     /* 
00248      * Flush decoder and wait until finished. 
00249      */
00250     printf("[P.FLUSH]");
00251     VsPlayerFlush();
00252     while (VsGetStatus() != VS_STATUS_EMPTY) {
00253         NutSleep(1);
00254     }
00255 
00256     /*
00257      * Reset the decoder. 
00258      */
00259     printf("[P.RST]");
00260     VsPlayerReset(0);
00261 
00262     printf("\nDone, %u bytes free\n", NutHeapAvailable());
00263     return 0;
00264 }
00265 
00266 #endif /* !__AVR__ */

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/