📄 common.c
字号:
/* $Aumix: aumix/src/common.c,v 1.9 2002/10/29 21:27:51 trevor Exp $ * * aumix: adjust audio mixer * copyright (c) 1993, 1996-2002 the authors--see AUTHORS file * * This file is part of aumix. * * Aumix 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. * * Aumix 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 * aumix; if not, write to the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307, USA. */#include "common.h"#ifdef HAVE_CURSES#include "curses.h"#include "gpm-xterm.h"#endif /* HAVE_CURSES */#if defined (HAVE_GTK) || defined (HAVE_GTK1)#include "gtk.h"#endif /* HAVE_GTK || HAVE_GTK1 */#include "interactive.h"FILE *OpenDefaultFile(char *mode);FILE *setfile;char *save_filename = NULL; /* name of file for saved settings */char *device_filename = "/dev/mixer"; /* name of mixer device file */unsigned short setfile_opened = FALSE, setfile_write_perm = FALSE, setfile_read_perm = FALSE;int current_dev = 0, mixer_fd = -1, mutelevel[SOUND_MIXER_NRDEVICES], devmask = 0, recmask = 0, recsrc = 0, stereodevs = 0, mutestate = 0, interactive = FALSE;#ifdef USE_OWN_LABELS/* This is to ease translation--don't use if this copy of aumix is very old. * These labels correspond to the soundcard.h from Linux 2.3.12 or FreeBSD * 3.2-19990713-STABLE. The point of having our own copy of these * macros is to make it possible to include translations of them. * The danger is that they won't always correspond to the sound * driver in the kernel. *//* There's probably not enough left to copyright, but... * Copyright by Hannu Savolainen 1993 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */char *dev_label[SOUND_MIXER_NRDEVICES] ={ LOCAL_TEXT_NOOP("Volume "), LOCAL_TEXT_NOOP("Bass "), LOCAL_TEXT_NOOP("Treble "), LOCAL_TEXT_NOOP("Synth "), LOCAL_TEXT_NOOP("PCM "), LOCAL_TEXT_NOOP("Speaker "), LOCAL_TEXT_NOOP("Line "), LOCAL_TEXT_NOOP("Mic "), LOCAL_TEXT_NOOP("CD "), LOCAL_TEXT_NOOP("Mix "), LOCAL_TEXT_NOOP("PCM 2 "), LOCAL_TEXT_NOOP("Record "), LOCAL_TEXT_NOOP("Input "), LOCAL_TEXT_NOOP("Output "), LOCAL_TEXT_NOOP("Line 1 "), LOCAL_TEXT_NOOP("Line 2 "), LOCAL_TEXT_NOOP("Line 3 "), LOCAL_TEXT_NOOP("Digital1"), LOCAL_TEXT_NOOP("Digital2"), LOCAL_TEXT_NOOP("Digital3"), LOCAL_TEXT_NOOP("Phone In"), LOCAL_TEXT_NOOP("PhoneOut"), LOCAL_TEXT_NOOP("Video "), LOCAL_TEXT_NOOP("Radio "), LOCAL_TEXT_NOOP("Monitor ")};#elsechar *dev_label[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;#endif /* USE_OWN_LABELS */char *dev_name[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;/* An index into this array gives the device number for the corresponding command-line option. */char *moptindx = "vbtswplmcxWrio123";char *mopt;char *scheme_name;extern char *optarg;int usage_ok = 1;int main(int argc, char *argv[]){ int optn, ii;#ifdef HAVE_CURSES int setcolors = FALSE;#endif /* HAVE_CURSES */ /* Internationalization */#ifdef HAVE_NLS I18nInitialize();#endif /* HAVE_NLS */ interactive = FALSE;/* Get options from the command line. Using numbers as options is deprecated, but we do it anyway because it makes sense for line1, line2 and line3. */ while (TRUE) { optn = getopt(argc, argv, "hILqSd:f:C:v:b:t:s:w:P:p:l:m:c:x:W:R:r:i:o:1:2:3:"); if (optn == -1) break;/* Funny, strchr() returns a pointer to char, according to the man page, but without this cast egcs warns "assignment makes pointer from integer without a cast". */ if ((mopt = (char *) strchr(moptindx, optn))) { usage_ok = 0; if (mixer_fd == -1) ErrorExitWarn(InitializeMixer(device_filename), 'e'); ErrorExitWarn(SetShowNoninter(mopt - moptindx), 'e'); } else { usage_ok = 0; switch (optn) { case 'q': /* query */ optarg = "q"; if (mixer_fd == -1) ErrorExitWarn(InitializeMixer(device_filename), 'e'); for (ii = 0; ii < SOUND_MIXER_NRDEVICES; ii++) { if ((1 << ii) & (devmask | recmask)) ErrorExitWarn(SetShowNoninter(ii), 'e'); } break; case 'd': /* User specified the device file. */ device_filename = strdup(optarg); ErrorExitWarn(InitializeMixer(device_filename), 'e'); break; case 'f': /* User specified the save file. */ save_filename = strdup(optarg); break;#ifdef HAVE_CURSES /* no color schemes for GTK+ */ case 'C': /* User specified the color scheme. */ scheme_name = strdup(optarg); setcolors = TRUE; interactive = IN_CURSES; break;#endif /* HAVE_CURSES */ case 'S': /* Save to file. */ if (mixer_fd == -1) ErrorExitWarn(InitializeMixer(device_filename), 'e'); ErrorExitWarn(SaveSettings(), 'e'); break; case 'L': /* Load from file. */ if (mixer_fd == -1) ErrorExitWarn(InitializeMixer(device_filename), 'e'); ErrorExitWarn(LoadSettings(), 'e'); break;#if defined (HAVE_CURSES) || defined (HAVE_GTK) || defined (HAVE_GTK1) case 'I': /* User asked for interactive mode. */ if (!interactive) interactive = IN_ANY; break;#endif /* HAVE_CURSES || HAVE_GTK || HAVE_GTK1 */ case 'h': /* Show help. */ Usage(EXIT_SUCCESS); break; default: /* Show help. */ Usage(EXIT_FAILURE); } } }#if defined (HAVE_CURSES) || defined (HAVE_GTK) || defined (HAVE_GTK1)/* Be interactive if no options were given. */ if (!interactive && argc <= 1) interactive = IN_ANY;/* By now we've decided whether to go interactive. The -C (color scheme) option implies curses, even if GTK is available.*/ if (interactive == IN_ANY) {#if defined (HAVE_GTK) || defined (HAVE_GTK1) if (getenv("DISPLAY") != NULL) interactive = IN_GTK;#endif /* HAVE_GTK || HAVE_GTK1 */#ifdef HAVE_CURSES if (interactive == IN_ANY) interactive = IN_CURSES;#endif /* HAVE_CURSES */ }#endif /* HAVE_CURSES || HAVE_GTK || HAVE_GTK1 *//* By now, interactive is not IN_ANY. It is IN_GTK only if DISPLAY is set, and otherwise defaults to IN_CURSES. Since interactive contains the right value, it should not be changed any more.*/#if defined (HAVE_GTK) || defined (HAVE_GTK1)/* GTK+ stuff */ if (interactive == IN_GTK) {#ifndef DUMMY_MIXER if ((mixer_fd = open(device_filename, O_RDWR)) < 0) return EOPENMIX;#endif /* DUMMY_MIXER */ ErrorExitWarn(MixerStatus(), 'e'); if (!devmask) return EFINDDEVICE; gtk_init(&argc, &argv); InitScreenGTK(); gtk_main(); return 0; }#endif /* HAVE_GTK || HAVE_GTK1 */ if (!interactive) { if (usage_ok && optn == -1) Usage(EXIT_SUCCESS); } if (mixer_fd == -1) ErrorExitWarn(InitializeMixer(device_filename), 'e');#if HAVE_CURSES if (interactive == IN_CURSES) { InitCurses(); if (setcolors == TRUE) ErrorExitWarn(InitColors(scheme_name), 'e'); else SetDefaultColors(); InitScreen(); StartMouse(); Inter(); Gpm_Close();#endif /* HAVE_CURSES */ close(mixer_fd);#if HAVE_CURSES CloseScreen(); }#endif /* HAVE_CURSES */ exit(EXIT_SUCCESS);}void ErrorExitWarn(int error, int mode){/* Print error messages. If mode is "e", bail out. */ char string[80]; const char *errorlist[] = {LOCAL_TEXT_NOOP("aumix: error opening mixer"), LOCAL_TEXT_NOOP("aumix: no device found"), " aumix: SOUND_MIXER_READ_DEVMASK", " aumix: SOUND_MIXER_READ_RECMASK", "aumix: SOUND_MIXER_READ_RECSRC", "aumix: SOUND_MIXER_READ_STEREODEVS", "aumix: SOUND_MIXER_WRITE_RECSRC", "aumix: MIXER_READ", "aumix: MIXER_WRITE", LOCAL_TEXT_NOOP("aumix: mixer not open"), LOCAL_TEXT_NOOP("aumix: unable to open settings file")}; if (!error) return;#if HAVE_CURSES if (mode == 'e') /* exit */ CloseScreen();#endif /* HAVE_CURSES */ if (error > 12) { sprintf(string, LOCAL_TEXT("aumix: unknown error %i"), error); fprintf(stderr, string); } else if (error > 0) { fprintf(stderr, LOCAL_TEXT(errorlist[error - 1])); } fprintf(stderr, "\n"); if (mode == 'e') /* exit */ exit(EXIT_FAILURE); else return; /* warn */}int LoadSettings(void){/* Read settings from file. We depend on the 'mixer' file descriptor having been set (and not clobbered) before entering this routine. */ char textline[80], tmpstring[80], recplay; int tmp, ii, left, right; setfile = OpenDefaultFile("r"); if (setfile == NULL) return EFILE; while (fgets(textline, 80, setfile) != NULL) { (void) sscanf(textline, "%[^:;, ]%*[:;, ]%10u%*[:;, ]%3u%*[:;, ]%1c\n", tmpstring, &left, &right, &recplay); if (!strcmp(tmpstring, "wait")) { if (!interactive) printf(LOCAL_TEXT("%i ms wait\n"), left); usleep(left * 1000); } else { for (ii = 0; ii < SOUND_MIXER_NRDEVICES; ii++) {/* Cycle through names of channels, looking for matches. */ if (!strcmp(tmpstring, dev_name[ii])) { left = (left > MAXLEVEL) ? MAXLEVEL : left; left = (left < 0) ? 0 : left; right = (right > MAXLEVEL) ? MAXLEVEL : right; right = (right < 0) ? 0 : right; tmp = left + (right << 8); if ((SOUND_IOCTL(mixer_fd, MIXER_WRITE(ii), &tmp) == -1) && !interactive) { printf("%s %s\n", dev_name[ii], LOCAL_TEXT("not set")); } else { if (!interactive) printf("%s %s %i, %i", dev_name[ii], LOCAL_TEXT("set to"), left, right); if ((1 << ii) & recmask) { ErrorExitWarn(ReadRecSrc(), 'e'); recsrc = (recplay == 'R') ? recsrc | (1 << ii) : recsrc & ~(1 << ii); ErrorExitWarn(WriteRecSrc(), 'e'); if (!interactive) printf(", %c", recplay); } if (!interactive) printf("\n"); } } } } } fclose(setfile); return 0;}int SaveSettings(void){/* Write settings to file. We depend on the 'mixer' file descriptor having been set (and not clobbered) before entering this routine. */ int tmp, ii; setfile = OpenDefaultFile("w"); if (setfile == NULL) return EFILE; ErrorExitWarn(ReadRecSrc(), 'e'); for (ii = 0; ii < SOUND_MIXER_NRDEVICES; ii++) { if ((1 << ii) & (devmask | recmask)) { ErrorExitWarn(ReadLevel(ii, &tmp), 'e'); fprintf(setfile, "%s:%i:%i:%c\n", dev_name[ii], (tmp & 0xFF), ((tmp >> 8) & 0xFF), ((1 << ii) & recsrc ? 'R' : 'P')); } } if (fclose(setfile)) return EFILE; return 0;}int InitializeMixer(char *device_filename){/* Initialize the mixer. Global: mixer_fd = mixer file descriptor reference number Return values: Success: 0 Failure: EOPENMIX trouble opening mixer device EFINDDEVICE no device found EREADDEV SOUND_MIXER_READ_DEVMASK EREADRECMASK SOUND_MIXER_READ_RECMASK EREADRECSRC SOUND_MIXER_READ_RECSRC EREADSTEREO SOUND_MIXER_READ_STEREODEVS */#ifdef HAVE_ALSA AlsaUnmute();#endif /* HAVE_ALSA */#ifndef DUMMY_MIXER if ((mixer_fd = open(device_filename, O_RDWR)) < 0) return EOPENMIX;#endif /* DUMMY_MIXER */ ErrorExitWarn(MixerStatus(), 'e'); if (!devmask)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -