ao: fix crash after ao init failure (from recent 3a5fd15fa2)
[mplayer/greg.git] / stream / ai_oss.c
blob656b45b5ac244cb1385bb5d81f550dc73abf85af
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>
22 #include "config.h"
24 #include <string.h> /* strerror */
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <sys/ioctl.h>
29 #ifdef HAVE_SYS_SOUNDCARD_H
30 #include <sys/soundcard.h>
31 #else
32 #ifdef HAVE_SOUNDCARD_H
33 #include <soundcard.h>
34 #else
35 #include <linux/soundcard.h>
36 #endif
37 #endif
39 #include "audio_in.h"
40 #include "mp_msg.h"
42 int ai_oss_set_samplerate(audio_in_t *ai)
44 int tmp = ai->req_samplerate;
45 if (ioctl(ai->oss.audio_fd, SNDCTL_DSP_SPEED, &tmp) == -1) return -1;
46 ai->samplerate = tmp;
47 return 0;
50 int ai_oss_set_channels(audio_in_t *ai)
52 int err;
53 int ioctl_param;
55 if (ai->req_channels > 2)
57 ioctl_param = ai->req_channels;
58 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp channels: %d\n",
59 err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_CHANNELS, &ioctl_param));
60 if (err < 0) {
61 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to set channel count: %d\n",
62 ai->req_channels);
63 return -1;
65 ai->channels = ioctl_param;
67 else
69 ioctl_param = (ai->req_channels == 2);
70 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp stereo: %d (req: %d)\n",
71 err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_STEREO, &ioctl_param),
72 ioctl_param);
73 if (err < 0) {
74 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to set stereo: %d\n",
75 ai->req_channels == 2);
76 return -1;
78 ai->channels = ioctl_param ? 2 : 1;
80 return 0;
83 int ai_oss_init(audio_in_t *ai)
85 int err;
86 int ioctl_param;
88 ai->oss.audio_fd = open(ai->oss.device, O_RDONLY);
89 if (ai->oss.audio_fd < 0)
91 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to open '%s': %s\n",
92 ai->oss.device, strerror(errno));
93 return -1;
96 ioctl_param = 0 ;
97 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp getfmt: %d\n",
98 ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETFMTS, &ioctl_param));
100 mp_msg(MSGT_TV, MSGL_V, "Supported formats: %x\n", ioctl_param);
101 if (!(ioctl_param & AFMT_S16_LE))
102 mp_tmsg(MSGT_TV, MSGL_ERR, "unsupported format\n");
104 ioctl_param = AFMT_S16_LE;
105 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp setfmt: %d\n",
106 err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETFMT, &ioctl_param));
107 if (err < 0) {
108 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to set audio format.");
109 return -1;
112 if (ai_oss_set_channels(ai) < 0) return -1;
114 ioctl_param = ai->req_samplerate;
115 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp speed: %d\n",
116 err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SPEED, &ioctl_param));
117 if (err < 0) {
118 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to set samplerate: %d\n",
119 ai->req_samplerate);
120 return -1;
122 ai->samplerate = ioctl_param;
124 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp trigger: %d\n",
125 ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETTRIGGER, &ioctl_param));
126 mp_msg(MSGT_TV, MSGL_V, "trigger: %x\n", ioctl_param);
127 ioctl_param = PCM_ENABLE_INPUT;
128 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp trigger: %d\n",
129 err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETTRIGGER, &ioctl_param));
130 if (err < 0) {
131 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to set trigger: %d\n",
132 PCM_ENABLE_INPUT);
135 ai->blocksize = 0;
136 mp_msg(MSGT_TV, MSGL_V, "ioctl dsp getblocksize: %d\n",
137 err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETBLKSIZE, &ai->blocksize));
138 if (err < 0) {
139 mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to get block size!\n");
141 mp_msg(MSGT_TV, MSGL_V, "blocksize: %d\n", ai->blocksize);
143 // correct the blocksize to a reasonable value
144 if (ai->blocksize <= 0) {
145 ai->blocksize = 4096*ai->channels*2;
146 mp_tmsg(MSGT_TV, MSGL_ERR, "Audio block size is zero, setting to %d!\n", ai->blocksize);
147 } else if (ai->blocksize < 4096*ai->channels*2) {
148 ai->blocksize *= 4096*ai->channels*2/ai->blocksize;
149 mp_tmsg(MSGT_TV, MSGL_ERR, "Audio block size too low, setting to %d!\n", ai->blocksize);
152 ai->samplesize = 16;
153 ai->bytes_per_sample = 2;
155 return 0;