Changed mixer interface...

This commit is contained in:
Jaroslav Kysela 1998-11-01 23:24:45 +00:00
parent cf96e410f9
commit 25f5f4965e
3 changed files with 132 additions and 57 deletions

View file

@ -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; }

View file

@ -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 <b_value> boolean
%type <i_value> 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 ( right & 0x80000000 ) {
Xmixerchannelflags |= SND_MIXER_FLG_MUTE_RIGHT;
right &= 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 -> 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 )
if ( Xmixerchannel -> c.left != left )
Xmixerchannel -> change = 1;
Xmixerchannel -> c.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 -> c.right != right )
Xmixerchannel -> change = 1;
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;
}

View file

@ -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" );
@ -578,8 +577,10 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign
fprintf( out, " type( 0x%x )", (pdata -> data16[5] >> 6) & 0x7f );
if ( pdata -> data16[5] & 0x2000 ) fprintf( out, " gstatus" );
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 ) {