1 /*
2 * madplay - MPEG audio decoder and player
3 * Copyright (C) 2000-2004 Robert Leslie
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * $Id: audio_cdda.c,v 1.9 2004/01/23 09:41:31 rob Exp $
20 */
21
22 # ifdef HAVE_CONFIG_H
23 # include "config.h"
24 # endif
25
26 # include "global.h"
27
28 # include <stdio.h>
29 # include <string.h>
30
31 # ifdef HAVE_ASSERT_H
32 # include <assert.h>
33 # endif
34
35 # include <mad.h>
36
37 # include "audio.h"
38
39 static FILE *outfile;
40 unsigned int samplecount;
41
42 # define CD_FRAMESZ (44100 / 75)
43
44 static
init(struct audio_init * init)45 int init(struct audio_init *init)
46 {
47 if (init->path && strcmp(init->path, "-") != 0) {
48 outfile = fopen(init->path, "wb");
49 if (outfile == 0) {
50 audio_error = ":";
51 return -1;
52 }
53 }
54 else
55 outfile = stdout;
56
57 samplecount = 0;
58
59 return 0;
60 }
61
62 static
config(struct audio_config * config)63 int config(struct audio_config *config)
64 {
65 /* force 16-bit 44100 Hz stereo */
66
67 config->channels = 2;
68 config->speed = 44100;
69 config->precision = 16;
70
71 return 0;
72 }
73
74 static
output(unsigned char const * data,unsigned int nsamples)75 int output(unsigned char const *data, unsigned int nsamples)
76 {
77 unsigned int count;
78 int result = 0;
79
80 count = fwrite(data, 2 * 2, nsamples, outfile);
81
82 if (count != nsamples) {
83 audio_error = ":fwrite";
84 result = -1;
85 }
86
87 samplecount = (samplecount + count) % CD_FRAMESZ;
88
89 return result;
90 }
91
92 static
play(struct audio_play * play)93 int play(struct audio_play *play)
94 {
95 unsigned char data[MAX_NSAMPLES * 2 * 2];
96
97 assert(play->samples[1]);
98
99 audio_pcm_s16be(data, play->nsamples, play->samples[0], play->samples[1],
100 play->mode, play->stats);
101
102 return output(data, play->nsamples);
103 }
104
105 static
stop(struct audio_stop * stop)106 int stop(struct audio_stop *stop)
107 {
108 return 0;
109 }
110
111 static
finish(struct audio_finish * finish)112 int finish(struct audio_finish *finish)
113 {
114 int result = 0;
115
116 /* pad audio to CD frame boundary */
117
118 if (samplecount) {
119 unsigned char padding[CD_FRAMESZ * 2 * 2];
120 unsigned int padsz;
121
122 assert(samplecount < CD_FRAMESZ);
123 padsz = CD_FRAMESZ - samplecount;
124
125 memset(padding, 0, padsz * 2 * 2);
126
127 result = output(padding, padsz);
128 }
129
130 if (outfile != stdout &&
131 fclose(outfile) == EOF &&
132 result == 0) {
133 audio_error = ":fclose";
134 result = -1;
135 }
136
137 return result;
138 }
139
audio_cdda(union audio_control * control)140 int audio_cdda(union audio_control *control)
141 {
142 audio_error = 0;
143
144 switch (control->command) {
145 case AUDIO_COMMAND_INIT:
146 return init(&control->init);
147
148 case AUDIO_COMMAND_CONFIG:
149 return config(&control->config);
150
151 case AUDIO_COMMAND_PLAY:
152 return play(&control->play);
153
154 case AUDIO_COMMAND_STOP:
155 return stop(&control->stop);
156
157 case AUDIO_COMMAND_FINISH:
158 return finish(&control->finish);
159 }
160
161 return 0;
162 }
163