2 * Copyright 2004-2005 Timo Hirvonen
4 * sun.c by alex <pukpuk@gmx.de>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <sys/audioio.h>
35 static sample_format_t sun_sf
;
36 static int sun_fd
= -1;
38 static char *sun_audio_device
= NULL
;
40 static int sun_reset(void);
41 static int sun_set_sf(sample_format_t
);
42 static int sun_device_exists(const char *);
43 static int sun_init(void);
44 static int sun_exit(void);
45 static int sun_open(sample_format_t
);
46 static int sun_close(void);
47 static int sun_write(const char *, int);
48 static int sun_pause(void);
49 static int sun_unpause(void);
50 static int sun_buffer_space(void);
51 static int op_sun_set_option(int, const char *);
52 static int op_sun_get_option(int, char **);
54 static int sun_reset(void)
56 if (ioctl(sun_fd
, AUDIO_FLUSH
, NULL
) == -1)
62 static int sun_set_sf(sample_format_t sf
)
64 struct audio_info ainf
;
66 AUDIO_INITINFO(&ainf
);
71 ainf
.play
.channels
= sf_get_channels(sun_sf
);
72 ainf
.play
.sample_rate
= sf_get_rate(sun_sf
);
74 ainf
.mode
= AUMODE_PLAY
;
76 switch (sf_get_bits(sun_sf
)) {
78 ainf
.play
.precision
= 16;
79 if (sf_get_signed(sun_sf
)) {
80 if (sf_get_bigendian(sun_sf
))
81 ainf
.play
.encoding
= AUDIO_ENCODING_SLINEAR_BE
;
83 ainf
.play
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
85 if (sf_get_bigendian(sun_sf
))
86 ainf
.play
.encoding
= AUDIO_ENCODING_ULINEAR_BE
;
88 ainf
.play
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
92 ainf
.play
.precision
= 8;
93 if (sf_get_signed(sun_sf
))
94 ainf
.play
.encoding
= AUDIO_ENCODING_SLINEAR
;
96 ainf
.play
.encoding
= AUDIO_ENCODING_ULINEAR
;
99 d_print("sun: bits is neither 8 nor 16\n");
103 if (ioctl(sun_fd
, AUDIO_SETINFO
, &ainf
) == -1) {
104 d_print("sun: AUDIO_SETINFO failed: %s", strerror(errno
));
108 if (ioctl(sun_fd
, AUDIO_GETINFO
, &ainf
) == -1)
110 /* XXX: check if sample rate is supported */
111 d_print("sun: sample_rate: %d chanels: %d\n", ainf
.play
.sample_rate
,
117 static int sun_device_exists(const char *dev
)
121 if (stat(dev
, &s
) == 0) {
122 d_print("device %s exists\n", dev
);
125 d_print("device %s does not exist\n", dev
);
130 static int sun_init(void)
132 const char *audio_dev
= "/dev/audio";
134 if (sun_audio_device
!= NULL
) {
135 if (sun_device_exists(sun_audio_device
))
137 free(sun_audio_device
);
138 sun_audio_device
= NULL
;
141 if (sun_device_exists(audio_dev
)) {
142 sun_audio_device
= xstrdup(audio_dev
);
149 static int sun_exit(void)
151 if (sun_audio_device
!= NULL
) {
152 free(sun_audio_device
);
153 sun_audio_device
= NULL
;
159 static int sun_open(sample_format_t sf
)
161 sun_fd
= open(sun_audio_device
, O_WRONLY
);
164 if (sun_set_sf(sf
) == -1) {
172 static int sun_close(void)
182 static int sun_write(const char *buf
, int cnt
)
191 if ((rc
= write(sun_fd
, buf
, cnt
)) == -1) {
204 static int sun_pause(void)
206 struct audio_info ainf
;
208 AUDIO_INITINFO(&ainf
);
211 if (ioctl(sun_fd
, AUDIO_SETINFO
, &ainf
) == -1)
217 static int sun_unpause(void)
219 struct audio_info ainf
;
221 AUDIO_INITINFO(&ainf
);
224 if (ioctl(sun_fd
, AUDIO_SETINFO
, &ainf
) == -1)
230 static int sun_buffer_space(void)
232 struct audio_info ainf
;
235 AUDIO_INITINFO(&ainf
);
237 if (ioctl(sun_fd
, AUDIO_GETINFO
, &ainf
) == -1)
239 sp
= ainf
.play
.buffer_size
;
244 static int op_sun_set_option(int key
, const char *val
)
248 free(sun_audio_device
);
249 sun_audio_device
= xstrdup(val
);
252 return -OP_ERROR_NOT_OPTION
;
258 static int op_sun_get_option(int key
, char **val
)
262 if (sun_audio_device
)
263 *val
= xstrdup(sun_audio_device
);
266 return -OP_ERROR_NOT_OPTION
;
272 const struct output_plugin_ops op_pcm_ops
= {
279 .unpause
= sun_unpause
,
280 .buffer_space
= sun_buffer_space
,
281 .set_option
= op_sun_set_option
,
282 .get_option
= op_sun_get_option
285 const char * const op_pcm_options
[] = {
290 const int op_priority
= 0;