From 88cdd83d0f7277f45c4ce94c32c98e5fc2d76001 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 15 Feb 1999 15:42:34 +0000 Subject: [PATCH] Changes for record volume... --- alsactl/alsactl.h | 1 + alsactl/alsactl_lexer.l | 5 ++- alsactl/alsactl_parser.y | 22 +++++++++++ alsactl/setup.c | 47 +++++++++++++++++------- alsamixer/alsamixer.1 | 2 + alsamixer/alsamixer.c | 79 +++++++++++++++++++++++++++++++++++----- 6 files changed, 132 insertions(+), 24 deletions(-) diff --git a/alsactl/alsactl.h b/alsactl/alsactl.h index 6ed0b00..e17f9ef 100644 --- a/alsactl/alsactl.h +++ b/alsactl/alsactl.h @@ -47,6 +47,7 @@ struct mixer_channel { int change; snd_mixer_channel_info_t i; snd_mixer_channel_t c; + snd_mixer_channel_t cr; struct mixer_channel *next; }; diff --git a/alsactl/alsactl_lexer.l b/alsactl/alsactl_lexer.l index 8b39d3b..a0e3712 100644 --- a/alsactl/alsactl_lexer.l +++ b/alsactl/alsactl_lexer.l @@ -38,6 +38,7 @@ int linecount; "{"|"}" return yytext[0]; "("|")" return yytext[0]; +"["|"]" return yytext[0]; ")"[ \t]*"{" return L_DOUBLE1; "," return yytext[0]; @@ -108,9 +109,9 @@ true|on|yes return L_TRUE; \'[^\']*\' { yytext[ strlen( yytext ) - 1 ] = 0; yylval.s_value = strdup( &yytext[ 1 ] ); return L_STRING; } -[a-z0-9/\~@-_\+=:\.]+ { yylval.s_value = strdup( yytext ); +[a-z0-9/\~@-Za-z_\+=:\.]+ { yylval.s_value = strdup( yytext ); return L_STRING; } -$[a-z0-9/\~@-_\+=:\.]+ { yylval.s_value = strdup( getenv( &yytext[ 1 ] ) ); +$[a-z0-9/\~@-Za-z_\+=:\.]+ { yylval.s_value = strdup( getenv( &yytext[ 1 ] ) ); return L_STRING; } /* comments & whitespaces */ diff --git a/alsactl/alsactl_parser.y b/alsactl/alsactl_parser.y index a0bd765..5948eed 100644 --- a/alsactl/alsactl_parser.y +++ b/alsactl/alsactl_parser.y @@ -43,6 +43,7 @@ static void select_rawmidi(char *name); static void select_mixer_channel(char *name); static void set_mixer_channel(int left, int right); +static void set_mixer_channel_record(int left, int right); static void set_mixer_channel_flags(unsigned int mask, unsigned int flags); static void set_mixer_channel_end(void); @@ -162,6 +163,7 @@ xmchls : xmchl ; xmchl : L_INTEGER { set_mixer_channel( $1, -1 ); } + | '[' L_INTEGER ']' { set_mixer_channel_record( $2, -1 ); } | L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE_LEFT, SND_MIXER_FLG_MUTE_LEFT ); } | L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD_LEFT, SND_MIXER_FLG_RECORD_LEFT ); } | L_SWOUT { set_mixer_channel_flags( SND_MIXER_FLG_LTOR_OUT, SND_MIXER_FLG_LTOR_OUT ); } @@ -174,6 +176,7 @@ xmchrs : xmchr ; xmchr : L_INTEGER { set_mixer_channel( -1, $1 ); } + | '[' L_INTEGER ']' { set_mixer_channel_record( -1, $2 ); } | L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE_RIGHT, SND_MIXER_FLG_MUTE_RIGHT ); } | L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD_RIGHT, SND_MIXER_FLG_RECORD_RIGHT ); } | L_SWOUT { set_mixer_channel_flags( SND_MIXER_FLG_RTOL_OUT, SND_MIXER_FLG_RTOL_OUT ); } @@ -186,6 +189,7 @@ xmchs : xmch ; xmch : L_INTEGER { set_mixer_channel( $1, $1 ); } + | '[' L_INTEGER ']' { set_mixer_channel_record( $2, $2 ); } | L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE, SND_MIXER_FLG_MUTE ); } | L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD, SND_MIXER_FLG_RECORD ); } | error { yyerror( "unknown keyword in mono channel section..." ); } @@ -417,6 +421,24 @@ static void set_mixer_channel(int left, int right) } } +static void set_mixer_channel_record(int left, int right) +{ + if (left >= 0) { + if (Xmixerchannel->i.min > left || Xmixerchannel->i.max < left) + yyerror("Value out of range (%i-%i)...", Xmixerchannel->i.min, Xmixerchannel->i.max); + if (Xmixerchannel->cr.left != left) + Xmixerchannel->change = 1; + Xmixerchannel->cr.left = left; + } + if (right >= 0) { + if (Xmixerchannel->i.min > right || Xmixerchannel->i.max < right) + yyerror("Value out of range (%i-%i)...", Xmixerchannel->i.min, Xmixerchannel->i.max); + if (Xmixerchannel->cr.right != right) + Xmixerchannel->change = 1; + Xmixerchannel->cr.right = right; + } +} + static void set_mixer_channel_flags(unsigned int mask, unsigned int flags) { Xmixerchannelflags &= ~mask; diff --git a/alsactl/setup.c b/alsactl/setup.c index 0218d0c..3742017 100644 --- a/alsactl/setup.c +++ b/alsactl/setup.c @@ -360,6 +360,12 @@ int soundcard_setup_collect(int cardno) error("MIXER channel read error (%s) - skipping", snd_strerror(err)); break; } + if ((mixerchannel->i.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) && + (err = snd_mixer_channel_record_read(mhandle, idx, &mixerchannel->cr)) < 0) { + free(mixerchannel); + error("MIXER channel record read error (%s) - skipping", snd_strerror(err)); + break; + } if (!mixerchannelprev) { mixer->channels = mixerchannel; } else { @@ -645,7 +651,7 @@ static void soundcard_setup_write_switch(FILE * out, int interface, const unsign } -static void soundcard_setup_write_mixer_channel(FILE * out, snd_mixer_channel_info_t * info, snd_mixer_channel_t * channel) +static void soundcard_setup_write_mixer_channel(FILE * out, snd_mixer_channel_info_t * info, snd_mixer_channel_t * channel, snd_mixer_channel_t * record_channel) { fprintf(out, " ; Capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s.\n", info->caps & SND_MIXER_CINFO_CAP_RECORD ? " record" : "", @@ -660,27 +666,39 @@ static void soundcard_setup_write_mixer_channel(FILE * out, snd_mixer_channel_in info->caps & SND_MIXER_CINFO_CAP_SWITCH_OUT ? " switch-out" : "", info->caps & SND_MIXER_CINFO_CAP_LTOR_IN ? " ltor-in" : "", info->caps & SND_MIXER_CINFO_CAP_RTOL_IN ? " rtol-in" : "", - info->caps & SND_MIXER_CINFO_CAP_RECORDBYMUTE ? " record-by-mute" : ""); + info->caps & SND_MIXER_CINFO_CAP_RECORDVOLUME ? " record-volume" : ""); fprintf(out, " ; Accepted channel range is from %i to %i.\n", info->min, info->max); fprintf(out, " channel( \"%s\", ", info->name); if (info->caps & SND_MIXER_CINFO_CAP_STEREO) { - fprintf(out, "stereo( %i%s%s%s%s, %i%s%s%s%s )", + char bufl[16] = ""; + char bufr[16] = ""; + if (info->caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) { + sprintf(bufl, " [%i]", record_channel->left); + sprintf(bufr, " [%i]", record_channel->right); + } + fprintf(out, "stereo( %i%s%s%s%s%s, %i%s%s%s%s%s )", channel->left, - channel->flags & SND_MIXER_FLG_MUTE_LEFT ? " mute" : "", + channel->flags & SND_MIXER_FLG_MUTE_LEFT ? " mute" : "", channel->flags & SND_MIXER_FLG_RECORD_LEFT ? " record" : "", - channel->flags & SND_MIXER_FLG_LTOR_OUT ? " swout" : "", - channel->flags & SND_MIXER_FLG_LTOR_IN ? " swin" : "", + bufl, + channel->flags & SND_MIXER_FLG_LTOR_OUT ? " swout" : "", + channel->flags & SND_MIXER_FLG_LTOR_IN ? " swin" : "", channel->right, - channel->flags & SND_MIXER_FLG_MUTE_RIGHT ? " mute" : "", + channel->flags & SND_MIXER_FLG_MUTE_RIGHT ? " mute" : "", channel->flags & SND_MIXER_FLG_RECORD_RIGHT ? " record" : "", - channel->flags & SND_MIXER_FLG_RTOL_OUT ? " swout" : "", - channel->flags & SND_MIXER_FLG_RTOL_IN ? " swin" : "" + bufr, + channel->flags & SND_MIXER_FLG_RTOL_OUT ? " swout" : "", + channel->flags & SND_MIXER_FLG_RTOL_IN ? " swin" : "" ); } else { - fprintf(out, "mono( %i%s%s )", + char buf[16] = ""; + if (info->caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) + sprintf(buf, " [%i]", (record_channel->left+record_channel->right) /2); + fprintf(out, "mono( %i%s%s%s )", (channel->left + channel->right) / 2, - channel->flags & SND_MIXER_FLG_MUTE ? " mute" : "", - channel->flags & SND_MIXER_FLG_RECORD ? " record" : "" + channel->flags & SND_MIXER_FLG_MUTE ? " mute" : "", + channel->flags & SND_MIXER_FLG_RECORD ? " record" : "", + buf ); } fprintf(out, " )\n"); @@ -717,7 +735,7 @@ int soundcard_setup_write(const char *cfgfile) for (mixer = first->mixers; mixer; mixer = mixer->next) { fprintf(out, " mixer( \"%s\" ) {\n", mixer->info.name); for (mixerchannel = mixer->channels; mixerchannel; mixerchannel = mixerchannel->next) - soundcard_setup_write_mixer_channel(out, &mixerchannel->i, &mixerchannel->c); + soundcard_setup_write_mixer_channel(out, &mixerchannel->i, &mixerchannel->c, &mixerchannel->cr); for (mixersw = mixer->switches; mixersw; mixersw = mixersw->next) soundcard_setup_write_switch(out, SND_INTERFACE_MIXER, mixersw->s.name, mixersw->s.type, mixersw->s.low, mixersw->s.high, (void *) (&mixersw->s.value)); fprintf(out, " }\n"); @@ -825,6 +843,9 @@ int soundcard_setup_process(int cardno) if (!soundcard_open_mix(&mixhandle, soundcard, mixer)) { if ((err = snd_mixer_channel_write(mixhandle, channel->no, &channel->c)) < 0) error("Mixer channel '%s' write error: %s", channel->i.name, snd_strerror(err)); + if ((channel->i.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) && + (err = snd_mixer_channel_record_write(mixhandle, channel->no, &channel->cr)) < 0) + error("Mixer channel '%s' record write error: %s", channel->i.name, snd_strerror(err)); } if (mixhandle) { snd_mixer_close(mixhandle); diff --git a/alsamixer/alsamixer.1 b/alsamixer/alsamixer.1 index 6c4f9aa..4d2a6a5 100644 --- a/alsamixer/alsamixer.1 +++ b/alsamixer/alsamixer.1 @@ -67,6 +67,8 @@ mute left and right independently by using \fI,\fP and \fI.\fP respectively. removed from the sources used for recording. This only works for valid input channels, of course. +\fIR\fP toggle display of playback or record mixer. + \fIL\fP re-draws the screen. \fITAB\fP toggles the mode for volume display. See description for the diff --git a/alsamixer/alsamixer.c b/alsamixer/alsamixer.c index 8b7e6f5..32186ca 100644 --- a/alsamixer/alsamixer.c +++ b/alsamixer/alsamixer.c @@ -97,6 +97,8 @@ static int mixer_first_vis_channel = 0; static int mixer_focus_channel = 0; static int mixer_exact = 0; +static int mixer_record_volumes = 0; + static int mixer_lvolume_delta = 0; static int mixer_rvolume_delta = 0; static int mixer_balance_volumes = 0; @@ -301,9 +303,12 @@ static void mixer_update_cbar(int channel_index) {0}; snd_mixer_channel_t cdata = {0}; + snd_mixer_channel_t crdata = + {0}; int vleft, vright; int x, y, i; + int channel_record_volume; /* set specified EXACT mode */ @@ -314,6 +319,7 @@ static void mixer_update_cbar(int channel_index) */ if (snd_mixer_channel_info(mixer_handle, channel_index, &cinfo) < 0) mixer_abort(ERR_FCN, "snd_mixer_channel_info"); + channel_record_volume = (cinfo.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME); /* set new channel values */ @@ -326,14 +332,40 @@ static void mixer_update_cbar(int channel_index) mixer_route_rtol_in || mixer_route_ltor_in)) { if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0) mixer_abort(ERR_FCN, "snd_mixer_channel_read"); + if (mixer_record_volumes && channel_record_volume && + snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0) + mixer_abort(ERR_FCN, "snd_mixer_channel_record_read"); cdata.flags &= ~SND_MIXER_FLG_DECIBEL; - cdata.left = CLAMP(cdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max); - cdata.right = CLAMP(cdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max); - mixer_lvolume_delta = mixer_rvolume_delta = 0; + if (mixer_lvolume_delta) { + if (mixer_record_volumes) { + if (channel_record_volume) + crdata.left = CLAMP(crdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max); + } + else + cdata.left = CLAMP(cdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max); + mixer_lvolume_delta = 0; + } + if (mixer_rvolume_delta) { + if (mixer_record_volumes) { + if (channel_record_volume) + crdata.right = CLAMP(crdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max); + } + else + cdata.right = CLAMP(cdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max); + mixer_rvolume_delta = 0; + } if (mixer_balance_volumes) { - cdata.left = (cdata.left + cdata.right) / 2; - cdata.right = cdata.left; + if (mixer_record_volumes) { + if (channel_record_volume) { + crdata.left = (crdata.left + crdata.right) / 2; + crdata.right = crdata.left; + } + } + else { + cdata.left = (cdata.left + cdata.right) / 2; + cdata.right = cdata.left; + } mixer_balance_volumes = 0; } if (mixer_toggle_mute_left) { @@ -393,14 +425,29 @@ static void mixer_update_cbar(int channel_index) if (snd_mixer_channel_write(mixer_handle, channel_index, &cdata) < 0) mixer_abort(ERR_FCN, "snd_mixer_channel_write"); + if (mixer_record_volumes && channel_record_volume && + snd_mixer_channel_record_write(mixer_handle, channel_index, &crdata) < 0) + mixer_abort(ERR_FCN, "snd_mixer_channel_record_write"); } /* first, read values for the numbers to be displayed in * specified EXACT mode */ if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0) mixer_abort(ERR_FCN, "snd_mixer_ioctl_channel_read"); - vleft = cdata.left; - vright = cdata.right; + if (mixer_record_volumes) { + if (channel_record_volume) { + if (snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0) + mixer_abort(ERR_FCN, "snd_mixer_channel_record_read"); + vleft = crdata.left; + vright = crdata.right; + } + else + vleft = vright = 0; + } + else { + vleft = cdata.left; + vright = cdata.right; + } /* then, always use percentage values for the bars. if we don't do * this, we will see aliasing effects on specific circumstances. @@ -413,6 +460,9 @@ static void mixer_update_cbar(int channel_index) mixer_abort(ERR_FCN, "snd_mixer_exact"); if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0) mixer_abort(ERR_FCN, "snd_mixer_channel_read"); + if (mixer_record_volumes && channel_record_volume && + snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0) + mixer_abort(ERR_FCN, "snd_mixer_channel_record_read"); } /* get channel bar position */ @@ -470,8 +520,8 @@ static void mixer_update_cbar(int channel_index) dc = DC_CBAR_FULL_2; else dc = DC_CBAR_FULL_1; - mvaddch(y, x + 3, mixer_dc(cdata.left > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); - mvaddch(y, x + 4, mixer_dc(cdata.right > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); + mvaddch(y, x + 3, mixer_dc(vleft > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); + mvaddch(y, x + 4, mixer_dc(vright > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); y--; } @@ -601,6 +651,10 @@ static void mixer_draw_frame(void) if (strlen(string) > max_len) string[max_len] = 0; mvaddstr(2, 2 + 6, string); + if (mixer_record_volumes) + mvaddstr(3, 2, "Record mixer"); + else + mvaddstr(3, 2, " "); } static void mixer_init(void) @@ -752,6 +806,7 @@ static int mixer_iteration(void) break; case 'm': case 'M': + mixer_record_volumes = 0; mixer_toggle_mute_left = 1; mixer_toggle_mute_right = 1; break; @@ -762,14 +817,18 @@ static int mixer_iteration(void) break; case '<': case ',': + mixer_record_volumes = 0; mixer_toggle_mute_left = 1; break; case '>': case '.': + mixer_record_volumes = 0; mixer_toggle_mute_right = 1; break; case 'R': case 'r': + mixer_record_volumes = !mixer_record_volumes; + break; case 'L': case 'l': mixer_clear(); @@ -786,9 +845,11 @@ static int mixer_iteration(void) mixer_toggle_rec_right = 1; break; case '1': + mixer_record_volumes = 0; mixer_route_rtol_in = 1; break; case '2': + mixer_record_volumes = 0; mixer_route_ltor_in = 1; break; }