source: roaraudio/roard/hwmixer_oss.c @ 4388:2de43be17c40

Last change on this file since 4388:2de43be17c40 was 4388:2de43be17c40, checked in by phi, 14 years ago

changed a lot internals of the OSS hwmixer.

File size: 5.7 KB
Line 
1//hwmixer_oss.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#define OSS_VOLUME_SCALE 100
29
30struct subdev {
31 int bit;
32 int channels;
33 long long int cmd_read, cmd_write;
34};
35
36static struct subdev_map {
37 const char * name;
38 struct subdev subdev;
39} g_subdevs[] = {
40 {"Volume", {.bit = SOUND_MASK_VOLUME, .cmd_read = SOUND_MIXER_READ_VOLUME, .cmd_write = SOUND_MIXER_WRITE_VOLUME}},
41 {NULL}
42};
43
44static int hwmixer_oss_open_stream(struct hwmixer_stream * stream, int devmask, int sdevmask, char * basename, struct roar_keyval * subname) {
45 struct subdev * subdev;
46 struct subdev * source_subdev = NULL;
47 struct roar_stream_server * ss;
48 int i;
49
50 for (i = 0; g_subdevs[i].name != NULL; i++) {
51  if ( !strcasecmp(subname->key, g_subdevs[i].name) ) {
52   source_subdev = &(g_subdevs[i].subdev);
53   break;
54  }
55 }
56
57 if ( source_subdev == NULL )
58  return -1;
59
60 if ( !(devmask & source_subdev->bit) )
61  return -1;
62
63 subdev = roar_mm_malloc(sizeof(struct subdev));
64
65 if ( subdev == NULL )
66  return -1;
67
68 memcpy(subdev, source_subdev, sizeof(struct subdev));
69
70 subdev->channels = sdevmask & subdev->bit ? 2 : 1;
71
72 stream->ud     = subdev;
73
74 if (streams_get(stream->stream, &ss) != -1) {
75  ROAR_STREAM(ss)->info.channels = subdev->channels;
76 } else {
77  ROAR_WARN("hwmixer_dstr_open(*): can not get object for stream %i", stream->stream);
78 }
79
80 return 0;
81}
82
83int hwmixer_oss_open(struct hwmixer_stream * stream, char * drv, char * dev, int fh, char * basename, struct roar_keyval * subnames, size_t subnamelen) {
84 struct roar_vio_calls * vio = roar_mm_malloc(sizeof(struct roar_vio_calls));
85 struct roar_vio_defaults def;
86 struct roar_vio_sysio_ioctl ctl;
87 struct roar_keyval kv;
88 int devmask, sdevmask;
89
90 if ( vio == NULL ) {
91  return -1;
92 }
93
94 if ( fh == -1 ) {
95#ifdef ROAR_DEFAULT_OSS_MIX_DEV
96  if ( dev == NULL ) {
97   dev = ROAR_DEFAULT_OSS_MIX_DEV;
98  }
99#endif
100
101  if ( dev == NULL ) {
102   roar_mm_free(vio);
103   return -1;
104  }
105
106  if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_FILE, O_RDWR, 0644) == -1 ) {
107   roar_mm_free(vio);
108   return -1;
109  }
110
111  if ( roar_vio_open_dstr(vio, dev, &def, 1) == -1 ) {
112   roar_mm_free(vio);
113   return -1;
114  }
115 } else {
116  if ( roar_vio_open_fh(vio, fh) == -1 ) {
117   roar_mm_free(vio);
118   return -1;
119  }
120 }
121
122 stream->baseud = vio;
123
124 ctl.cmd  = SOUND_MIXER_READ_DEVMASK;
125 ctl.argp = &devmask;
126
127 if ( roar_vio_ctl(vio, ROAR_VIO_CTL_SYSIO_IOCTL, &ctl) == -1 ) {
128  roar_vio_close(vio);
129  roar_mm_free(vio);
130  return -1;
131 }
132
133 ctl.cmd  = SOUND_MIXER_READ_STEREODEVS;
134 ctl.argp = &sdevmask;
135
136 if ( roar_vio_ctl(vio, ROAR_VIO_CTL_SYSIO_IOCTL, &ctl) == -1 ) {
137  sdevmask = 0;
138 }
139
140 kv.key   = "Volume";
141 kv.value = NULL;
142
143 if ( hwmixer_oss_open_stream(stream, devmask, sdevmask, basename, &kv) == -1 ) {
144  roar_vio_close(vio);
145  roar_mm_free(vio);
146  return -1;
147 }
148
149
150#ifdef TEST_HWMIXER_SUBSTREAMS
151 stream = hwmixer_substream_new(stream);
152 if ( stream == NULL ) {
153  ROAR_WARN("hwmixer_dstr_open(*): can not create substream");
154 } else {
155  if (streams_get(stream->stream, &ss) != -1) {
156   ROAR_STREAM(ss)->info.channels = 2;
157  } else {
158   ROAR_WARN("hwmixer_dstr_open(*): can not get object for stream %i", stream->stream);
159  }
160 }
161#endif
162
163 return 0;
164}
165
166int hwmixer_oss_close(struct hwmixer_stream * stream) {
167 // are we a substream? if yes we do not clean up anything.
168 // streams_delete() will do all our work.
169
170 roar_mm_free(stream->ud);
171
172 if ( stream->stream != stream->basestream )
173  return 0;
174
175 roar_vio_close(stream->baseud);
176 roar_mm_free(stream->baseud);
177 return 0;
178}
179
180int hwmixer_oss_set_vol(struct hwmixer_stream * stream, int channels, int mode, struct roar_mixer_settings * settings) {
181 struct roar_vio_calls * vio = stream->baseud;
182 struct roar_vio_sysio_ioctl ctl;
183 struct subdev         * subdev = stream->ud;
184 int i;
185 int l, r;
186
187 if ( channels == 0 )
188  return 0;
189
190 if ( channels == 1 ) {
191  l = r = settings->mixer[0];
192 } else {
193  l = settings->mixer[0];
194  r = settings->mixer[1];
195 }
196
197 if ( subdev->channels == 1 ) {
198  l = r = (l + r) / 2;
199 }
200
201 l = (l * OSS_VOLUME_SCALE) / settings->scale;
202 r = (r * OSS_VOLUME_SCALE) / settings->scale;
203
204 i = (l & 0xFF) | ((r & 0xFF) << 8);
205
206 ctl.cmd = subdev->cmd_write;
207 ctl.argp = &i;
208
209 return roar_vio_ctl(vio, ROAR_VIO_CTL_SYSIO_IOCTL, &ctl);
210}
211
212int hwmixer_oss_get_vol(struct hwmixer_stream * stream, int channels, int mode, struct roar_mixer_settings * settings) {
213 struct roar_vio_calls * vio = stream->baseud;
214 struct roar_vio_sysio_ioctl ctl;
215 struct subdev         * subdev = stream->ud;
216 int i;
217 int l, r;
218
219 ctl.cmd = subdev->cmd_read;
220 ctl.argp = &i;
221
222 if ( roar_vio_ctl(vio, ROAR_VIO_CTL_SYSIO_IOCTL, &ctl) == -1 )
223  return -1;
224
225 l =  i       & 0xFF;
226 r = (i >> 8) & 0xFF;
227
228 if ( subdev->channels == 1 )
229  r = l;
230
231 settings->scale    = OSS_VOLUME_SCALE;
232
233 if ( channels == 1 ) {
234  settings->mixer[0] = (l + r) / 2;
235 } else if ( channels == 2 ) {
236  settings->mixer[0] = l;
237  settings->mixer[1] = r;
238 } else {
239  return -1;
240 }
241
242 return 0;
243}
244
245//ll
Note: See TracBrowser for help on using the repository browser.