#include #include #include #include #include #include #define VNC_INTERNAL_SPKR 0x01 //the sw mute on/off control bit #define VNC_INTERNAL_MIC 0x10 //the hw internal/handset mic bit #define VNC_LINE_OUT_MUTE 0x40 //the sw mute of line-out bit #define VNC_HANDSET_SW_ONLY 0x80 //software in total control of handset! int mixer_fd = -1; unsigned supported; int source; char **p; /* parameters */ #define ALL_OPT "all" #define MASTER_OPT "master" #define DSP_OPT "dsp" #define MIC_OPT "mic" #define FM_OPT "fm" #define SOURCE_OPT "source" #define LINE_OPT "line" #define PHONE_OPT "phone" //LINE1 is our analog phone #define SPKR_OPT "spkr" #define RECLEV_OPT "reclev" #define HELP_OPT "help" #define RECMON_OPT "recmon" #define PRIVATE_OPT "private" #define NOT_CMP -2 #define GET -1 #define SET 0 #define LEFT 0x0001 #define RIGHT 0x0100 #define LEFT_MASK 0x00ff #define RIGHT_MASK 0xff00 int str_cmp (char *pattern, char *s) { int i, j, k, l; if(!s[0]) /* if empty string - display all */ return GET; if(s[0] == '-') s++; /* skip over the leading - */ for (i = 0; (pattern[i]) && (s[i]) && (pattern[i] == s[i]); i++); if (pattern[i]) return NOT_CMP; /* not this one */ if (!s[i]) return GET; /* if just keyword - get it */ if (!s[i + 1]) return GET; /* if keyword= - display only */ if (s[i + 1] == '(') /* we got stereo */ { for (k = i + 1; s[k] && (s[k] != ','); k++); if (!s[k]) return GET; s[k] = 0; for (l = k + 1; s[k] && (s[k] != ')'); k++); s[k] = 0; j = strtol((s + i + 2), NULL, 0); l = strtol((s + k + 1), NULL, 0); return LEFT * j + RIGHT * l; } else //no stereo settings { j = strtol((s + i + 1), NULL, 0); return (LEFT + RIGHT) * j; } } void get_source (void) { source = 0; if (ioctl (mixer_fd, SOUND_MIXER_READ_RECSRC, &source) == -1) perror ("Error reading mixer recording source"); printf ("Record input:"); if (source == 0 || source == 1 << SOUND_MIXER_SPEAKER) printf ("\tNot connected\n"); else { if (source & ( 1 << SOUND_MIXER_MIC)) { if (source & (1 << SOUND_MIXER_SPEAKER)) printf ("\tInternal microphone "); else printf ("\tHandset Microphone "); } if (source & ( 1 << SOUND_MIXER_LINE)) printf ("\tLine "); if (source & (1 << SOUND_MIXER_LINE1)) printf ("\tAnalog phone "); printf("\n"); } } void set_source (int id) { source = 0; if (ioctl (mixer_fd, SOUND_MIXER_READ_RECSRC, &source) == -1) perror ("Error reading mixer recording source"); source ^= 1 << id; if (ioctl (mixer_fd, SOUND_MIXER_WRITE_RECSRC, &source) < 0) perror ("Mixer.set_source()"); } int check_source (char *s) { int k; k = str_cmp (SOURCE_OPT, s); switch (k) { case GET: get_source (); return 1; case NOT_CMP: return 0; default: // set_source(SOUND_MIXER_LINE); set_source ((k) & 0x0F); //convert from "stereo" to a number return 1; } } void set_volume (int mixer_id, int volume) { if (ioctl (mixer_fd, MIXER_WRITE (mixer_id), &volume) < 0) perror ("Mixer.set_mixer()"); } int get_volume (int mixer_id) { int volume; if (ioctl (mixer_fd, MIXER_READ (mixer_id), &volume) < 0) { perror ("Mixer.get_volume()"); return 0; } return volume; } char * sget_volume (int mixer_id) { char *s; int v; v = get_volume (mixer_id); s = NULL; s = calloc (100, sizeof (char)); if (s == NULL) { perror ("Mixer.sget_volume()"); return "ERROR"; } if ((v & LEFT_MASK) == (v & RIGHT_MASK) >> 8) { sprintf (s, "\t%d", (v & LEFT_MASK)); } else { sprintf (s, "\t(L=%d R=%d)", (v & LEFT_MASK), (v & RIGHT_MASK) >> 8); } return s; } int check_master (char *s) { int k; if ((supported & SOUND_MASK_VOLUME) == 0) return 0; k = str_cmp (MASTER_OPT, s); switch (k) { case GET: printf ("Master volume %s\n", sget_volume (SOUND_MIXER_VOLUME)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_VOLUME, k); return 1; } } int check_mic (char *s) { int k; if ((supported & SOUND_MASK_MIC) == 0) return 0; k = str_cmp (MIC_OPT, s); switch (k) { case GET: printf ("Mic/handset %s\n", sget_volume (SOUND_MIXER_MIC)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_MIC, k); return 1; } } int check_reclev (char *s) { int k; if ((supported & SOUND_MASK_RECLEV) == 0) return 0; k = str_cmp (RECLEV_OPT, s); switch (k) { case GET: printf ("Record volume %s\n", sget_volume (SOUND_MIXER_RECLEV)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_RECLEV, k); return 1; } } int check_dsp (char *s) { int k; if ((supported & SOUND_MASK_PCM) == 0) return 0; k = str_cmp (DSP_OPT, s); switch (k) { case GET: printf ("DSP volume %s\n", sget_volume (SOUND_MIXER_PCM)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_PCM, k); return 1; } } int check_fm (char *s) { int k; if ((supported & SOUND_MASK_SYNTH) == 0) return 0; k = str_cmp (FM_OPT, s); switch (k) { case GET: printf ("FM volume %s\n", sget_volume (SOUND_MIXER_SYNTH)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_SYNTH, k); return 1; } } int check_recmon (char *s) { int k; if ((supported & SOUND_MASK_IMIX) == 0) return 0; k = str_cmp (RECMON_OPT, s); switch (k) { case GET: printf ("RecMon volume %s\n", sget_volume (SOUND_MIXER_IMIX)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_IMIX, k); return 1; } } int check_private (char *s) { int k, mixprivate; // if ((supported & SOUND_MASK_IMIX) == 0) // return 0; k = str_cmp (PRIVATE_OPT, s); switch (k) { case GET: mixprivate = 0; if (ioctl (mixer_fd, MIXER_READ (SOUND_MIXER_PRIVATE2), &mixprivate) < 0) { printf("Error reading the private mixer control...\n"); return 0; } printf ("Private [0x%X]", mixprivate); if (mixprivate & VNC_INTERNAL_SPKR) printf("\tInt spkr OFF"); else printf("\tInt spkr ON"); if (mixprivate & VNC_INTERNAL_MIC) printf(" Int mic ON"); else printf(" Hset mic ON"); if (mixprivate & VNC_LINE_OUT_MUTE) printf(" Line out OFF"); else printf(" Line out ON"); if (mixprivate & VNC_HANDSET_SW_ONLY) printf(" Hset detection OFF\n"); else printf(" Hset detection ON\n"); return 1; case NOT_CMP: return 0; default: mixprivate = k & 0xFF; printf ("Setting PRIVATE to 0x%X.\n", mixprivate); if (ioctl (mixer_fd, MIXER_WRITE (SOUND_MIXER_PRIVATE1), &mixprivate) < 0) { printf("Error setting the private mixer control...\n"); return(0); } return 1; } } #if 0 int check_line (char *s) { int k; if ((supported & SOUND_MASK_LINE) == 0) return 0; k = str_cmp (LINE_OPT, s); switch (k) { case GET: printf ("LINE recmon volume %s\n", sget_volume (SOUND_MIXER_LINE)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_LINE, k); return 1; } } int check_phone (char *s) { int k; if ((supported & SOUND_MASK_LINE1) == 0) return 0; k = str_cmp (PHONE_OPT, s); switch (k) { case GET: printf ("PHONE recmon volume %s\n", sget_volume (SOUND_MIXER_LINE1)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_LINE1, k); return 1; } } int check_spkr (char *s) { int k; if ((supported & SOUND_MASK_SPEAKER) == 0) return 0; k = str_cmp (SPKR_OPT, s); switch (k) { case GET: printf ("SPKR (built-in mic) volume %s\n", sget_volume (SOUND_MIXER_SPEAKER)); return 1; case NOT_CMP: return 0; default: set_volume (SOUND_MIXER_SPEAKER, k); return 1; } } #endif void check_all (char *s) { check_master (s); check_dsp (s); check_fm (s); // check_line (strdup (s)); // check_phone (strdup (s)); // check_spkr(strdup(s)); check_mic (s); check_recmon (s); check_reclev (s); check_source (s); check_private (s); } void usage (char *s) { printf ("SYNOPSIS\n"); printf ("\t%s [options]\n\n", s); printf ("OPTIONS\n"); // printf("\t-all\t\tshow all settings\n"); printf ("\t-master=n\tset master volume to n\n"); printf ("\t-dsp=n\t\tset dsp synth volume to n\n"); printf ("\t-mic=n\t\tset mic preamp to n\n"); printf ("\t-fm=n\t\tset fm synth volume to n\n"); printf ("\t-source={6,7,14} set source to {Line, Mic/Handset, Phone} (XOR)\n"); // printf ("\t-line=n\t\tset line volume to n\n"); // printf ("\t-phone=n\t\tset phone volume to n\n"); // printf("\t-spkr=n\t\tset speaker volume to n\n"); printf ("\t-reclev=n\tset recording level to n\n"); printf ("\t-recmon=n\tset recording monitor level to n\n"); printf ("\t-help\t\tshow this screen\n"); printf ("\tuse volume=(left,right) for stereo setting.\n"); } int main (int argc, char *argv[]) { int k; mixer_fd = open ("/dev/mixer", O_RDWR); if (mixer_fd < 0) { perror ("Can not open mixer device!"); exit (-1); } if (ioctl (mixer_fd, SOUND_MIXER_READ_DEVMASK, &supported) < 0) supported = 0xffff; if (argc == 1) { check_all (""); printf ("\n`%s -help\' for more information.\n", argv[0]); close (mixer_fd); exit (0); } if (strcmp (HELP_OPT, argv[1]) == 0) { usage (argv[0]); close (mixer_fd); exit (0); } for (k = 1; k < argc; k++) { // printf("Mixer: checking arg: %s.\n",argv[k]); check_all (argv[k]); } close (mixer_fd); exit (0); }