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
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 */
static int Xswitchtype = SWITCH_CONTROL;
static int *Xswitchchange = NULL;
static void *Xswitch = NULL;
+static unsigned int Xswitchiec958ocs = 0;
+static unsigned short Xswitchiec958ocs1[16];
%}
/* 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 <b_value> boolean
%type <i_value> integer
| 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
;
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" ); }
;
| 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) ); }
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;
}
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;
}
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;
}
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 = " ";
}
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" );
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 ) {
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" );
}
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 ) {