1 /* Sysdep Open Sound System sound mixer driver
2
3 Copyright 2000 Hans de Goede, Mathis Rosenhauer
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, February 2000
22 -initial release based on oss.c by Hans de Goede (Mathis Rosenhauer)
23 */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/stropts.h>
32 #include <sys/audioio.h>
33 #include "sysdep/sysdep_mixer.h"
34 #include "sysdep/sysdep_mixer_priv.h"
35 #include "sysdep/plugin_manager.h"
36
37 /* our per instance private data struct */
38 struct sol_mixer_priv_data {
39 int fd;
40 };
41
42 /* public methods prototypes (static but exported through the sysdep_mixer or
43 plugin struct) */
44 static void *sol_mixer_create(const void *flags);
45 static void sol_mixer_destroy(struct sysdep_mixer_struct *mixer);
46 static int sol_mixer_set(struct sysdep_mixer_struct *mixer,
47 int channel, int left, int right);
48 static int sol_mixer_get(struct sysdep_mixer_struct *mixer,
49 int channel, int *left, int *right);
50
51 /* public variables */
52 const struct plugin_struct sysdep_mixer_solaris = {
53 "solaris",
54 "sysdep_mixer",
55 "Solaris mixer plugin",
56 NULL, /* no options */
57 NULL, /* no init */
58 NULL, /* no exit */
59 sol_mixer_create,
60 3 /* high priority */
61 };
62
63 /* public methods (static but exported through the sysdep_mixer or plugin
64 struct) */
sol_mixer_create(const void * flags)65 static void *sol_mixer_create(const void *flags)
66 {
67 struct sol_mixer_priv_data *priv = NULL;
68 struct sysdep_mixer_struct *mixer = NULL;
69 const struct sysdep_mixer_create_params *params = flags;
70 const char *device = params->device;
71
72 /* allocate the mixer struct */
73 if (!(mixer = calloc(1, sizeof(struct sysdep_mixer_struct))))
74 {
75 perror("error malloc failed for struct sysdep_mixer_struct\n");
76 return NULL;
77 }
78
79 /* alloc private data */
80 if(!(priv = calloc(1, sizeof(struct sol_mixer_priv_data))))
81 {
82 perror("error malloc failed for struct sol_mixer_priv_data\n");
83 sol_mixer_destroy(mixer);
84 return NULL;
85 }
86
87 /* fill in the functions and some data */
88 priv->fd = -1;
89 mixer->_priv = priv;
90 mixer->set = sol_mixer_set;
91 mixer->get = sol_mixer_get;
92 mixer->destroy = sol_mixer_destroy;
93
94 /* open the mixer device */
95 if (!device)
96 device = getenv("AUDIODEV");
97 if (!device)
98 device = "/dev/audioctl";
99
100 if((priv->fd = open(device, O_RDWR)) < 0) {
101 fprintf(stderr, "error: opening %s\n", device);
102 sol_mixer_destroy(mixer);
103 return NULL;
104 }
105
106 /* are there more channels on other hardware as dbri? */
107 mixer->channel_available[SYSDEP_MIXER_PCM1] = 1;
108 return mixer;
109 }
110
sol_mixer_destroy(struct sysdep_mixer_struct * mixer)111 static void sol_mixer_destroy(struct sysdep_mixer_struct *mixer)
112 {
113 struct sol_mixer_priv_data *priv = mixer->_priv;
114
115 if(priv)
116 {
117 if(priv->fd >= 0)
118 close(priv->fd);
119
120 free(priv);
121 }
122 free(mixer);
123 }
124
sol_mixer_set(struct sysdep_mixer_struct * mixer,int channel,int left,int right)125 static int sol_mixer_set(struct sysdep_mixer_struct *mixer, int channel, int left, int right)
126 {
127 audio_info_t info;
128 struct sol_mixer_priv_data *priv = mixer->_priv;
129 int maxvol = (left > right)? left: right;
130
131 AUDIO_INITINFO(&info);
132
133 info.play.gain = (maxvol * (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)) / 100 + AUDIO_MIN_GAIN;
134 if (maxvol)
135 {
136 info.play.balance = (right - left) * (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE);
137 info.play.balance /= 2 * maxvol;
138 info.play.balance += AUDIO_MID_BALANCE;
139 }
140
141 if (ioctl(priv->fd, AUDIO_SETINFO, &info) < 0)
142 {
143 perror("error: AUDIO_SETINFO\n");
144 return -1;
145 }
146 return 0;
147 }
148
sol_mixer_get(struct sysdep_mixer_struct * mixer,int channel,int * left,int * right)149 static int sol_mixer_get(struct sysdep_mixer_struct *mixer, int channel, int *left, int *right)
150 {
151 audio_info_t info;
152 struct sol_mixer_priv_data *priv = mixer->_priv;
153
154 if (ioctl(priv->fd, AUDIO_GETINFO, &info) < 0)
155 {
156 perror("error: AUDIO_GETINFO\n");
157 return -1;
158 }
159
160 if (info.play.balance > AUDIO_MID_BALANCE)
161 {
162 *right = ((info.play.gain - AUDIO_MIN_GAIN) * 100) / (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN);
163 *left = *right * ((AUDIO_RIGHT_BALANCE - (float)info.play.balance) / AUDIO_MID_BALANCE);
164 }
165 else
166 {
167 *left = ((info.play.gain - AUDIO_MIN_GAIN) * 100) / (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN);
168 *right = *left * ((float)info.play.balance / AUDIO_MID_BALANCE);
169 }
170 return 0;
171 }
172
173