From 25f5f4965e2ceb5cb3da5b6d81e03755c004dbf1 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 1 Nov 1998 23:24:45 +0000 Subject: [PATCH] Changed mixer interface... --- alsactl/alsactl_lexer.l | 6 +- alsactl/alsactl_parser.y | 132 +++++++++++++++++++++++++++------------ alsactl/setup.c | 51 ++++++++++----- 3 files changed, 132 insertions(+), 57 deletions(-) diff --git a/alsactl/alsactl_lexer.l b/alsactl/alsactl_lexer.l index a472852..f16c767 100644 --- a/alsactl/alsactl_lexer.l +++ b/alsactl/alsactl_lexer.l @@ -63,13 +63,16 @@ reset return L_RESET; user return L_USER; valid return L_VALID; data return L_DATA; -protected return L_PROTECTED; +protected return L_PROTECT; pre2 return L_PRE2; fslock return L_FSLOCK; type return L_TYPE; gstatus return L_GSTATUS; enable return L_ENABLE; disable return L_DISABLE; +mute return L_MUTE; +swout return L_SWOUT; +swin return L_SWIN; /* boolean */ @@ -79,7 +82,6 @@ true|on|yes return L_TRUE; /* integers */ [0-9]+ { yylval.i_value = atoi( yytext ); return L_INTEGER; } -"!"[0-9]+ { yylval.i_value = atoi( yytext ); yylval.i_value |= 0x80000000; return L_INTEGER; } 0x[0-9a-f]+ { char *end; yylval.i_value = strtol( yytext, &end, 0 ); return L_INTEGER; } diff --git a/alsactl/alsactl_parser.y b/alsactl/alsactl_parser.y index 63395bc..f463152 100644 --- a/alsactl/alsactl_parser.y +++ b/alsactl/alsactl_parser.y @@ -43,7 +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( void ); +static void set_mixer_channel_flags( unsigned int mask, unsigned int flags ); static void set_mixer_channel_end( void ); #define SWITCH_CONTROL 0 @@ -60,7 +60,7 @@ static void select_rawmidi_input_switch( char *name ); static void set_switch_boolean( int val ); static void set_switch_integer( int val ); -static void set_switch_iec958ocs_begin( void ); +static void set_switch_iec958ocs_begin( int end ); static void set_switch_iec958ocs( int idx, unsigned short val, unsigned short mask ); /* local variables */ @@ -74,6 +74,8 @@ static unsigned int Xmixerchannelflags = 0; static int Xswitchtype = SWITCH_CONTROL; static int *Xswitchchange = NULL; static void *Xswitch = NULL; +static unsigned int Xswitchiec958ocs = 0; +static unsigned short Xswitchiec958ocs1[16]; %} @@ -100,8 +102,8 @@ static void *Xswitch = NULL; /* other keywords */ %token L_SOUNDCARD L_MIXER L_CHANNEL L_STEREO L_MONO L_SWITCH L_RAWDATA %token L_CONTROL L_PCM L_RAWMIDI L_PLAYBACK L_RECORD L_OUTPUT L_INPUT -%token L_IEC958OCS L_3D L_RESET L_USER L_VALID L_DATA L_PROTECTED L_PRE2 -%token L_FSLOCK L_TYPE L_GSTATUS L_ENABLE L_DISABLE +%token L_IEC958OCS L_3D L_RESET L_USER L_VALID L_DATA L_PROTECT L_PRE2 +%token L_FSLOCK L_TYPE L_GSTATUS L_ENABLE L_DISABLE L_MUTE L_SWOUT L_SWIN %type boolean %type integer @@ -150,12 +152,45 @@ mvalues : mvalue | mvalues mvalue ; -mvalue : L_STEREO '(' integer ',' integer ')' { set_mixer_channel( $3, $5 ); } - | L_MONO '(' integer ')' { set_mixer_channel( $3, $3 ); } - | L_RECORD { set_mixer_channel_record(); } +mvalue : L_STEREO '(' xmchls ',' xmchrs ')' + | L_MONO '(' xmchs ')' | error { yyerror( "unknown keyword in mixer channel{} level" ); } ; +xmchls : xmchl + | xmchls xmchl + ; + +xmchl : L_INTEGER { set_mixer_channel( $1, -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 ); } + | L_SWIN { set_mixer_channel_flags( SND_MIXER_FLG_LTOR_IN, SND_MIXER_FLG_LTOR_IN ); } + | error { yyerror( "unknown keyword in left channel section..." ); } + ; + +xmchrs : xmchr + | xmchrs xmchr + ; + +xmchr : L_INTEGER { set_mixer_channel( -1, $1 ); } + | 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 ); } + | L_SWIN { set_mixer_channel_flags( SND_MIXER_FLG_RTOL_IN, SND_MIXER_FLG_RTOL_IN ); } + | error { yyerror( "unknown keyword in right channel section..." ); } + ; + +xmchs : xmch + | xmchs xmch + ; + +xmch : L_INTEGER { set_mixer_channel( $1, $1 ); } + | 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..." ); } + ; + pcms : pcm | pcms pcm ; @@ -212,7 +247,7 @@ switches : switch switch : L_TRUE { set_switch_boolean( 1 ); } | L_FALSE { set_switch_boolean( 0 ); } | L_INTEGER { set_switch_integer( $1 ); } - | L_IEC958OCS '(' { set_switch_iec958ocs_begin(); } iec958ocs ')' + | L_IEC958OCS '(' { set_switch_iec958ocs_begin( 0 ); } iec958ocs { set_switch_iec958ocs_begin( 1 ); } ')' | error { yyerror( "unknown keyword in switch() data parameter" ); } ; @@ -227,6 +262,7 @@ iec958ocs1 : L_ENABLE { set_switch_iec958ocs( 0, 1, 0 ); } | L_USER { set_switch_iec958ocs( 4, 0x0020, ~0x0020 ); } | L_VALID { set_switch_iec958ocs( 4, 0x0010, ~0x0010 ); } | L_DATA { set_switch_iec958ocs( 5, 0x0002, ~0x0002 ); } + | L_PROTECT { set_switch_iec958ocs( 5, 0x0004, ~0x0004 ); } | L_PRE2 { set_switch_iec958ocs( 5, 0x0008, ~0x0018 ); } | L_FSLOCK { set_switch_iec958ocs( 5, 0x0020, ~0x0020 ); } | L_TYPE '(' integer ')' { set_switch_iec958ocs( 5, ($3 & 0x7f) << 6, ~(0x7f<<6) ); } @@ -334,6 +370,13 @@ static void select_mixer_channel( char *name ) for ( channel = Xmixer -> channels; channel; channel = channel -> next ) if ( !strcmp( channel -> i.name, name ) ) { Xmixerchannel = channel; + Xmixerchannelflags = Xmixerchannel -> c.flags & + ~(SND_MIXER_FLG_RECORD | + SND_MIXER_FLG_MUTE | + SND_MIXER_FLG_SWITCH_OUT | + SND_MIXER_FLG_SWITCH_IN | + SND_MIXER_FLG_DECIBEL | + SND_MIXER_FLG_FORCE); free( name ); return; } @@ -343,38 +386,33 @@ static void select_mixer_channel( char *name ) static void set_mixer_channel( int left, int right ) { - Xmixerchannelflags = Xmixerchannel -> c.flags & - ~(SND_MIXER_FLG_RECORD | - SND_MIXER_FLG_MUTE | - SND_MIXER_FLG_DECIBEL | - SND_MIXER_FLG_FORCE); - if ( left & 0x80000000 ) { - Xmixerchannelflags |= SND_MIXER_FLG_MUTE_LEFT; - left &= 0x7fffffff; + 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 -> c.left != left ) + Xmixerchannel -> change = 1; + Xmixerchannel -> c.left = left; } - if ( right & 0x80000000 ) { - Xmixerchannelflags |= SND_MIXER_FLG_MUTE_RIGHT; - right &= 0x7fffffff; + 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 -> c.right != right ) + Xmixerchannel -> change = 1; + Xmixerchannel -> c.right = right; } - if ( Xmixerchannel -> i.min > left || Xmixerchannel -> i.max < left ) - yyerror( "Value out of range (%i-%i)...", Xmixerchannel -> i.min, Xmixerchannel -> i.max ); - if ( Xmixerchannel -> i.min > right || Xmixerchannel -> i.max < right ) - yyerror( "Value out of range (%i-%i)...", Xmixerchannel -> i.min, Xmixerchannel -> i.max ); - if ( Xmixerchannel -> c.left != left || Xmixerchannel -> c.right != right ) - Xmixerchannel -> change = 1; - Xmixerchannel -> c.left = left; - Xmixerchannel -> c.right = right; } -static void set_mixer_channel_record( void ) +static void set_mixer_channel_flags( unsigned int mask, unsigned int flags ) { - Xmixerchannelflags |= SND_MIXER_FLG_RECORD; + Xmixerchannelflags &= ~mask; + Xmixerchannelflags |= flags; } static void set_mixer_channel_end( void ) { - if ( Xmixerchannel -> c.flags != Xmixerchannelflags ) + if ( Xmixerchannel -> c.flags != Xmixerchannelflags ) { Xmixerchannel -> change = 1; + } Xmixerchannel -> c.flags = Xmixerchannelflags; } @@ -458,30 +496,42 @@ static void set_switch_integer( int val ) memcpy( &sw -> value, &xx, sizeof(xx) ); } -static void set_switch_iec958ocs_begin( void ) +static void set_switch_iec958ocs_begin( int end ) { /* ok.. this is a little bit wrong, but at these times are all switches same */ snd_ctl_switch_t *sw = (snd_ctl_switch_t *)Xswitch; + if ( !end ) { + if ( Xswitchiec958ocs != sw -> value.enable ) { + sw -> value.enable = Xswitchiec958ocs; + *Xswitchchange = 1; + } + if ( Xswitchiec958ocs1[4] != sw -> value.data16[4] ) { + sw -> value.data16[4] = Xswitchiec958ocs1[4]; + *Xswitchchange = 1; + } + if ( Xswitchiec958ocs1[5] != sw -> value.data16[5] ) { + sw -> value.data16[5] = Xswitchiec958ocs1[5]; + *Xswitchchange = 1; + } + return; + } if ( Xswitchtype != SWITCH_MIXER || sw -> type != SND_MIXER_SW_TYPE_BOOLEAN || - !strcmp( sw -> name, SND_MIXER_SW_IEC958OUT ) ) + strcmp( sw -> name, SND_MIXER_SW_IEC958OUT ) ) yyerror( "Switch '%s' cannot store IEC958 information for Cirrus Logic chips...", sw -> name ); if ( sw -> value.data32[1] != (('C'<<8)|'S') ) yyerror( "Switch '%s' doesn't have Cirrus Logic signature!!!", sw -> name ); - sw -> value.enable = 0; - sw -> value.data16[4] = 0x0000; - sw -> value.data16[5] = 0x0000; + Xswitchiec958ocs = 0; + Xswitchiec958ocs1[4] = 0x0000; + Xswitchiec958ocs1[5] = 0x0000; } static void set_switch_iec958ocs( int idx, unsigned short val, unsigned short mask ) { - /* ok.. this is a little bit wrong, but at these times are all switches same */ - snd_ctl_switch_t *sw = (snd_ctl_switch_t *)Xswitch; - if ( idx == 0 ) { - sw -> value.enable = val ? 1 : 0; + Xswitchiec958ocs = val ? 1 : 0; return; } - sw -> value.data16[ idx ] &= ~mask; - sw -> value.data16[ idx ] |= val; + Xswitchiec958ocs1[ idx ] &= ~mask; + Xswitchiec958ocs1[ idx ] |= val; } diff --git a/alsactl/setup.c b/alsactl/setup.c index df0e6e3..23334f7 100644 --- a/alsactl/setup.c +++ b/alsactl/setup.c @@ -520,14 +520,13 @@ int soundcard_setup_load( const char *cfgfile ) static void soundcard_setup_write_switch( FILE *out, int interface, const unsigned char *name, unsigned int type, unsigned int low, unsigned int high, void *data ) { - struct data { + union { unsigned int enable; unsigned char data8[32]; unsigned short data16[16]; unsigned int data32[8]; - }; + } *pdata = data; char *s, v[16]; - struct data *pdata = (struct data *)data; int idx, first, switchok = 0; const char *space = " "; @@ -558,10 +557,10 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign } if ( !first ) fprintf( out, "\n" ); } - fprintf( out, "%sswitch( \"%s\", ", space, name ); if ( interface == SND_INTERFACE_MIXER && type == SND_MIXER_SW_TYPE_BOOLEAN && !strcmp( name, SND_MIXER_SW_IEC958OUT ) ) { - if ( pdata -> data16[0] == (('C'<<8)|'S') ) { /* Cirrus Crystal */ + fprintf( out, "%sswitch( \"%s\", ", space, name ); + if ( pdata -> data32[1] == (('C'<<8)|'S') ) { /* Cirrus Crystal */ switchok = 0; fprintf( out, "iec958ocs( %s", pdata -> enable ? "enable" : "disable" ); if ( pdata -> data16[4] & 0x2000 ) fprintf( out, " 3d" ); @@ -577,9 +576,11 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign if ( pdata -> data16[5] & 0x0020 ) fprintf( out, " fslock" ); fprintf( out, " type( 0x%x )", (pdata -> data16[5] >> 6) & 0x7f ); if ( pdata -> data16[5] & 0x2000 ) fprintf( out, " gstatus" ); - fprintf( out, ")" ); + fprintf( out, " )" ); + goto __end; } } + fprintf( out, "%sswitch( \"%s\", ", space, name ); if ( !switchok ) { fprintf( out, v ); if ( type < 0 || type > SND_CTL_SW_TYPE_DWORD ) { @@ -591,28 +592,50 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign fprintf( out, "%02x@ )\n", pdata -> data8[31] ); } } + __end: fprintf( out, " )\n" ); } static void soundcard_setup_write_mixer_channel( FILE *out, snd_mixer_channel_info_t *info, snd_mixer_channel_t *channel ) { - fprintf( out, " ; Capabilities:%s%s%s%s%s%s.\n", + 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" : "", + info -> caps & SND_MIXER_CINFO_CAP_JOINRECORD ? " join-record" : "", info -> caps & SND_MIXER_CINFO_CAP_STEREO ? " stereo" : "", info -> caps & SND_MIXER_CINFO_CAP_HWMUTE ? " hardware-mute" : "", - info -> caps & SND_MIXER_CINFO_CAP_MONOMUTE ? " mono-mute" : "", + info -> caps & SND_MIXER_CINFO_CAP_JOINMUTE ? " join-mute" : "", info -> caps & SND_MIXER_CINFO_CAP_DIGITAL ? " digital" : "", - info -> caps & SND_MIXER_CINFO_CAP_INPUT ? " external-input" : "" ); + info -> caps & SND_MIXER_CINFO_CAP_INPUT ? " external-input" : "", + info -> caps & SND_MIXER_CINFO_CAP_LTOR_OUT ? " ltor-out" : "", + info -> caps & SND_MIXER_CINFO_CAP_RTOL_OUT ? " rtol-out" : "", + 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" : "" ); fprintf( out, " ; Accepted channel range is from %i to %i.\n", info -> min, info -> max ); fprintf( out, " channel( \"%s\", ", info -> name ); + printf( "flags = 0x%x\n", channel -> flags ); if ( info -> caps & SND_MIXER_CINFO_CAP_STEREO ) { - fprintf( out, "stereo( %s%i, %s%i )", channel -> flags & SND_MIXER_FLG_MUTE_LEFT ? "!" : "", channel -> left, channel -> flags & SND_MIXER_FLG_MUTE_RIGHT ? "!" : "", channel -> right ); + fprintf( out, "stereo( %i%s%s%s%s, %i%s%s%s%s )", + channel -> left, + 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" : "", + channel -> right, + 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" : "" + ); } else { - fprintf( out, "mono( %s%i )", channel -> flags & SND_MIXER_FLG_MUTE ? "!" : "", channel -> left ); + fprintf( out, "mono( %i%s%s )", + (channel -> left + channel -> right) / 2, + channel -> flags & SND_MIXER_FLG_MUTE ? " mute" : "", + channel -> flags & SND_MIXER_FLG_RECORD ? " record" : "" + ); } - if ( channel -> flags & SND_MIXER_FLG_RECORD ) - fprintf( out, " record" ); fprintf( out, " )\n" ); } @@ -649,7 +672,7 @@ int soundcard_setup_write( const char *cfgfile ) for ( mixerchannel = mixer -> channels; mixerchannel; mixerchannel = mixerchannel -> next ) soundcard_setup_write_mixer_channel( out, &mixerchannel -> i, &mixerchannel -> c ); 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 ); + 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" ); } for ( pcm = first -> pcms; pcm; pcm = pcm -> next ) { -- 2.47.1