1 /*
2 	esd: audio output for ESounD (highly untested nowadays (?))
3 
4 	copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
5 	see COPYING and AUTHORS files in distribution or http://mpg123.org
6 	initially written by Eric B. Mitchell ("esd port" should be this file...)
7 */
8 
9 /* First the common header, including config.h
10    ...this is important for stuff like _FILE_OFFSET_BITS */
11 #include "out123_int.h"
12 
13 #include <esd.h>
14 #include <errno.h>
15 #include <assert.h>
16 
17 #ifdef SOLARIS
18 #include <stropts.h>
19 #include <sys/conf.h>
20 #endif
21 #ifdef NETBSD
22 #include <sys/ioctl.h>
23 #include <sys/audioio.h>
24 #endif
25 #include "debug.h"
26 
27 static unsigned esd_rate = 0, esd_format = 0, esd_channels = 0;
28 
29 
open_esound(out123_handle * ao)30 static int open_esound(out123_handle *ao)
31 {
32 	esd_format_t format = ESD_STREAM | ESD_PLAY;
33 
34 	if (!esd_rate)
35 	{
36 		int esd;
37 		esd_server_info_t *info;
38 		esd_format_t fmt;
39 
40 		if ((esd = esd_open_sound(NULL)) >= 0)
41 		{
42 			info = esd_get_server_info(esd);
43 			esd_rate = info->rate;
44 			fmt = info->format;
45 			esd_free_server_info(info);
46 			esd_close(esd);
47 		}
48 		else
49 		{
50 			esd_rate = esd_audio_rate;
51 			fmt = esd_audio_format;
52 		}
53 		esd_format = MPG123_ENC_UNSIGNED_8;
54 
55 		if ((fmt & ESD_MASK_BITS) == ESD_BITS16)
56 			esd_format |= MPG123_ENC_SIGNED_16;
57 		esd_channels = fmt & ESD_MASK_CHAN;
58 	}
59 
60 	if (ao->format == -1)
61 		ao->format = esd_format;
62 	else if (!(ao->format & esd_format))
63 	{
64 		if(!AOQUIET)
65 			error1("Unsupported audio format: %d\n", ao->format);
66 		errno = EINVAL;
67 		return -1;
68 	}
69 
70 
71 	if (ao->format & MPG123_ENC_SIGNED_16)
72 		format |= ESD_BITS16;
73 	else if (ao->format & MPG123_ENC_UNSIGNED_8)
74 		format |= ESD_BITS8;
75 	else assert(0);
76 
77 	if (ao->channels == -1) ao->channels = 2;
78 	else if (ao->channels <= 0 || ao->channels > esd_channels)
79 	{
80 		if(!AOQUIET)
81 			error1("Unsupported no of channels: %d\n", ao->channels);
82 		errno = EINVAL;
83 		return -1;
84 	}
85 	if (ao->channels == 1)
86 		format |= ESD_MONO;
87 	else if (ao->channels == 2)
88 		format |= ESD_STEREO;
89 	else assert(0);
90 
91 	if (ao->rate == -1) ao->rate = esd_rate;
92 	else if (ao->rate > esd_rate)
93 	return -1;
94 
95 	ao->fn = esd_play_stream_fallback(format, ao->rate, ao->device, "mpg123");
96 	return (ao->fn);
97 }
98 
get_formats_esound(out123_handle * ao)99 static int get_formats_esound (out123_handle *ao)
100 {
101 	if (0 < ao->channels && ao->channels <= esd_channels
102 	    && 0 < ao->rate && ao->rate <= esd_rate)
103 	{
104 		return esd_format;
105 	} else {
106 		return -1;
107 	}
108 }
109 
write_esound(out123_handle * ao,unsigned char * buf,int len)110 static int write_esound(out123_handle *ao,unsigned char *buf,int len)
111 {
112 	return write(ao->fn,buf,len);
113 }
114 
close_esound(out123_handle * ao)115 static int close_esound(out123_handle *ao)
116 {
117 	close (ao->fn);
118 	return 0;
119 }
120 
121 #ifdef SOLARIS
flush_esound(out123_handle * ao)122 static void flush_esound (out123_handle *ao)
123 {
124         ioctl (ao->fn, I_FLUSH, FLUSHRW);
125 }
126 #else
127 #ifdef NETBSD
flush_esound(out123_handle * ao)128 static void flush_esound (out123_handle *ao)
129 {
130         ioctl (ao->fn, AUDIO_FLUSH, 0);
131 }
132 #else
133 /* Dunno what to do on Linux and Cygwin, but the func must be at least defined! */
flush_esound(out123_handle * ao)134 static void flush_esound (out123_handle *ao)
135 {
136 }
137 #endif
138 #endif
139 
140 
init_esound(out123_handle * ao)141 static int init_esound(out123_handle* ao)
142 {
143 	if (ao==NULL) return -1;
144 
145 	/* Set callbacks */
146 	ao->open = open_esound;
147 	ao->flush = flush_esound;
148 	ao->write = write_esound;
149 	ao->get_formats = get_formats_esound;
150 	ao->close = close_esound;
151 
152 	/* Success */
153 	return 0;
154 }
155 
156 
157 
158 /*
159 	Module information data structure
160 */
161 mpg123_module_t mpg123_output_module_info = {
162 	/* api_version */	MPG123_MODULE_API_VERSION,
163 	/* name */			"esd",
164 	/* description */	"Output audio using ESounD (The Enlightened Sound Daemon).",
165 	/* revision */		"$Rev: 3915 $",
166 	/* handle */		NULL,
167 
168 	/* init_output */	init_esound,
169 };
170