1 /*
2  * This file is part of MPlayer.
3  *
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.
8  *
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.
13  *
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.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 
23 #include "config.h"
24 
25 #include "audio_in.h"
26 #include "mp_msg.h"
27 #include "help_mp.h"
28 #include <string.h>
29 #include <errno.h>
30 
31 // sanitizes ai structure before calling other functions
audio_in_init(audio_in_t * ai,int type)32 int audio_in_init(audio_in_t *ai, int type)
33 {
34     ai->type = type;
35     ai->setup = 0;
36 
37     ai->channels = -1;
38     ai->samplerate = -1;
39     ai->blocksize = -1;
40     ai->bytes_per_sample = -1;
41     ai->samplesize = -1;
42 
43     switch (ai->type) {
44 #ifdef CONFIG_ALSA
45     case AUDIO_IN_ALSA:
46 	ai->alsa.handle = NULL;
47 	ai->alsa.log = NULL;
48 	ai->alsa.device = strdup("default");
49 	return 0;
50 #endif
51 #ifdef CONFIG_OSS_AUDIO
52     case AUDIO_IN_OSS:
53 	ai->oss.audio_fd = -1;
54 	ai->oss.device = strdup("/dev/dsp");
55 	return 0;
56 #endif
57     default:
58 	return -1;
59     }
60 }
61 
audio_in_setup(audio_in_t * ai)62 int audio_in_setup(audio_in_t *ai)
63 {
64 
65     switch (ai->type) {
66 #ifdef CONFIG_ALSA
67     case AUDIO_IN_ALSA:
68 	if (ai_alsa_init(ai) < 0) return -1;
69 	ai->setup = 1;
70 	return 0;
71 #endif
72 #ifdef CONFIG_OSS_AUDIO
73     case AUDIO_IN_OSS:
74 	if (ai_oss_init(ai) < 0) return -1;
75 	ai->setup = 1;
76 	return 0;
77 #endif
78     default:
79 	return -1;
80     }
81 }
82 
audio_in_set_samplerate(audio_in_t * ai,int rate)83 int audio_in_set_samplerate(audio_in_t *ai, int rate)
84 {
85     switch (ai->type) {
86 #ifdef CONFIG_ALSA
87     case AUDIO_IN_ALSA:
88 	ai->req_samplerate = rate;
89 	if (!ai->setup) return 0;
90 	if (ai_alsa_setup(ai) < 0) return -1;
91 	return ai->samplerate;
92 #endif
93 #ifdef CONFIG_OSS_AUDIO
94     case AUDIO_IN_OSS:
95 	ai->req_samplerate = rate;
96 	if (!ai->setup) return 0;
97 	if (ai_oss_set_samplerate(ai) < 0) return -1;
98 	return ai->samplerate;
99 #endif
100     default:
101 	return -1;
102     }
103 }
104 
audio_in_set_channels(audio_in_t * ai,int channels)105 int audio_in_set_channels(audio_in_t *ai, int channels)
106 {
107     switch (ai->type) {
108 #ifdef CONFIG_ALSA
109     case AUDIO_IN_ALSA:
110 	ai->req_channels = channels;
111 	if (!ai->setup) return 0;
112 	if (ai_alsa_setup(ai) < 0) return -1;
113 	return ai->channels;
114 #endif
115 #ifdef CONFIG_OSS_AUDIO
116     case AUDIO_IN_OSS:
117 	ai->req_channels = channels;
118 	if (!ai->setup) return 0;
119 	if (ai_oss_set_channels(ai) < 0) return -1;
120 	return ai->channels;
121 #endif
122     default:
123 	return -1;
124     }
125 }
126 
audio_in_set_device(audio_in_t * ai,char * device)127 int audio_in_set_device(audio_in_t *ai, char *device)
128 {
129 #ifdef CONFIG_ALSA
130     int i;
131 #endif
132     if (ai->setup) return -1;
133     switch (ai->type) {
134 #ifdef CONFIG_ALSA
135     case AUDIO_IN_ALSA:
136 	free(ai->alsa.device);
137 	ai->alsa.device = strdup(device);
138 	/* mplayer cannot handle colons in arguments */
139 	for (i = 0; i < (int)strlen(ai->alsa.device); i++) {
140 	    if (ai->alsa.device[i] == '.') ai->alsa.device[i] = ':';
141 	}
142 	return 0;
143 #endif
144 #ifdef CONFIG_OSS_AUDIO
145     case AUDIO_IN_OSS:
146 	free(ai->oss.device);
147 	ai->oss.device = strdup(device);
148 	return 0;
149 #endif
150     default:
151 	return -1;
152     }
153 }
154 
audio_in_uninit(audio_in_t * ai)155 int audio_in_uninit(audio_in_t *ai)
156 {
157     if (ai->setup) {
158 	switch (ai->type) {
159 #ifdef CONFIG_ALSA
160 	case AUDIO_IN_ALSA:
161 	    if (ai->alsa.log)
162 		snd_output_close(ai->alsa.log);
163 	    if (ai->alsa.handle) {
164 		snd_pcm_close(ai->alsa.handle);
165 	    }
166 	    ai->setup = 0;
167 	    return 0;
168 #endif
169 #ifdef CONFIG_OSS_AUDIO
170 	case AUDIO_IN_OSS:
171 	    close(ai->oss.audio_fd);
172 	    ai->setup = 0;
173 	    return 0;
174 #endif
175 	}
176     }
177     return -1;
178 }
179 
audio_in_start_capture(audio_in_t * ai)180 int audio_in_start_capture(audio_in_t *ai)
181 {
182     switch (ai->type) {
183 #ifdef CONFIG_ALSA
184     case AUDIO_IN_ALSA:
185 	return snd_pcm_start(ai->alsa.handle);
186 #endif
187 #ifdef CONFIG_OSS_AUDIO
188     case AUDIO_IN_OSS:
189 	return 0;
190 #endif
191     default:
192 	return -1;
193     }
194 }
195 
audio_in_read_chunk(audio_in_t * ai,unsigned char * buffer)196 int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer)
197 {
198     int ret;
199 
200     switch (ai->type) {
201 #ifdef CONFIG_ALSA
202     case AUDIO_IN_ALSA:
203 	ret = snd_pcm_readi(ai->alsa.handle, buffer, ai->alsa.chunk_size);
204 	if (ret != ai->alsa.chunk_size) {
205 	    if (ret < 0) {
206 		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio, snd_strerror(ret));
207 		if (ret == -EPIPE) {
208 		    if (ai_alsa_xrun(ai) == 0) {
209 			mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_XRUNSomeFramesMayBeLeftOut);
210 		    } else {
211 			mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrFatalCannotRecover);
212 		    }
213 		}
214 	    } else {
215 		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples);
216 	    }
217 	    return -1;
218 	}
219 	return ret;
220 #endif
221 #ifdef CONFIG_OSS_AUDIO
222     case AUDIO_IN_OSS:
223 	ret = read(ai->oss.audio_fd, buffer, ai->blocksize);
224 	if (ret != ai->blocksize) {
225 	    if (ret < 0) {
226 		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio, strerror(errno));
227 	    } else {
228 		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples);
229 	    }
230 	    return -1;
231 	}
232 	return ret;
233 #endif
234     default:
235 	return -1;
236     }
237 }
238