moved matrix init away from MPV_common_init()
[libav.git] / libav / audio.c
1 /*
2 * Linux audio play and grab interface
3 * Copyright (c) 2000, 2001 Gerard Lantau.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <linux/soundcard.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <sys/ioctl.h>
26 #include <sys/mman.h>
27 #include <errno.h>
28 #include <sys/time.h>
29
30 #include "avformat.h"
31
32 const char *audio_device = "/dev/dsp";
33
34 typedef struct {
35 int fd;
36 int rate;
37 int channels;
38 } AudioData;
39
40 #define AUDIO_BLOCK_SIZE 4096
41
42 /* audio read support */
43
44 static int audio_read(URLContext *h, UINT8 *buf, int size)
45 {
46 AudioData *s = h->priv_data;
47 int ret;
48
49 ret = read(s->fd, buf, size);
50 if (ret < 0)
51 return -errno;
52 else
53 return ret;
54 }
55
56 static int audio_write(URLContext *h, UINT8 *buf, int size)
57 {
58 AudioData *s = h->priv_data;
59 int ret;
60
61 ret = write(s->fd, buf, size);
62 if (ret < 0)
63 return -errno;
64 else
65 return ret;
66 }
67
68 static int audio_get_format(URLContext *h, URLFormat *f)
69 {
70 AudioData *s = h->priv_data;
71
72 strcpy(f->format_name, "pcm");
73 f->sample_rate = s->rate;
74 f->channels = s->channels;
75 return 0;
76 }
77
78 /* URI syntax: 'audio:[rate[,channels]]'
79 default: rate=44100, channels=2
80 */
81 static int audio_open(URLContext *h, const char *uri, int flags)
82 {
83 AudioData *s;
84 const char *p;
85 int freq, channels, audio_fd;
86 int tmp, err;
87
88 h->is_streamed = 1;
89 h->packet_size = AUDIO_BLOCK_SIZE;
90
91 s = malloc(sizeof(AudioData));
92 if (!s)
93 return -ENOMEM;
94 h->priv_data = s;
95
96 /* extract parameters */
97 p = uri;
98 strstart(p, "audio:", &p);
99 freq = strtol(p, (char **)&p, 0);
100 if (freq <= 0)
101 freq = 44100;
102 if (*p == ',')
103 p++;
104 channels = strtol(p, (char **)&p, 0);
105 if (channels <= 0)
106 channels = 2;
107 s->rate = freq;
108 s->channels = channels;
109
110 /* open linux audio device */
111 if (flags & URL_WRONLY)
112 audio_fd = open(audio_device,O_WRONLY);
113 else
114 audio_fd = open(audio_device,O_RDONLY);
115 if (audio_fd < 0) {
116 perror(audio_device);
117 return -EIO;
118 }
119
120 /* non blocking mode */
121 fcntl(audio_fd, F_SETFL, O_NONBLOCK);
122
123 #if 0
124 tmp=(NB_FRAGMENTS << 16) | FRAGMENT_BITS;
125 err=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
126 if (err < 0) {
127 perror("SNDCTL_DSP_SETFRAGMENT");
128 }
129 #endif
130
131 tmp=AFMT_S16_LE;
132 err=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&tmp);
133 if (err < 0) {
134 perror("SNDCTL_DSP_SETFMT");
135 goto fail;
136 }
137
138 tmp= (channels == 2);
139 err=ioctl(audio_fd,SNDCTL_DSP_STEREO,&tmp);
140 if (err < 0) {
141 perror("SNDCTL_DSP_STEREO");
142 goto fail;
143 }
144
145 tmp = freq;
146 err=ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
147 if (err < 0) {
148 perror("SNDCTL_DSP_SPEED");
149 goto fail;
150 }
151
152 s->rate = tmp;
153 s->fd = audio_fd;
154
155 return 0;
156 fail:
157 close(audio_fd);
158 free(s);
159 return -EIO;
160 }
161
162 static int audio_close(URLContext *h)
163 {
164 AudioData *s = h->priv_data;
165
166 close(s->fd);
167 free(s);
168 return 0;
169 }
170
171 URLProtocol audio_protocol = {
172 "audio",
173 audio_open,
174 audio_read,
175 audio_write,
176 NULL, /* seek */
177 audio_close,
178 audio_get_format,
179 };