1 /* Sysdep esound sound dsp driver
2 
3    Copyright 2000 Hans de Goede
4 
5    This file and the acompanying files in this directory are free software;
6    you can redistribute them and/or modify them under the terms of the GNU
7    Library General Public License as published by the Free Software Foundation;
8    either version 2 of the License, or (at your option) any later version.
9 
10    These files are distributed in the hope that they will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public
16    License along with these files; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.
19 */
20 /* Changelog
21 Version 0.1, January 2000
22 -initial release, based on the driver submitted by riq <riq@ciudad.com.ar>,
23  amongst others (Hans de Goede)
24 */
25 #ifdef SYSDEP_DSP_ESOUND
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/ioctl.h>
30 #include <esd.h>
31 #include "sysdep/sysdep_dsp.h"
32 #include "sysdep/sysdep_dsp_priv.h"
33 #include "sysdep/plugin_manager.h"
34 
35 /* #define ESOUND_DEBUG */
36 
37 /* our per instance private data struct */
38 struct esound_dsp_priv_data {
39    int fd;
40 };
41 
42 /* public methods prototypes (static but exported through the sysdep_dsp or
43    plugin struct) */
44 static void *esound_dsp_create(const void *flags);
45 static void esound_dsp_destroy(struct sysdep_dsp_struct *dsp);
46 static int esound_dsp_write(struct sysdep_dsp_struct *dsp, unsigned char *data,
47    int count);
48 
49 /* public variables */
50 const struct plugin_struct sysdep_dsp_esound = {
51    "esound",
52    "sysdep_dsp",
53    "Esound DSP plugin",
54    NULL, /* no options */
55    NULL, /* no init */
56    NULL, /* no exit */
57    esound_dsp_create,
58    2     /* lower priority as direct device access */
59 };
60 
61 /* private variables */
62 static int esound_dsp_bytes_per_sample[4] = SYSDEP_DSP_BYTES_PER_SAMPLE;
63 
64 /* public methods (static but exported through the sysdep_dsp or plugin
65    struct) */
esound_dsp_create(const void * flags)66 static void *esound_dsp_create(const void *flags)
67 {
68 #ifdef ESOUND_DEBUG
69    int server_fd;
70    esd_server_info_t *info = NULL;
71 #endif
72    struct esound_dsp_priv_data *priv = NULL;
73    struct sysdep_dsp_struct *dsp = NULL;
74    const struct sysdep_dsp_create_params *params = flags;
75    esd_format_t esd_format;
76 
77    /* allocate the dsp struct */
78    if (!(dsp = calloc(1, sizeof(struct sysdep_dsp_struct))))
79    {
80       fprintf(stderr,
81          "error malloc failed for struct sysdep_dsp_struct\n");
82       return NULL;
83    }
84 
85    /* alloc private data */
86    if(!(priv = calloc(1, sizeof(struct esound_dsp_priv_data))))
87    {
88       fprintf(stderr,
89          "error malloc failed for struct esound_dsp_priv_data\n");
90       esound_dsp_destroy(dsp);
91       return NULL;
92    }
93 
94    /* fill in the functions and some data */
95    priv->fd = -1;
96    dsp->_priv = priv;
97    dsp->write = esound_dsp_write;
98    dsp->destroy = esound_dsp_destroy;
99    dsp->hw_info.type = params->type;
100    dsp->hw_info.samplerate = params->samplerate;
101 
102    /* open the sound device */
103    esd_format = ESD_STREAM | ESD_PLAY ;
104    esd_format |= (dsp->hw_info.type & SYSDEP_DSP_16BIT)?
105       ESD_BITS16 : ESD_BITS8;
106    esd_format |= (dsp->hw_info.type & SYSDEP_DSP_STEREO)?
107       ESD_STEREO : ESD_MONO;
108 
109 #ifdef ESOUND_DEBUG
110    if((server_fd = esd_open_sound(params->device)) < 0)
111    {
112       fprintf(stderr, "error: esound server open failed\n");
113       esound_dsp_destroy(dsp);
114       return NULL;
115    }
116 
117    if(!(info = esd_get_server_info(server_fd)))
118    {
119       fprintf(stderr, "error: esound get server info failed\n");
120       esd_close(server_fd);
121       esound_dsp_destroy(dsp);
122       return NULL;
123    }
124 
125    esd_print_server_info(info);
126    esd_free_server_info(info);
127    esd_close(server_fd);
128 #endif
129 
130    if((priv->fd = esd_play_stream(esd_format, dsp->hw_info.samplerate,
131       params->device, "mame esound")) < 0)
132    {
133       fprintf(stderr, "error: esound open stream failed\n");
134       esound_dsp_destroy(dsp);
135       return NULL;
136    }
137 
138    /* set non-blocking mode if selected */
139    if(params->flags & SYSDEP_DSP_O_NONBLOCK)
140    {
141       long flags = fcntl(priv->fd, F_GETFL);
142       if((flags < 0) || (fcntl(priv->fd, F_SETFL, flags|O_NONBLOCK) < 0))
143       {
144          perror("Esound-driver, error: fnctl");
145          esound_dsp_destroy(dsp);
146          return NULL;
147       }
148    }
149 
150    return dsp;
151 }
152 
esound_dsp_destroy(struct sysdep_dsp_struct * dsp)153 static void esound_dsp_destroy(struct sysdep_dsp_struct *dsp)
154 {
155    struct esound_dsp_priv_data *priv = dsp->_priv;
156 
157    if(priv)
158    {
159       if(priv->fd >= 0)
160          close(priv->fd);
161 
162       free(priv);
163    }
164    free(dsp);
165 }
166 
esound_dsp_write(struct sysdep_dsp_struct * dsp,unsigned char * data,int count)167 static int esound_dsp_write(struct sysdep_dsp_struct *dsp, unsigned char *data,
168    int count)
169 {
170    int result;
171    struct esound_dsp_priv_data *priv = dsp->_priv;
172 
173    result = write(priv->fd, data, count *
174       esound_dsp_bytes_per_sample[dsp->hw_info.type]);
175 
176    if (result < 0)
177    {
178       fprintf(stderr, "error: esound write to stream failed\n");
179       return -1;
180    }
181 
182    return result / esound_dsp_bytes_per_sample[dsp->hw_info.type];
183 }
184 
185 #endif /* ifdef SYSDEP_DSP_ESOUND */
186