summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2002-05-09 23:54:47 +0000
committerDave Chapman <dave@dchapman.com>2002-05-09 23:54:47 +0000
commit4dbbca63d31ad40e8ec778b2ddfc63f33dc9f500 (patch)
treed0301232c53631cf90357ce3cf1e783a7499c43c
parent564bb3edb0d52ce13367c8f53bc54b4fe448b8cf (diff)
downloadrockbox-4dbbca63d31ad40e8ec778b2ddfc63f33dc9f500.tar.gz
rockbox-4dbbca63d31ad40e8ec778b2ddfc63f33dc9f500.zip
first attempt at mp3 playback in x11 simulator using libmad
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@535 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--uisimulator/play.c10
-rw-r--r--uisimulator/x11/Makefile8
-rw-r--r--uisimulator/x11/mpegplay.c232
-rw-r--r--uisimulator/x11/mpegplay.h23
4 files changed, 272 insertions, 1 deletions
diff --git a/uisimulator/play.c b/uisimulator/play.c
index 7031fd208e..f9877134eb 100644
--- a/uisimulator/play.c
+++ b/uisimulator/play.c
@@ -29,6 +29,10 @@
29 29
30#include "id3.h" 30#include "id3.h"
31 31
32#ifdef MPEG_PLAY
33#include "x11/mpegplay.h"
34#endif
35
32#define LINE_Y 8 /* initial line */ 36#define LINE_Y 8 /* initial line */
33#define LINE_HEIGTH 8 /* line height in pixels */ 37#define LINE_HEIGTH 8 /* line height in pixels */
34 38
@@ -68,6 +72,12 @@ void playtune(char *dir, char *file)
68 lcd_update(); 72 lcd_update();
69#endif 73#endif
70 74
75#ifdef MPEG_PLAY
76 sprintf(buffer, "%s/%s", dir, file);
77 mpeg_play(buffer);
78 return;
79#endif
80
71 while(1) { 81 while(1) {
72 int key = button_get(); 82 int key = button_get();
73 83
diff --git a/uisimulator/x11/Makefile b/uisimulator/x11/Makefile
index 9753394456..7cc8b088c3 100644
--- a/uisimulator/x11/Makefile
+++ b/uisimulator/x11/Makefile
@@ -57,6 +57,12 @@ APPS = tetris.c screensaver.c tree.c app.c play.c menu.c icons.c
57SRCS = screenhack.c uibasic.c resources.c visual.c lcd-x11.c \ 57SRCS = screenhack.c uibasic.c resources.c visual.c lcd-x11.c \
58 button-x11.c io.c sleep.c $(APPS) $(FIRMSRCS) 58 button-x11.c io.c sleep.c $(APPS) $(FIRMSRCS)
59 59
60ifdef MPEG_PLAY
61 SRCS += mpegplay.c
62 DEFINES += -DMPEG_PLAY
63 LIBS = -lmad
64endif
65
60OBJS := $(SRCS:c=o) 66OBJS := $(SRCS:c=o)
61 67
62all: $(TARGET) 68all: $(TARGET)
@@ -108,7 +114,7 @@ sprintf.o: $(COMMON)/sprintf.c
108 $(CC) $(CFLAGS) -c $< 114 $(CC) $(CFLAGS) -c $<
109 115
110$(TARGET): $(OBJS) 116$(TARGET): $(OBJS)
111 $(CC) -g -o $(TARGET) $(LIBDIRS) $(LDFLAGS) $(OBJS) 117 $(CC) -g -o $(TARGET) $(LIBDIRS) $(LDFLAGS) $(OBJS) $(LIBS)
112 118
113DEPS:=.deps 119DEPS:=.deps
114 120
diff --git a/uisimulator/x11/mpegplay.c b/uisimulator/x11/mpegplay.c
new file mode 100644
index 0000000000..2d31c073dd
--- /dev/null
+++ b/uisimulator/x11/mpegplay.c
@@ -0,0 +1,232 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2002 Dave Chapman
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#ifdef MPEG_PLAY
20
21#include <string.h>
22#include <stdlib.h>
23#include <file.h>
24#include <types.h>
25#include <lcd.h>
26#include <button.h>
27#include "id3.h"
28
29#include <stdio.h>
30#include <mad.h>
31#include <linux/soundcard.h>
32
33/* We want to use the "real" open in some cases */
34#undef open
35
36struct mad_stream Stream;
37struct mad_frame Frame;
38struct mad_synth Synth;
39mad_timer_t Timer;
40int sound;
41
42void init_oss(int sound, int sound_freq, int channels) {
43 int format=AFMT_U16_LE;
44 int setting=0x000C000D; // 12 fragments size 8kb ? WHAT IS THIS?
45
46 if (ioctl(sound,SNDCTL_DSP_SETFRAGMENT,&setting)==-1) {
47 perror("SNDCTL_DSP_SETFRAGMENT");
48 }
49
50 if (ioctl(sound,SNDCTL_DSP_STEREO,&channels)==-1) {
51 perror("SNDCTL_DSP_STEREO");
52 }
53 if (channels==0) { fprintf(stderr,"Warning, only mono supported\n"); }
54
55 if (ioctl(sound,SNDCTL_DSP_SETFMT,&format)==-1) {
56 perror("SNDCTL_DSP_SETFMT");
57 }
58
59 fprintf(stderr,"SETTING /dev/dsp to %dHz\n",sound_freq);
60 if (ioctl(sound,SNDCTL_DSP_SPEED,&sound_freq)==-1) {
61 perror("SNDCTL_DSP_SPEED");
62 }
63}
64
65unsigned short MadFixedToUshort(mad_fixed_t Fixed)
66{
67 Fixed=Fixed>>(MAD_F_FRACBITS-15);
68 return((unsigned short)Fixed);
69}
70
71#define INPUT_BUFFER_SIZE (5*8192)
72#define OUTPUT_BUFFER_SIZE 8192 /* Must be an integer multiple of 4. */
73int mpeg_play(char* fname)
74{
75 unsigned char InputBuffer[INPUT_BUFFER_SIZE],
76 OutputBuffer[OUTPUT_BUFFER_SIZE],
77 *OutputPtr=OutputBuffer;
78 const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
79 int Status=0,
80 i;
81 unsigned long FrameCount=0;
82 int sound,fd;
83 mp3entry mp3;
84
85 mp3info(&mp3, fname);
86
87 #undef open
88 sound=open("/dev/dsp", O_WRONLY);
89
90 if (sound < 0) {
91 fprintf(stderr,"Can not open /dev/dsp - Aborting - sound=%d\n",sound);
92 exit(-1);
93 }
94
95 init_oss(sound,mp3.frequency,2);
96
97 fd=x11_open(fname,O_RDONLY);
98 if (fd < 0) {
99 fprintf(stderr,"could not open %s\n",fname);
100 return 0;
101 }
102
103 /* First the structures used by libmad must be initialized. */
104 mad_stream_init(&Stream);
105 mad_frame_init(&Frame);
106 mad_synth_init(&Synth);
107 mad_timer_reset(&Timer);
108
109 do
110 {
111 if (button_get()) break; /* Return if a key is pressed */
112
113 if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN)
114 {
115 size_t ReadSize,Remaining;
116 unsigned char *ReadStart;
117
118 if(Stream.next_frame!=NULL)
119 {
120 Remaining=Stream.bufend-Stream.next_frame;
121 memmove(InputBuffer,Stream.next_frame,Remaining);
122 ReadStart=InputBuffer+Remaining;
123 ReadSize=INPUT_BUFFER_SIZE-Remaining;
124 }
125 else
126 ReadSize=INPUT_BUFFER_SIZE,
127 ReadStart=InputBuffer,
128 Remaining=0;
129
130 ReadSize=read(fd,ReadStart,ReadSize);
131 if(ReadSize<=0)
132 {
133 fprintf(stderr,"end of input stream\n");
134 break;
135 }
136
137 mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
138 Stream.error=0;
139 }
140
141 if(mad_frame_decode(&Frame,&Stream)) {
142 if(MAD_RECOVERABLE(Stream.error))
143 {
144 fprintf(stderr,"recoverable frame level error\n");
145 fflush(stderr);
146 continue;
147 }
148 else
149 if(Stream.error==MAD_ERROR_BUFLEN) {
150 continue;
151 } else {
152 fprintf(stderr,"unrecoverable frame level error\n");
153 Status=1;
154 break;
155 }
156 }
157
158 FrameCount++;
159 mad_timer_add(&Timer,Frame.header.duration);
160
161 mad_synth_frame(&Synth,&Frame);
162
163 for(i=0;i<Synth.pcm.length;i++)
164 {
165 unsigned short Sample;
166
167 /* Left channel */
168 Sample=MadFixedToUshort(Synth.pcm.samples[0][i]);
169 *(OutputPtr++)=Sample&0xff;
170 *(OutputPtr++)=Sample>>8;
171
172 /* Right channel. If the decoded stream is monophonic then
173 * the right output channel is the same as the left one.
174 */
175 if(MAD_NCHANNELS(&Frame.header)==2)
176 Sample=MadFixedToUshort(Synth.pcm.samples[1][i]);
177 *(OutputPtr++)=Sample&0xff;
178 *(OutputPtr++)=Sample>>8;
179
180 /* Flush the buffer if it is full. */
181 if(OutputPtr==OutputBufferEnd)
182 {
183 if(write(sound,OutputBuffer,OUTPUT_BUFFER_SIZE)!=OUTPUT_BUFFER_SIZE)
184 {
185 fprintf(stderr,"PCM write error.\n");
186 Status=2;
187 break;
188 }
189 OutputPtr=OutputBuffer;
190 }
191 }
192 }while(1);
193
194 fprintf(stderr,"END OF MAD LOOP\n");
195 /* Mad is no longer used, the structures that were initialized must
196 * now be cleared.
197 */
198 mad_synth_finish(&Synth);
199 mad_frame_finish(&Frame);
200 mad_stream_finish(&Stream);
201
202 /* If the output buffer is not empty and no error occured during
203 * the last write, then flush it.
204 */
205 if(OutputPtr!=OutputBuffer && Status!=2)
206 {
207 size_t BufferSize=OutputPtr-OutputBuffer;
208
209 if(write(sound,OutputBuffer,1,BufferSize)!=BufferSize)
210 {
211 fprintf(stderr,"PCM write error\n");
212 Status=2;
213 }
214 }
215
216 /* Accounting report if no error occured. */
217 if(!Status)
218 {
219 char Buffer[80];
220
221 mad_timer_string(Timer,Buffer,"%lu:%02lu.%03u",
222 MAD_UNITS_MINUTES,MAD_UNITS_MILLISECONDS,0);
223 fprintf(stderr,"%lu frames decoded (%s).\n",FrameCount,Buffer);
224 }
225
226 close(sound);
227 /* That's the end of the world (in the H. G. Wells way). */
228 return(Status);
229}
230
231
232#endif
diff --git a/uisimulator/x11/mpegplay.h b/uisimulator/x11/mpegplay.h
new file mode 100644
index 0000000000..cde9fe183f
--- /dev/null
+++ b/uisimulator/x11/mpegplay.h
@@ -0,0 +1,23 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2002 Dave Chapman
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#ifdef MPEG_PLAY
20
21int mpeg_play(char* fname);
22
23#endif