1 /* 2 * Library to query / set various sound mixer parameters. 3 * 4 * This code is based on setmixer program by Michal Jaegermann 5 * 6 * Copyright (c) 2000 Sergey Gribov <sergey@sergey.com> 7 * This is free software with ABSOLUTELY NO WARRANTY. 8 * You can redistribute and modify it freely, but please leave 9 * this message attached to this file. 10 * 11 * Subject to terms of GNU General Public License (www.gnu.org) 12 * 13 * Last update: $Date: 2002/04/30 00:48:21 $ by $Author: sergey $ 14 * Revision: $Revision: 1.5 $ 15 * 16 */ 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <fcntl.h> 21 #include <unistd.h> 22 #include <sys/ioctl.h> 23 #include <sys/soundcard.h> 24 25 #include "Mix.h" 26 27 #define BUFSIZE 512 28 29 const char * dname[] = SOUND_DEVICE_NAMES; 30 31 static int devmask, stereod, recmask, mixer_fd = -1, init_flag = 0; 32 33 static char dev_fname[BUFSIZE] = ""; 34 35 int 36 set_mixer_dev(char *fname) { 37 #ifdef DEBUG 38 fprintf(stderr, "set_mixer_dev(%s)\n", fname); 39 #endif 40 strncpy(dev_fname, fname, BUFSIZE-1); 41 return(0); 42 } 43 44 int 45 open_mixer() { 46 #ifdef DEBUG 47 fprintf(stderr, "open_mixer()\n"); 48 #endif 49 if (dev_fname[0] == '\0') { 50 strncpy(dev_fname, MIXER, BUFSIZE-1); 51 } 52 if ((mixer_fd = open(dev_fname, O_RDWR)) < 0) { 53 fprintf(stderr, "Error opening %s.", MIXER); 54 return(-1); 55 } 56 if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { 57 perror("SOUND_MIXER_READ_DEVMASK"); 58 return(-1); 59 } 60 if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereod) == -1) { 61 perror("SOUND_MIXER_READ_STEREODEVS"); 62 return(-1); 63 } 64 if (ioctl(mixer_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { 65 perror("SOUND_MIXER_READ_RECMASK"); 66 return(-1); 67 } 68 69 if (!devmask) { 70 fprintf(stderr, "No device found."); 71 return(-1); 72 } 73 return(0); 74 } 75 76 int 77 close_mixer() { 78 #ifdef DEBUG 79 fprintf(stderr, "close_mixer()\n"); 80 #endif 81 if (mixer_fd < 0) return 0; 82 close(mixer_fd); 83 init_flag = 0; 84 mixer_fd = -1; 85 return(0); 86 } 87 88 /* 89 * Get parameter value 90 * Parameter: 91 * cntrl - name of parameter 92 * Returns: 93 * integer value, which will be constructed as follows: 94 * lower byte (x & 0xff) - value of the left channel (or whole value) 95 * next byte (x & 0xff00) - value of the right channel 96 * third byte (x & 0xff0000) - flags (if x & 0x10000 then 2 channels exist) 97 */ 98 int 99 get_param_val(char *cntrl) { 100 int i, d, len, lcval, ret = 0; 101 102 #ifdef DEBUG 103 fprintf(stderr, "get_param_val(%s)\n", cntrl); 104 #endif 105 106 if (!init_flag) { 107 if (open_mixer()) { 108 return(-1); 109 } 110 } 111 len = strlen(cntrl); 112 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 113 d = (1 << i); 114 if ((0 == strncmp(dname[i], cntrl, len)) && 115 (0 != (devmask & d))) { 116 if (-1 == ioctl(mixer_fd, MIXER_READ(i), &lcval)) { 117 perror("MIXER_READ"); 118 if (!init_flag) 119 close_mixer(); 120 return(-1); 121 } 122 else { 123 ret = lcval & 0x7f; 124 if (d & stereod) { 125 ret = ret | 0x10000; 126 ret = ret | (lcval & 0x7f00); 127 if (!init_flag) 128 close_mixer(); 129 return(ret); 130 } 131 } 132 } 133 } 134 if (!init_flag) 135 close_mixer(); 136 return(-1); 137 } 138 139 140 char * 141 get_source() 142 { 143 int j; 144 unsigned int source = 0; 145 if (!init_flag){ 146 if (open_mixer()) 147 return(""); 148 } 149 if (-1 == ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &source)){ 150 perror("MIXER_READ_RECSRC"); 151 if (!init_flag) 152 close_mixer(); 153 return(""); 154 } 155 if (!init_flag) 156 close_mixer(); 157 source &= recmask; 158 for (j = 0; source; source >>= 1, j++){ 159 if (source & 1) 160 return((char *) dname[j]); 161 } 162 return(""); 163 } 164 165 int 166 set_source(char *cntrl) 167 { 168 int i, d, len, ret = 0; 169 170 #ifdef DEBUG 171 fprintf(stderr, "set_recsrc(%s)\n", cntrl); 172 #endif 173 174 if (!init_flag) { 175 if (open_mixer()) { 176 return(-1); 177 } 178 } 179 len = strlen(cntrl); 180 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 181 d = (1 << i); 182 if ((0 == strncmp(dname[i], cntrl, len)) && 183 (0 != (recmask & d))) { 184 if (-1 == ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &d)) { 185 perror("MIXER_WRITE_RECSRC"); 186 if (!init_flag) 187 close_mixer(); 188 return(-1); 189 } 190 else { 191 if (!init_flag) 192 close_mixer(); 193 return(0); 194 } 195 } 196 } 197 d = 0; 198 if (-1 == ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &d)) { 199 perror("MIXER_WRITE_RECSRC"); 200 if (!init_flag) 201 close_mixer(); 202 return(-1); 203 } 204 if (!init_flag) 205 close_mixer(); 206 return(0); 207 } 208 209 /* 210 * Set parameter value. 211 * Parameters: 212 * cntrl - name of parameter 213 * lcval - left channel value 214 * rcval - right channel value 215 * Returns 0 if Ok, -1 if failed 216 */ 217 int 218 set_param_val(char *cntrl, int lcval, int rcval) { 219 int len, i, d; 220 221 #ifdef DEBUG 222 fprintf(stderr, "set_param_val(%s, %d, %d)\n", cntrl, lcval, rcval); 223 #endif 224 225 if (!init_flag) { 226 if (open_mixer()) { 227 return(-1); 228 } 229 } 230 len = strlen(cntrl); 231 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 232 if (0 == strncmp(dname[i], cntrl, len)) { 233 d = (1 << i); 234 if (0 != (devmask & d)) { 235 lcval = (lcval < 0 ? 0 : (lcval > 100 ? 100 : lcval)); 236 if (d & stereod) { 237 rcval = (rcval < 0 ? 0 : (rcval > 100 ? 100 : rcval)); 238 lcval |= (rcval << 8); 239 } 240 if (-1 == ioctl(mixer_fd, MIXER_WRITE(i), &lcval)) { 241 perror("MIXER_WRITE"); 242 if (!init_flag) 243 close_mixer(); 244 return(-1); 245 } 246 } 247 break; 248 } 249 } 250 if (!init_flag) 251 close_mixer(); 252 return(0); 253 } 254 255 int 256 init_mixer() { 257 if (open_mixer()) { 258 return(-1); 259 } 260 init_flag = 1; 261 return(0); 262 } 263 264 int 265 get_params_num() { 266 return(SOUND_MIXER_NRDEVICES); 267 } 268 269 char * 270 get_params_list() { 271 static char buf[BUFSIZE]; 272 int i, l, len = 0; 273 buf[0] = '\0'; 274 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 275 l = strlen(dname[i]); 276 if ((len >= (BUFSIZE - 2)) || ((len + l + 3) >= BUFSIZE)) { 277 buf[len] = '\0'; 278 return(buf); 279 } 280 strcat(buf, dname[i]); 281 strcat(buf, " "); 282 len += l + 1; 283 } 284 buf[len] = '\0'; 285 return(buf); 286 } 287 288