ao: fix crash after ao init failure (from recent 3a5fd15fa2)
[mplayer/greg.git] / stream / audio_in.c
blobb7d388d89d85bdefa5830365f2a11dac5f649215
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
23 #include "config.h"
25 #include "audio_in.h"
26 #include "mp_msg.h"
27 #include <string.h>
28 #include <errno.h>
30 // sanitizes ai structure before calling other functions
31 int audio_in_init(audio_in_t *ai, int type)
33 ai->type = type;
34 ai->setup = 0;
36 ai->channels = -1;
37 ai->samplerate = -1;
38 ai->blocksize = -1;
39 ai->bytes_per_sample = -1;
40 ai->samplesize = -1;
42 switch (ai->type) {
43 #ifdef CONFIG_ALSA
44 case AUDIO_IN_ALSA:
45 ai->alsa.handle = NULL;
46 ai->alsa.log = NULL;
47 ai->alsa.device = strdup("default");
48 return 0;
49 #endif
50 #ifdef CONFIG_OSS_AUDIO
51 case AUDIO_IN_OSS:
52 ai->oss.audio_fd = -1;
53 ai->oss.device = strdup("/dev/dsp");
54 return 0;
55 #endif
56 default:
57 return -1;
61 int audio_in_setup(audio_in_t *ai)
64 switch (ai->type) {
65 #ifdef CONFIG_ALSA
66 case AUDIO_IN_ALSA:
67 if (ai_alsa_init(ai) < 0) return -1;
68 ai->setup = 1;
69 return 0;
70 #endif
71 #ifdef CONFIG_OSS_AUDIO
72 case AUDIO_IN_OSS:
73 if (ai_oss_init(ai) < 0) return -1;
74 ai->setup = 1;
75 return 0;
76 #endif
77 default:
78 return -1;
82 int audio_in_set_samplerate(audio_in_t *ai, int rate)
84 switch (ai->type) {
85 #ifdef CONFIG_ALSA
86 case AUDIO_IN_ALSA:
87 ai->req_samplerate = rate;
88 if (!ai->setup) return 0;
89 if (ai_alsa_setup(ai) < 0) return -1;
90 return ai->samplerate;
91 #endif
92 #ifdef CONFIG_OSS_AUDIO
93 case AUDIO_IN_OSS:
94 ai->req_samplerate = rate;
95 if (!ai->setup) return 0;
96 if (ai_oss_set_samplerate(ai) < 0) return -1;
97 return ai->samplerate;
98 #endif
99 default:
100 return -1;
104 int audio_in_set_channels(audio_in_t *ai, int channels)
106 switch (ai->type) {
107 #ifdef CONFIG_ALSA
108 case AUDIO_IN_ALSA:
109 ai->req_channels = channels;
110 if (!ai->setup) return 0;
111 if (ai_alsa_setup(ai) < 0) return -1;
112 return ai->channels;
113 #endif
114 #ifdef CONFIG_OSS_AUDIO
115 case AUDIO_IN_OSS:
116 ai->req_channels = channels;
117 if (!ai->setup) return 0;
118 if (ai_oss_set_channels(ai) < 0) return -1;
119 return ai->channels;
120 #endif
121 default:
122 return -1;
126 int audio_in_set_device(audio_in_t *ai, char *device)
128 #ifdef CONFIG_ALSA
129 int i;
130 #endif
131 if (ai->setup) return -1;
132 switch (ai->type) {
133 #ifdef CONFIG_ALSA
134 case AUDIO_IN_ALSA:
135 free(ai->alsa.device);
136 ai->alsa.device = strdup(device);
137 /* mplayer cannot handle colons in arguments */
138 for (i = 0; i < (int)strlen(ai->alsa.device); i++) {
139 if (ai->alsa.device[i] == '.') ai->alsa.device[i] = ':';
141 return 0;
142 #endif
143 #ifdef CONFIG_OSS_AUDIO
144 case AUDIO_IN_OSS:
145 free(ai->oss.device);
146 ai->oss.device = strdup(device);
147 return 0;
148 #endif
149 default:
150 return -1;
154 int audio_in_uninit(audio_in_t *ai)
156 if (ai->setup) {
157 switch (ai->type) {
158 #ifdef CONFIG_ALSA
159 case AUDIO_IN_ALSA:
160 if (ai->alsa.log)
161 snd_output_close(ai->alsa.log);
162 if (ai->alsa.handle) {
163 snd_pcm_close(ai->alsa.handle);
165 ai->setup = 0;
166 return 0;
167 #endif
168 #ifdef CONFIG_OSS_AUDIO
169 case AUDIO_IN_OSS:
170 close(ai->oss.audio_fd);
171 ai->setup = 0;
172 return 0;
173 #endif
176 return -1;
179 int audio_in_start_capture(audio_in_t *ai)
181 switch (ai->type) {
182 #ifdef CONFIG_ALSA
183 case AUDIO_IN_ALSA:
184 return snd_pcm_start(ai->alsa.handle);
185 #endif
186 #ifdef CONFIG_OSS_AUDIO
187 case AUDIO_IN_OSS:
188 return 0;
189 #endif
190 default:
191 return -1;
195 int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer)
197 int ret;
199 switch (ai->type) {
200 #ifdef CONFIG_ALSA
201 case AUDIO_IN_ALSA:
202 ret = snd_pcm_readi(ai->alsa.handle, buffer, ai->alsa.chunk_size);
203 if (ret != ai->alsa.chunk_size) {
204 if (ret < 0) {
205 mp_tmsg(MSGT_TV, MSGL_ERR, "\nError reading audio: %s\n", snd_strerror(ret));
206 if (ret == -EPIPE) {
207 if (ai_alsa_xrun(ai) == 0) {
208 mp_tmsg(MSGT_TV, MSGL_ERR, "Recovered from cross-run, some frames may be left out!\n");
209 } else {
210 mp_tmsg(MSGT_TV, MSGL_ERR, "Fatal error, cannot recover!\n");
213 } else {
214 mp_tmsg(MSGT_TV, MSGL_ERR, "\nNot enough audio samples!\n");
216 return -1;
218 return ret;
219 #endif
220 #ifdef CONFIG_OSS_AUDIO
221 case AUDIO_IN_OSS:
222 ret = read(ai->oss.audio_fd, buffer, ai->blocksize);
223 if (ret != ai->blocksize) {
224 if (ret < 0) {
225 mp_tmsg(MSGT_TV, MSGL_ERR, "\nError reading audio: %s\n", strerror(errno));
226 } else {
227 mp_tmsg(MSGT_TV, MSGL_ERR, "\nNot enough audio samples!\n");
229 return -1;
231 return ret;
232 #endif
233 default:
234 return -1;