home *** CD-ROM | disk | FTP | other *** search
- /*
- * xmmix - Motif(tm) Audio Mixer
- *
- * Copyright (C) 1995 Ti Kan
- * E-mail: ti@amb.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
- #ifndef LINT
- static char *_mixer_c_ident_ = "@(#)mixer.c 2.15 95/05/13";
- #endif
-
- #include "appenv.h"
- #include "patchlevel.h"
- #include "widget.h"
- #include "mixer.h"
-
-
- /* Ioctl data direction flags */
- #define IOC_DATA_NONE 0
- #define IOC_DATA_IN 1
- #define IOC_DATA_OUT 2
-
-
- extern appdata_t app_data;
- extern widgets_t widgets;
- extern bool_t exit_flag;
- extern FILE *errfp;
-
-
- int maxdevs; /* Maximum number of devices */
-
- STATIC int dev_fd = -1, /* Mixer device file descriptor */
- fsmode; /* File selection mode */
-
- STATIC char drv_ver[128]; /* Sound driver version */
-
- STATIC ctlinfo_t ctlinfo = { /* Current state of all controls */
- 0, 0, 0, 0, 0, 0, FALSE, FALSE,
- {
- { 0, 0, TRUE }, /* 0 */
- { 50, 50, TRUE }, /* 1 */
- { 50, 50, TRUE }, /* 2 */
- { 0, 0, TRUE }, /* 3 */
- { 0, 0, TRUE }, /* 4 */
- { 0, 0, TRUE }, /* 5 */
- { 0, 0, TRUE }, /* 6 */
- { 0, 0, TRUE }, /* 7 */
- { 0, 0, TRUE }, /* 8 */
- { 0, 0, TRUE }, /* 9 */
- { 0, 0, TRUE }, /* 10 */
- { 0, 0, TRUE }, /* 11 */
- { 0, 0, TRUE }, /* 12 */
- { 0, 0, TRUE }, /* 13 */
- { 0, 0, TRUE }, /* 14 */
- { 0, 0, TRUE }, /* 15 */
- { 0, 0, TRUE }, /* 16 */
- { 0, 0, TRUE }, /* 17 */
- { 0, 0, TRUE }, /* 18 */
- { 0, 0, TRUE }, /* 19 */
- { 0, 0, TRUE }, /* 20 */
- { 0, 0, TRUE }, /* 21 */
- { 0, 0, TRUE }, /* 22 */
- { 0, 0, TRUE }, /* 23 */
- { 0, 0, TRUE }, /* 24 */
- { 0, 0, TRUE }, /* 25 */
- { 0, 0, TRUE }, /* 26 */
- { 0, 0, TRUE }, /* 27 */
- { 0, 0, TRUE }, /* 28 */
- { 0, 0, TRUE }, /* 29 */
- { 0, 0, TRUE }, /* 30 */
- { 0, 0, TRUE } /* 31 */
- }
- };
-
- STATIC ctlinfo_t ctlsav; /* Saved state of all controls */
-
-
- /***********************
- * internal routines *
- ***********************/
-
-
- /*
- * do_ioctl
- * Perform ioctl command. If file is not yet open or if we
- * are in demo mode, just quietly return. If an error
- * status is returned, print an appropriate error message
- * and exit.
- *
- * Args:
- * cmd - The ioctl command
- * arg - The ioctl argument
- * name - The ioctl command string
- * dir - Data direction
- * IOC_DATA_IN
- * IOC_DATA_OUT
- * IOC_DATA_NONE
- *
- * Return:
- * Nothing
- */
- STATIC void
- do_ioctl(int cmd, int *arg, char *name, int dir)
- {
- int ret;
- char errmsg[STR_BUF_SZ];
-
- if (dev_fd < 0 || app_data.demo)
- return;
-
- sprintf(errmsg, "\n%s ioctl failed", name);
- if (app_data.debug) {
- fprintf(errfp, "%s: cmd=0x%x (%s) ", PROGNAME, cmd, name);
-
- if (dir == IOC_DATA_OUT)
- fprintf(errfp, "*arg=0x%x", *arg);
- }
-
- if ((ret = ioctl(dev_fd, cmd, arg)) < 0) {
- perror(errmsg);
- exit_flag = TRUE;
- }
-
- if (app_data.debug) {
- if (ret == 0 && dir == IOC_DATA_IN)
- fprintf(errfp, "*arg=0x%x", *arg);
- fprintf(errfp, "\n");
- }
- }
-
-
- /*
- * mx_queryhw
- * Query mixer settings and update current ctlinfo state.
- *
- * Args:
- * m - Pointer to the main widgets structure
- *
- * Return:
- * Nothing
- */
- STATIC void
- mx_queryhw(widgets_t *m)
- {
- int i,
- level,
- curmask;
- char iocstr[STR_BUF_SZ];
- static bool_t first = TRUE;
-
- if (app_data.demo) {
- if (first) {
- /* Save start-up settings */
- first = FALSE;
- ctlsav = ctlinfo; /* Structure copy */
- }
- return;
- }
-
- /* Read record source */
- do_ioctl(
- SOUND_MIXER_READ_RECSRC,
- &ctlinfo.recsrc,
- "SOUND_MIXER_READ_RECSRC",
- IOC_DATA_IN
- );
-
- /* Read control settings */
- for (i = 0; i < maxdevs; i++) {
- curmask = (1 << i);
-
- if (m->sl[i].supp) {
- sprintf(iocstr, "MIXER_READ[%d]:%s", i, m->sl[i].name);
- do_ioctl(MIXER_READ(i), &level, iocstr, IOC_DATA_IN);
-
- ctlinfo.slinfo[i].left = (level & 0xff);
- ctlinfo.slinfo[i].right = ((level >> 8) & 0xff);
-
- /* Sanity check */
- if (ctlinfo.slinfo[i].left > 100)
- ctlinfo.slinfo[i].left = 100;
- else if (ctlinfo.slinfo[i].left < 0)
- ctlinfo.slinfo[i].left = 0;
- if (ctlinfo.slinfo[i].right > 100)
- ctlinfo.slinfo[i].right = 100;
- else if (ctlinfo.slinfo[i].right < 0)
- ctlinfo.slinfo[i].right = 0;
-
- if ((curmask & ctlinfo.stereodevs) == 0) {
- ctlinfo.slinfo[i].left =
- ctlinfo.slinfo[i].right =
- (ctlinfo.slinfo[i].left +
- ctlinfo.slinfo[i].right) / 2;
- ctlinfo.slinfo[i].locked = TRUE;
- }
-
- if (ctlinfo.slinfo[i].left != ctlinfo.slinfo[i].right)
- ctlinfo.slinfo[i].locked = FALSE;
- }
- }
-
- #ifdef SOUND_ONOFF_MAX
- /* Additional toggle capabilitites */
- for (i = SOUND_ONOFF_MIN; i <= SOUND_ONOFF_MAX; i++) {
- curmask = (1 << i);
-
- if (curmask & ctlinfo.devmask) {
- sprintf(iocstr, "MIXER_READ[%d]:%s", i, m->sl[i].name);
- do_ioctl(MIXER_READ(i), &level, iocstr, IOC_DATA_IN);
-
- switch (i) {
- case SOUND_MIXER_MUTE:
- ctlinfo.mute = (level != 0);
- break;
- case SOUND_MIXER_LOUD:
- ctlinfo.loudness = (level != 0);
- break;
- case SOUND_MIXER_ENHANCE:
- /* Hack: The enhance values are hard wired. */
- switch (level) {
- case 80:
- ctlinfo.enhance = 3;
- break;
- case 60:
- ctlinfo.enhance = 2;
- break;
- case 40:
- ctlinfo.enhance = 1;
- break;
- case 0:
- default:
- ctlinfo.enhance = 0;
- break;
- }
- break;
- default:
- /* Unsupported feature: ignore */
- break;
- }
- }
- }
- #endif /* SOUND_ONOFF_MAX */
-
- if (first) {
- /* Save start-up settings */
- first = FALSE;
- ctlsav = ctlinfo; /* Structure copy */
- }
- }
-
-
- /*
- * mx_sethw
- * Set all sound hardware settings to the current ctlinfo state.
- *
- * Args:
- * m - Pointer to the main widgets structure
- *
- * Return:
- * Nothing
- */
- STATIC void
- mx_sethw(widgets_t *m)
- {
- int i;
- XmScaleCallbackStruct s;
- XmToggleButtonCallbackStruct t;
- XmPushButtonCallbackStruct p;
-
- /* Fake callbacks */
- s.reason = XmCR_VALUE_CHANGED;
- t.reason = XmCR_VALUE_CHANGED;
- p.reason = XmCR_ACTIVATE;
-
- for (i = 0; i < maxdevs; i++) {
- if (!m->sl[i].supp)
- continue;
-
- /* Left slider */
- s.value = ctlinfo.slinfo[i].left;
- mx_slider_l(m->sl[i].widget_l, (XtPointer) i, (XtPointer) &s);
-
- /* Right slider */
- s.value = ctlinfo.slinfo[i].right;
- mx_slider_r(m->sl[i].widget_r, (XtPointer) i, (XtPointer) &s);
-
- /* Lock button */
- t.set = (Boolean) ctlinfo.slinfo[i].locked;
- mx_lock_btn(m->sl[i].widget_lock_btn, (XtPointer) i,
- (XtPointer) &t);
-
- /* Rec button */
- if (m->sl[i].recsupp) {
- #ifdef SOUND_CAP_EXCL_INPUT
- if ((ctlinfo.recsrc & (1 << i)) ||
- ctlinfo.caps != SOUND_CAP_EXCL_INPUT)
- #endif
- {
- if (ctlinfo.recsrc & (1 << i))
- t.set = True;
- else
- t.set = False;
-
- mx_rec_btn(m->sl[i].widget_rec_btn,
- (XtPointer) i, (XtPointer) &t);
- }
- }
- }
-
- /* Mute button */
- if (m->mute_supp) {
- t.set = (Boolean) ctlinfo.mute;
- mx_mute_btn(m->mute_btn, NULL, (XtPointer) &t);
- }
-
- /* Loudness button */
- if (m->loud_supp) {
- t.set = (Boolean) ctlinfo.loudness;
- mx_loud_btn(m->loud_btn, NULL, (XtPointer) &t);
- }
-
- /* Enhance buttons */
- if (m->enh_supp) {
- mx_enhance_btn(m->enh_btn[ctlinfo.enhance],
- (XtPointer) ctlinfo.enhance, (XtPointer) &p);
- }
- }
-
-
- /*
- * mx_updctl
- * Update all control positions on screen to the current ctlinfo
- * state.
- *
- * Args:
- * m - Pointer to the main widgets structure
- *
- * Return:
- * Nothing
- */
- STATIC void
- mx_updctl(widgets_t *m)
- {
- int i;
-
- for (i = 0; i < maxdevs; i++) {
- if (!m->sl[i].supp)
- continue;
-
- /* Left and right sliders */
- XmScaleSetValue(
- m->sl[i].widget_l,
- ctlinfo.slinfo[i].left
- );
- XmScaleSetValue(
- m->sl[i].widget_r,
- ctlinfo.slinfo[i].right
- );
-
- /* Lock button */
- XmToggleButtonSetState(
- m->sl[i].widget_lock_btn,
- ctlinfo.slinfo[i].locked, False
- );
-
- /* Rec button */
- if (m->sl[i].recsupp) {
- if (ctlinfo.recsrc & (1 << i)) {
- XmToggleButtonSetState(
- m->sl[i].widget_rec_btn,
- True, False
- );
- }
- else {
- XmToggleButtonSetState(
- m->sl[i].widget_rec_btn,
- False, False
- );
- }
- }
- }
-
- /* Mute button */
- if (m->mute_supp)
- XmToggleButtonSetState(m->mute_btn, ctlinfo.mute, False);
-
- /* Loudness button */
- if (m->loud_supp)
- XmToggleButtonSetState(m->loud_btn, ctlinfo.loudness, False);
-
- /* Stereo enhance menu */
- if (m->enh_supp) {
- XtVaSetValues(m->enh_opt,
- XmNmenuHistory, m->enh_btn[ctlinfo.enhance],
- NULL
- );
- }
- }
-
-
- /*
- * mx_readfile
- * Read mixer settings from file and update control settings.
- *
- * Args:
- * path - File path string
- *
- * Return:
- * TRUE on success, FALSE on failure
- */
- STATIC bool_t
- mx_readfile(char *path)
- {
- FILE *fp;
- int i,
- curmask,
- val1,
- val2,
- val3,
- val4;
- char *p,
- buf[STR_BUF_SZ];
-
- if (app_data.debug)
- fprintf(errfp, "Reading mixer file: %s\n", path);
-
- /* Open file for reading */
- if ((fp = fopen(path, "r")) == NULL)
- return FALSE;
-
- /* Read first line of mixer settings file */
- if (fgets(buf, sizeof(buf), fp) == NULL) {
- fclose(fp);
- return FALSE;
- }
-
- /* Mixer settings file signature check */
- if (strncmp(buf, "# xmmix ", 8) != 0) {
- fclose(fp);
- return FALSE;
- }
-
- /* Read the rest of the mixer settings file */
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- if (buf[0] == '#')
- /* Comment line */
- continue;
-
- if ((p = strchr(buf, '=')) == NULL)
- /* Invalid line */
- continue;
-
- *p = '\0';
-
- if (sscanf(p+1, "%d,%d,%d,%d\n",
- &val1, &val2, &val3, &val4) == 4) {
-
- for (i = 0; i < maxdevs; i++) {
- if (strcmp(buf, widgets.sl[i].name) == 0)
- break;
- }
-
- if (i >= maxdevs)
- /* Unrecognized keyword */
- continue;
-
- curmask = (1 << i);
-
- if (!(ctlinfo.devmask & curmask))
- /* Device not supported */
- continue;
-
- ctlinfo.slinfo[i].left = val1;
- ctlinfo.slinfo[i].right = val2;
-
- if (val1 == val2)
- ctlinfo.slinfo[i].locked = (bool_t) (val3 > 0);
- else
- ctlinfo.slinfo[i].locked = FALSE;
-
- if (val4 > 0 && widgets.sl[i].recsupp &&
- (ctlinfo.recmask & curmask))
- ctlinfo.recsrc |= (1 << i);
- else
- ctlinfo.recsrc &= ~(1 << i);
- }
- #ifdef SOUND_ONOFF_MAX
- else if (sscanf(p+1, "%d\n", &val1) == 1) {
- if (strcmp(buf, "mute") == 0 &&
- ctlinfo.devmask & (1 << SOUND_MIXER_MUTE)) {
- ctlinfo.mute = (bool_t) (val1 > 0);
- }
- else if (strcmp(buf, "enhance") == 0 &&
- ctlinfo.devmask & (1 << SOUND_MIXER_ENHANCE)) {
- ctlinfo.enhance = val1;
- }
- else if (strcmp(buf, "loudness") == 0 &&
- ctlinfo.devmask & (1 << SOUND_MIXER_LOUD)) {
- ctlinfo.loudness = (bool_t) (val1 > 0);
- }
- }
- #endif
- }
-
- fclose(fp);
-
- /* Update controls to match current status */
- mx_updctl(&widgets);
-
- /* Set all controls */
- mx_sethw(&widgets);
-
- return TRUE;
- }
-
-
- /*
- * mx_writefile
- * Write current mixer settings to file.
- *
- * Args:
- * path - File path string
- *
- * Return:
- * TRUE on success, FALSE on failure
- */
- STATIC bool_t
- mx_writefile(char *path)
- {
- FILE *fp;
- int i;
-
- if (app_data.debug)
- fprintf(errfp, "Writing mixer file: %s\n", path);
-
- /* Open file for writing */
- if ((fp = fopen(path, "w")) == NULL)
- return FALSE;
-
- /* Write first two lines of mixer settings file */
- fprintf(fp, "# xmmix %s Mixer Settings File\n", VERSION);
- fprintf(fp, "# Copyright (C) 1995 Ti Kan\n#\n");
-
- /* Write all control settings */
- for (i = 0; i < MAXDEVS; i++) {
- if (widgets.sl[i].name == NULL)
- break;
-
- fprintf(fp, "%s=%d,%d,%d,%d\n",
- widgets.sl[i].name,
- ctlinfo.slinfo[i].left,
- ctlinfo.slinfo[i].right,
- ctlinfo.slinfo[i].locked,
- (int) ((ctlinfo.recsrc & (1 << i)) > 0));
- }
-
- #ifdef SOUND_ONOFF_MAX
- fprintf(fp, "%s=%d\n", "mute", (int) ctlinfo.mute);
- fprintf(fp, "%s=%d\n", "enhance", ctlinfo.enhance);
- fprintf(fp, "%s=%d\n", "loudness", (int) ctlinfo.loudness);
- #endif
-
- return (fclose(fp) == 0);
- }
-
-
- /*
- * mx_warning
- * Pop up a warning message dialog box.
- *
- * Args:
- * msg - The message string to display
- *
- * Return:
- * Nothing
- */
- STATIC void
- mx_warning(char *msg)
- {
- XmString xs;
-
- xs = XmStringCreateLtoR(msg, XmSTRING_DEFAULT_CHARSET);
- XtVaSetValues(widgets.warning, XmNmessageString, xs, NULL);
- XmStringFree(xs);
-
- if (!XtIsManaged(widgets.warning))
- XtManageChild(widgets.warning);
- }
-
-
- /***********************
- * public routines *
- ***********************/
-
-
- /*
- * mx_init_drv
- * Sound driver version-specific initialization routine.
- * Query sound driver version and set appropriate capabilities.
- * Note: this routine will likely require modification if
- * future sound driver versions add new mixer features.
- *
- * Args:
- * None
- *
- * Return:
- * Nothing
- */
- void
- mx_init_drv(void)
- {
- FILE *fp;
- char *p,
- tmpbuf[128];
-
- if (app_data.debug) {
- fprintf(errfp, "XMMIX v%s%s PL%d DEBUG MODE\n\n",
- VERSION, VERSION_EXT, PATCHLEVEL);
-
- if (app_data.demo)
- fprintf(errfp, "DEMO MODE!!!\n");
- fprintf(errfp, "Compiled with soundcard.h version %d\n",
- SOUND_VERSION);
- fprintf(errfp, "device=%s\n", app_data.device);
- fprintf(errfp, "helpPath=%s\n", app_data.helppath);
- fprintf(errfp, "autoLoadOnStartUp=%s\n",
- app_data.autoload == NULL ? "" : app_data.autoload);
- fprintf(errfp, "resetOnExit=%s\n",
- app_data.exitreset ? "True" : "False");
- }
-
- /* Set maximum number of devices supported */
- maxdevs = MAXDEVS_V3;
-
- strcpy(drv_ver, "unknown");
-
- /* Query sound driver version */
- if ((fp = fopen("/dev/sndstat", "r")) == NULL) {
- if (!app_data.demo) {
- fprintf(errfp, "%s: %s: %s\n",
- PROGNAME,
- "Cannot open /dev/sndstat",
- "assuming pre-3.0 VoxWare driver.");
- maxdevs = MAXDEVS_V2;
- }
- return;
- }
-
- if (fgets(tmpbuf, sizeof(tmpbuf), fp) == NULL) {
- if (!app_data.demo) {
- fprintf(errfp, "%s: %s: %s\n",
- PROGNAME,
- "Cannot read /dev/sndstat",
- "assuming pre-3.0 VoxWare driver.");
- maxdevs = MAXDEVS_V2;
- }
- fclose(fp);
- return;
- }
-
- fclose(fp);
-
- /* Eat newline */
- tmpbuf[strlen(tmpbuf) - 1] = '\0';
-
- /* Skip forward to the first colon character */
- for (p = tmpbuf; *p != '\0' && *p != ':'; p++)
- ;
-
- if (*p != ':') {
- if (!app_data.demo) {
- fprintf(errfp, "%s: %s: %s\n",
- PROGNAME,
- "Cannot parse info from /dev/sndstat",
- "assuming pre-3.0 VoxWare driver.");
- maxdevs = MAXDEVS_V2;
- }
- strcpy(drv_ver, tmpbuf);
- return;
- }
-
- /* Skip blanks */
- p++;
- while (*p == ' ' || *p == '\t')
- p++;
-
- strcpy(drv_ver, p);
-
- if (!app_data.demo && *p < '3')
- /* Running on VoxWare 2.x: set max devices accordingly */
- maxdevs = MAXDEVS_V2;
-
- if (app_data.debug) {
- fprintf(errfp, "Sound driver [%s]\n", drv_ver);
- fprintf(errfp, "Running with maxdevs=%d\n\n", maxdevs);
- }
- }
-
-
- /*
- * mx_init_hw
- * Pre-realize mixer initialization routine.
- * Query sound board mixer feature capabilities and current
- * hardware settings.
- *
- * Args:
- * m - Pointer to the main widgets structure
- *
- * Return:
- * Nothing
- */
- void
- mx_init_hw(widgets_t *m)
- {
- int i,
- level,
- curmask;
- char errmsg[STR_BUF_SZ],
- iocstr[STR_BUF_SZ];
-
- if (app_data.demo) {
- /* Fake all capabilities */
- for (i = 0; i < maxdevs; i++) {
- curmask = (1 << i);
-
- ctlinfo.devmask |= curmask;
- ctlinfo.recmask |= curmask;
- ctlinfo.stereodevs |= curmask;
-
- m->sl[i].supp = TRUE;
- if (m->sl[i].type == CTL_INPUT)
- m->sl[i].recsupp = TRUE;
- else
- m->sl[i].recsupp = FALSE;
- }
-
- #ifdef SOUND_ONOFF_MAX
- for (i = SOUND_ONOFF_MIN; i <= SOUND_ONOFF_MAX; i++)
- ctlinfo.devmask |= (1 << i);
-
- m->mute_supp = TRUE;
- m->loud_supp = TRUE;
- m->enh_supp = TRUE;
- #endif
-
- /* Save start-up settings */
- ctlsav = ctlinfo; /* Structure copy */
- return;
- }
-
- /* Open device */
- sprintf(errmsg, "%s: Cannot open device %s",
- PROGNAME, app_data.device);
- if ((dev_fd = open(app_data.device, O_RDONLY)) < 0) {
- perror(errmsg);
- exit_flag = TRUE;
- }
-
- /* Read device mask */
- do_ioctl(
- SOUND_MIXER_READ_DEVMASK,
- &ctlinfo.devmask,
- "SOUND_MIXER_READ_DEVMASK",
- IOC_DATA_IN
- );
-
- /* Read record mask */
- do_ioctl(
- SOUND_MIXER_READ_RECMASK,
- &ctlinfo.recmask,
- "SOUND_MIXER_READ_RECMASK",
- IOC_DATA_IN
- );
-
- /* Read stereo devices */
- do_ioctl(
- SOUND_MIXER_READ_STEREODEVS,
- &ctlinfo.stereodevs,
- "SOUND_MIXER_READ_STEREODEVS",
- IOC_DATA_IN
- );
-
- #ifdef SOUND_MIXER_CAPS
- /* Check mixer capability */
- do_ioctl(
- SOUND_MIXER_READ_CAPS,
- &ctlinfo.caps,
- "SOUND_MIXER_READ_CAPS",
- IOC_DATA_IN
- );
- #endif
-
- /* Set flags */
- for (i = 0; i < maxdevs; i++) {
- curmask = (1 << i);
-
- if ((curmask & ctlinfo.devmask) == 0)
- m->sl[i].supp = FALSE;
- else
- m->sl[i].supp = TRUE;
-
- if (m->sl[i].type == CTL_INPUT && (curmask & ctlinfo.recmask))
- m->sl[i].recsupp = TRUE;
- else
- m->sl[i].recsupp = FALSE;
- }
-
- #ifdef SOUND_ONOFF_MAX
- /* Additional toggle capabilitites */
- for (i = SOUND_ONOFF_MIN; i <= SOUND_ONOFF_MAX; i++) {
- curmask = (1 << i);
-
- switch (i) {
- case SOUND_MIXER_MUTE:
- if (curmask & ctlinfo.devmask)
- m->mute_supp = TRUE;
- else
- m->mute_supp = FALSE;
- break;
- case SOUND_MIXER_LOUD:
- if (curmask & ctlinfo.devmask)
- m->loud_supp = TRUE;
- else
- m->loud_supp = FALSE;
- break;
- case SOUND_MIXER_ENHANCE:
- if (curmask & ctlinfo.devmask)
- m->enh_supp = TRUE;
- else
- m->enh_supp = FALSE;
- break;
- default:
- /* Unsupported feature: ignore */
- break;
- }
- }
- #else
- m->mute_supp = FALSE;
- m->loud_supp = FALSE;
- m->enh_supp = FALSE;
- #endif /* SOUND_ONOFF_MAX */
- }
-
-
- /*
- * mx_start
- * Post-realize mixer initialization routine
- *
- * Args:
- * m - Pointer to the main widgets structure
- *
- * Return:
- * Nothing
- */
- void
- mx_start(widgets_t *m)
- {
- char msg[256];
-
- if (app_data.autoload != NULL && app_data.autoload[0] != '\0' &&
- strcmp(app_data.autoload, "/dev/null") != 0) {
- if (mx_readfile(app_data.autoload)) {
- /* Successful auto-load */
- return;
- }
- else {
- sprintf(msg,
- "Autoload: Cannot read mixer settings file:\n%s",
- app_data.autoload);
- mx_warning(msg);
- }
- }
-
- /* Update screen controls to match current status */
- mx_updctl(m);
- }
-
-
- /**************** vv Callback routines vv ****************/
-
-
- /*
- * mx_slider_l
- * Left slider callback routine
- */
- /*ARGSUSED*/
- void
- mx_slider_l(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level,
- i = (int)(void *) client_data;
- XmScaleCallbackStruct *p =
- (XmScaleCallbackStruct *)(void *) call_data;
- char iocstr[STR_BUF_SZ];
-
- ctlinfo.slinfo[i].left = p->value;
-
- if (ctlinfo.slinfo[i].locked) {
- ctlinfo.slinfo[i].right = p->value;
- XmScaleSetValue(widgets.sl[i].widget_r, p->value);
- }
-
- level = (ctlinfo.slinfo[i].right << 8) | ctlinfo.slinfo[i].left;
-
- sprintf(iocstr, "MIXER_WRITE[%d]:%s", i, widgets.sl[i].name);
- do_ioctl(MIXER_WRITE(i), &level, iocstr, IOC_DATA_OUT);
- }
-
-
- /*
- * mx_slider_r
- * Right slider callback routine
- */
- /*ARGSUSED*/
- void
- mx_slider_r(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level,
- i = (int)(void *) client_data;
- XmScaleCallbackStruct *p =
- (XmScaleCallbackStruct *)(void *) call_data;
- char iocstr[STR_BUF_SZ];
-
- ctlinfo.slinfo[i].right = p->value;
-
- if (ctlinfo.slinfo[i].locked) {
- ctlinfo.slinfo[i].left = p->value;
- XmScaleSetValue(widgets.sl[i].widget_l, p->value);
- }
-
- level = (ctlinfo.slinfo[i].right << 8) | ctlinfo.slinfo[i].left;
-
- sprintf(iocstr, "MIXER_WRITE[%d]:%s", i, widgets.sl[i].name);
- do_ioctl(MIXER_WRITE(i), &level, iocstr, IOC_DATA_OUT);
- }
-
-
- /*
- * mx_lock_btn
- * Slider lock button callback routine
- */
- void
- mx_lock_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level,
- i = (int)(void *) client_data;
- XmToggleButtonCallbackStruct *p =
- (XmToggleButtonCallbackStruct *)(void *) call_data;
- char iocstr[STR_BUF_SZ];
-
- if (ctlinfo.slinfo[i].locked == p->set)
- /* No change */
- return;
-
- if (p->set) {
- ctlinfo.slinfo[i].locked = TRUE;
- ctlinfo.slinfo[i].left = ctlinfo.slinfo[i].right =
- (ctlinfo.slinfo[i].left + ctlinfo.slinfo[i].right) / 2;
-
- XmScaleSetValue(
- widgets.sl[i].widget_l,
- ctlinfo.slinfo[i].left
- );
- XmScaleSetValue(
- widgets.sl[i].widget_r,
- ctlinfo.slinfo[i].right
- );
-
- level = (ctlinfo.slinfo[i].right << 8) | ctlinfo.slinfo[i].left;
-
- sprintf(iocstr, "MIXER_WRITE[%d]:%s", i, widgets.sl[i].name);
- do_ioctl(MIXER_WRITE(i), &level, iocstr, IOC_DATA_OUT);
- }
- else {
- if ((1 << i) & ctlinfo.stereodevs)
- ctlinfo.slinfo[i].locked = FALSE;
- else {
- XmToggleButtonSetState(w, (Boolean) !p->set, False);
- XBell(XtDisplay(w), 50);
- }
- }
- }
-
-
- /*
- * mx_rec_btn
- * Record source select button callback routine
- */
- void
- mx_rec_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int i = (int)(void *) client_data,
- j,
- curmask;
- XmToggleButtonCallbackStruct *p =
- (XmToggleButtonCallbackStruct *)(void *) call_data;
-
- #ifdef SOUND_CAP_EXCL_INPUT
- if (ctlinfo.caps == SOUND_CAP_EXCL_INPUT) {
- if (!p->set) {
- XmToggleButtonSetState(w, True, False);
- return;
- }
-
- for (j = 0; j < maxdevs; j++) {
- if (!widgets.sl[j].supp || i == j)
- continue;
-
- curmask = (1 << j);
-
- if ((curmask & ctlinfo.recmask) &&
- (curmask & ctlinfo.recsrc)) {
- XmToggleButtonSetState(
- widgets.sl[j].widget_rec_btn,
- False,
- False
- );
- }
-
- }
-
- ctlinfo.recsrc = 0;
- }
- #endif
-
- if (p->set)
- ctlinfo.recsrc |= (1 << i);
- else
- ctlinfo.recsrc &= ~(1 << i);
-
- do_ioctl(
- SOUND_MIXER_WRITE_RECSRC,
- &ctlinfo.recsrc,
- "SOUND_MIXER_WRITE_RECSRC",
- IOC_DATA_OUT
- );
- }
-
-
- /*
- * mx_flat_btn
- * Bass/Treble Flat button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_flat_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level;
-
- ctlinfo.slinfo[SOUND_MIXER_BASS].left = 50;
- ctlinfo.slinfo[SOUND_MIXER_BASS].right = 50;
- ctlinfo.slinfo[SOUND_MIXER_TREBLE].left = 50;
- ctlinfo.slinfo[SOUND_MIXER_TREBLE].right = 50;
-
- XmScaleSetValue(widgets.sl[SOUND_MIXER_BASS].widget_l, 50);
- XmScaleSetValue(widgets.sl[SOUND_MIXER_BASS].widget_r, 50);
- XmScaleSetValue(widgets.sl[SOUND_MIXER_TREBLE].widget_l, 50);
- XmScaleSetValue(widgets.sl[SOUND_MIXER_TREBLE].widget_r, 50);
-
- level = (50 << 8) | 50;
-
- do_ioctl(
- SOUND_MIXER_WRITE_BASS,
- &level,
- "SOUND_MIXER_WRITE_BASS",
- IOC_DATA_OUT
- );
- do_ioctl(
- SOUND_MIXER_WRITE_TREBLE,
- &level,
- "SOUND_MIXER_WRITE_TREBLE",
- IOC_DATA_OUT
- );
- }
-
-
- /*
- * mx_mute_btn
- * Mute button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_mute_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level;
- XmToggleButtonCallbackStruct *p =
- (XmToggleButtonCallbackStruct *)(void *) call_data;
-
- if (ctlinfo.mute == p->set)
- /* No change */
- return;
-
- ctlinfo.mute = p->set;
-
- level = (int) p->set;
-
- #ifdef SOUND_MIXER_WRITE_MUTE
- do_ioctl(
- SOUND_MIXER_WRITE_MUTE,
- &level,
- "SOUND_MIXER_WRITE_MUTE",
- IOC_DATA_OUT
- );
- #endif
- }
-
-
- /*
- * mx_loud_btn
- * Loudness button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_loud_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level;
- XmToggleButtonCallbackStruct *p =
- (XmToggleButtonCallbackStruct *)(void *) call_data;
-
- if (ctlinfo.loudness == p->set)
- /* No change */
- return;
-
- ctlinfo.loudness = p->set;
-
- level = (int) p->set;
-
- #ifdef SOUND_MIXER_WRITE_LOUD
- do_ioctl(
- SOUND_MIXER_WRITE_LOUD,
- &level,
- "SOUND_MIXER_WRITE_LOUD",
- IOC_DATA_OUT
- );
- #endif
- }
-
-
- /*
- * mx_enhance_btn
- * Stereo enhance button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_enhance_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int level,
- i = (int)(void *) client_data;
-
- if (ctlinfo.enhance == i)
- /* No change */
- return;
-
- ctlinfo.enhance = i;
-
- /* Hack: The enhance values are hard wired */
- switch (i) {
- case 0:
- level = 0;
- break;
- case 1:
- level = 40;
- break;
- case 2:
- level = 60;
- break;
- case 3:
- level = 80;
- break;
- default:
- return;
- }
-
- #ifdef SOUND_MIXER_WRITE_ENHANCE
- do_ioctl(
- SOUND_MIXER_WRITE_ENHANCE,
- &level,
- "SOUND_MIXER_WRITE_ENHANCE",
- IOC_DATA_OUT
- );
- #endif
- }
-
-
- /*
- * mx_load
- * Load button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_load(Widget w, XtPointer client_data, XtPointer call_data)
- {
- XmString xs;
-
- /* Pop up file selection box window */
- if (!XtIsManaged(widgets.fsform)) {
- fsmode = FS_LOAD;
- xs = XmStringCreateSimple("Load Mixer Settings");
- XtVaSetValues(widgets.fsform, XmNdialogTitle, xs, NULL);
- XtManageChild(widgets.fsform);
- XmStringFree(xs);
- }
- }
-
-
- /*
- * mx_save
- * Save button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_save(Widget w, XtPointer client_data, XtPointer call_data)
- {
- XmString xs;
-
- /* Pop up file selection box window */
- if (!XtIsManaged(widgets.fsform)) {
- fsmode = FS_SAVE;
- xs = XmStringCreateSimple("Save Mixer Settings");
- XtVaSetValues(widgets.fsform, XmNdialogTitle, xs, NULL);
- XtManageChild(widgets.fsform);
- XmStringFree(xs);
- }
- }
-
-
- /*
- * mx_exit
- * Exit button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_exit(Widget w, XtPointer client_data, XtPointer call_data)
- {
- if (app_data.exitreset)
- mx_reset(w, client_data, call_data);
-
- exit_flag = TRUE;
- }
-
-
- /*
- * mx_reset
- * Reset button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_reset(Widget w, XtPointer client_data, XtPointer call_data)
- {
- if (app_data.debug)
- fprintf(errfp, "Resetting mixer\n");
-
- /* Restore start-up settings */
- ctlinfo = ctlsav; /* Structure copy */
-
- /* Update controls to match current status */
- mx_updctl(&widgets);
-
- /* Set all controls */
- mx_sethw(&widgets);
- }
-
-
- /*
- * mx_manpg
- * Man Page button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_manpg(Widget w, XtPointer client_data, XtPointer call_data)
- {
- FILE *fp;
- char *helptext = NULL,
- buf[STR_BUF_SZ * 2];
-
- if (XtIsManaged(widgets.helpform))
- return;
-
- if ((fp = fopen(app_data.helppath, "r")) == NULL) {
- /* Can't read help file on this widget */
- sprintf(buf, "Cannot open help file: %s", app_data.helppath);
- XmTextSetString(widgets.helptxt, buf);
- XtManageChild(widgets.helpform);
- return;
- }
-
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- if (buf[0] == '#')
- /* Comment */
- continue;
-
- if (helptext == NULL) {
- helptext = (char *) XtMalloc(strlen(buf) + 1);
-
- if (helptext != NULL)
- *helptext = '\0';
- }
- else {
- helptext = (char *) XtRealloc(
- helptext,
- strlen(helptext) + strlen(buf) + 1
- );
- }
-
- if (helptext == NULL) {
- fprintf(errfp, "%s: Out of memory\n", PROGNAME);
- exit_flag = TRUE;
- }
-
- strcat(helptext, buf);
- }
-
- fclose(fp);
-
- XmTextSetString(widgets.helptxt, helptext);
- XtFree(helptext);
- XtManageChild(widgets.helpform);
- }
-
-
- /*
- * mx_about
- * About button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_about(Widget w, XtPointer client_data, XtPointer call_data)
- {
- char txt[512];
- XmString xs,
- xs_progname,
- xs_desc,
- xs_info,
- xs_tmp;
-
- if (XtIsManaged(widgets.about))
- return;
-
- xs_progname = XmStringCreateLtoR(PROGNAME, CHSET1);
-
- sprintf(txt, " v%s%s PL%d\n%s\n%s\n%s\n\n",
- VERSION,
- VERSION_EXT,
- PATCHLEVEL,
- "Motif(tm) Audio Mixer",
- "Copyright (C) 1995 Ti Kan",
- "E-mail: ti@amb.org");
-
- xs_desc = XmStringCreateLtoR(txt, CHSET2);
-
- sprintf(txt, "%s %d\n\nDevice: %s\nDriver: %s\n\n%s\n%s\n",
- "Compiled with VoxWare soundcard.h version",
- SOUND_VERSION,
- app_data.demo ?
- "DEMO MODE - does not operate sound hardware" :
- app_data.device,
- drv_ver,
- "This is free software and comes with no warranty.",
- "See the GNU General Public License for details.");
-
- xs_info = XmStringCreateLtoR(txt, CHSET3);
-
- /* Set the dialog box message */
- xs_tmp = XmStringConcat(xs_progname, xs_desc);
- xs = XmStringConcat(xs_tmp, xs_info);
-
- XtVaSetValues(widgets.about, XmNmessageString, xs, NULL);
- XmStringFree(xs_progname);
- XmStringFree(xs_desc);
- XmStringFree(xs_info);
- XmStringFree(xs_tmp);
- XmStringFree(xs);
-
- /* Pop up the about dialog box */
- XtManageChild(widgets.about);
- }
-
-
- /*
- * mx_fsok_btn
- * File selection box OK button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_fsok_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- XmFileSelectionBoxCallbackStruct *p =
- (XmFileSelectionBoxCallbackStruct *)(void *) call_data;
- struct stat stbuf;
- char *file,
- msg[256];
-
- if (!XmStringGetLtoR(p->value, XmSTRING_DEFAULT_CHARSET, &file) ||
- file == NULL) {
- XBell(XtDisplay(w), 50);
- return;
- }
-
- if (stat(file, &stbuf) < 0) {
- if (errno != ENOENT) {
- sprintf(msg, "Invalid mixer settings file:\n%s",
- file);
- mx_warning(msg);
- return;
- }
- }
- else {
- switch (stbuf.st_mode & S_IFMT) {
- case S_IFREG:
- break;
- default:
- sprintf(msg, "Invalid mixer settings file:\n%s",
- file);
- mx_warning(msg);
- return;
- }
- }
-
- switch (fsmode) {
- case FS_LOAD:
- if (!mx_readfile(file)) {
- sprintf(msg, "Cannot read mixer settings file:\n%s",
- file);
- mx_warning(msg);
- return;
- }
- break;
- case FS_SAVE:
- if (!mx_writefile(file)) {
- sprintf(msg, "Cannot write mixer settings file:\n%s",
- file);
- mx_warning(msg);
- return;
- }
- break;
- default:
- XBell(XtDisplay(w), 50);
- return;
- }
-
- /* Pop down file selection box window */
- if (XtIsManaged(widgets.fsform))
- XtUnmanageChild(widgets.fsform);
- }
-
-
- /*
- * mx_fscancel_btn
- * File selection box Cancel button callback routine.
- */
- /*ARGSUSED*/
- void
- mx_fscancel_btn(Widget w, XtPointer client_data, XtPointer call_data)
- {
- /* Pop down file selection box window */
- if (XtIsManaged(widgets.fsform))
- XtUnmanageChild(widgets.fsform);
- }
-
-
- /*
- * mx_focuschg
- * Main window focus change callback routine.
- */
- /*ARGSUSED*/
- void
- mx_focuschg(Widget w, XtPointer client_data, XtPointer call_data)
- {
- XmAnyCallbackStruct *p = (XmAnyCallbackStruct *)(void *) call_data;
- Widget form = (Widget) client_data;
-
- if (p->reason != XmCR_FOCUS || form == (Widget) NULL)
- return;
-
- /* Query hardware mixer settings */
- mx_queryhw(&widgets);
-
- /* Update screen controls */
- mx_updctl(&widgets);
- }
-
-
- /**************** ^^ Callback routines ^^ ****************/
-
-