mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-08 22:35:41 +01:00
Changed mixer interface...
This commit is contained in:
parent
cf96e410f9
commit
25f5f4965e
3 changed files with 132 additions and 57 deletions
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
Loading…
Reference in a new issue