1999-05-02 18:21:40 +02:00
/*
* Advanced Linux Sound Architecture Control Program
1999-05-12 00:18:49 +02:00
* Copyright ( c ) 1999 by Jaroslav Kysela < perex @ suse . cz >
1999-05-02 18:21:40 +02:00
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
# include "alsactl.h"
2000-07-15 12:21:59 +02:00
static int merge_one_control ( struct ctl_control * cctl , struct ctl_control * uctl , int cardno )
1999-05-02 18:21:40 +02:00
{
2000-07-15 12:21:59 +02:00
int idx ;
1999-05-02 18:21:40 +02:00
2000-07-15 12:21:59 +02:00
if ( ! ( cctl - > info . access & SND_CONTROL_ACCESS_WRITE ) )
return 0 ;
switch ( cctl - > info . type ) {
case SND_CONTROL_TYPE_BOOLEAN :
2000-07-25 17:17:55 +02:00
if ( uctl - > type ! = SND_CONTROL_TYPE_BOOLEAN ) {
2000-07-15 12:21:59 +02:00
error ( " A wrong type %i for the control '%s'. The type integer is expected. Skipping... " , uctl - > type , control_id ( & uctl - > c . id ) ) ;
1999-05-02 18:21:40 +02:00
return 1 ;
}
2000-07-15 12:21:59 +02:00
for ( idx = 0 ; idx < cctl - > info . values_count ; idx + + ) {
if ( cctl - > c . value . integer . value [ idx ] ! = uctl - > c . value . integer . value [ idx ] ) {
cctl - > change = 1 ;
cctl - > c . value . integer . value [ idx ] = uctl - > c . value . integer . value [ idx ] ;
1999-05-02 18:21:40 +02:00
}
}
break ;
2000-07-15 12:21:59 +02:00
case SND_CONTROL_TYPE_INTEGER :
2000-07-25 17:17:55 +02:00
if ( uctl - > type ! = SND_CONTROL_TYPE_INTEGER ) {
2000-07-15 12:21:59 +02:00
error ( " A wrong type %i for the control '%s'. The type integer is expected. Skipping... " , uctl - > type , control_id ( & uctl - > c . id ) ) ;
1999-05-02 18:21:40 +02:00
return 1 ;
}
2000-07-15 12:21:59 +02:00
for ( idx = 0 ; idx < cctl - > info . values_count ; idx + + ) {
if ( cctl - > info . value . integer . min > uctl - > c . value . integer . value [ idx ] | |
cctl - > info . value . integer . max < uctl - > c . value . integer . value [ idx ] ) {
error ( " The value %li for the control '%s' is out of range %i-%i. " , uctl - > c . value . integer . value [ idx ] , control_id ( & uctl - > c . id ) , cctl - > info . value . integer . min , cctl - > info . value . integer . max ) ;
return 1 ;
1999-05-02 18:21:40 +02:00
}
2000-07-15 12:21:59 +02:00
if ( cctl - > c . value . integer . value [ idx ] ! = uctl - > c . value . integer . value [ idx ] ) {
cctl - > change = 1 ;
cctl - > c . value . integer . value [ idx ] = uctl - > c . value . integer . value [ idx ] ;
1999-05-02 18:21:40 +02:00
}
}
break ;
2000-07-15 12:21:59 +02:00
case SND_CONTROL_TYPE_ENUMERATED :
2000-07-25 17:17:55 +02:00
if ( uctl - > type ! = SND_CONTROL_TYPE_ENUMERATED ) {
2000-07-15 12:21:59 +02:00
error ( " A wrong type %i for the control '%s'. The type integer is expected. Skipping... " , uctl - > type , control_id ( & uctl - > c . id ) ) ;
1999-05-02 18:21:40 +02:00
return 1 ;
}
2000-07-15 12:21:59 +02:00
for ( idx = 0 ; idx < cctl - > info . values_count ; idx + + ) {
2000-07-25 17:17:55 +02:00
if ( cctl - > info . value . enumerated . items < = uctl - > c . value . enumerated . item [ idx ] ) {
2000-07-15 12:21:59 +02:00
error ( " The value %u for the control '%s' is out of range 0-%i. " , uctl - > c . value . integer . value [ idx ] , control_id ( & uctl - > c . id ) , cctl - > info . value . enumerated . items - 1 ) ;
1999-05-02 18:21:40 +02:00
return 1 ;
}
2000-07-25 17:17:55 +02:00
if ( cctl - > c . value . enumerated . item [ idx ] ! = uctl - > c . value . enumerated . item [ idx ] ) {
2000-07-15 12:21:59 +02:00
cctl - > change = 1 ;
2000-07-25 17:17:55 +02:00
cctl - > c . value . enumerated . item [ idx ] = uctl - > c . value . enumerated . item [ idx ] ;
2000-07-15 12:21:59 +02:00
}
1999-05-02 18:21:40 +02:00
}
break ;
2000-07-15 12:21:59 +02:00
case SND_CONTROL_TYPE_BYTES :
if ( uctl - > type ! = SND_CONTROL_TYPE_BYTES ) {
error ( " A wrong type %i for the control %s. The type 'bytes' is expected. Skipping... " , uctl - > type , control_id ( & uctl - > c . id ) ) ;
1999-05-02 18:21:40 +02:00
return 1 ;
}
2000-07-15 12:21:59 +02:00
if ( memcmp ( cctl - > c . value . bytes . data , uctl - > c . value . bytes . data , uctl - > info . values_count ) ) {
cctl - > change = 1 ;
memcpy ( cctl - > c . value . bytes . data , uctl - > c . value . bytes . data , uctl - > info . values_count ) ;
1999-05-02 18:21:40 +02:00
}
break ;
default :
2000-07-15 12:21:59 +02:00
error ( " The control type %i is not known. " , cctl - > type ) ;
1999-05-02 18:21:40 +02:00
}
return 0 ;
}
2000-07-15 12:21:59 +02:00
static int soundcard_setup_merge_control ( struct ctl_control * cctl , struct ctl_control * uctl , int cardno )
1999-05-02 18:21:40 +02:00
{
2000-07-15 12:21:59 +02:00
struct ctl_control * cctl1 ;
1999-05-02 18:21:40 +02:00
2000-07-15 12:21:59 +02:00
for ( ; uctl ; uctl = uctl - > next ) {
for ( cctl1 = cctl ; cctl1 ; cctl1 = cctl1 - > next ) {
if ( cctl1 - > c . id . iface = = uctl - > c . id . iface & &
cctl1 - > c . id . device = = uctl - > c . id . device & &
cctl1 - > c . id . subdevice = = uctl - > c . id . subdevice & &
2000-07-26 13:40:31 +02:00
! strncmp ( cctl1 - > c . id . name , uctl - > c . id . name , sizeof ( cctl1 - > c . id . name ) ) & &
cctl1 - > c . id . index = = uctl - > c . id . index ) {
2000-07-15 12:21:59 +02:00
merge_one_control ( cctl1 , uctl , cardno ) ;
1999-05-02 18:21:40 +02:00
break ;
}
}
2000-07-15 12:21:59 +02:00
if ( ! cctl1 ) {
error ( " Cannot find the control %s... " , control_id ( & uctl - > c . id ) ) ;
1999-05-02 18:21:40 +02:00
}
}
return 0 ;
}
2000-07-15 12:21:59 +02:00
int soundcard_setup_merge_controls ( int cardno )
1999-05-02 18:21:40 +02:00
{
struct soundcard * soundcard , * rsoundcard ;
for ( rsoundcard = rsoundcards ; rsoundcard ; rsoundcard = rsoundcard - > next ) {
for ( soundcard = soundcards ; soundcard ; soundcard = soundcard - > next ) {
if ( ! strncmp ( soundcard - > control . hwinfo . id , rsoundcard - > control . hwinfo . id , sizeof ( soundcard - > control . hwinfo . id ) ) )
break ;
}
if ( ! soundcard ) {
error ( " The soundcard '%s' was not found... \n " , rsoundcard - > control . hwinfo . id ) ;
continue ;
}
if ( cardno > = 0 & & soundcard - > no ! = cardno )
continue ;
2000-07-15 12:21:59 +02:00
soundcard_setup_merge_control ( soundcard - > control . controls , rsoundcard - > control . controls , soundcard - > no ) ;
1999-05-02 18:21:40 +02:00
}
return 0 ;
}
1999-06-02 02:40:31 +02:00
static int soundcard_open_ctl ( snd_ctl_t * * ctlhandle , struct soundcard * soundcard )
1999-05-02 18:21:40 +02:00
{
int err ;
if ( * ctlhandle )
return 0 ;
if ( ( err = snd_ctl_open ( ctlhandle , soundcard - > no ) ) < 0 ) {
error ( " Cannot open control interface for soundcard #%i. " , soundcard - > no + 1 ) ;
return 1 ;
}
return 0 ;
}
2000-07-15 12:21:59 +02:00
int soundcard_setup_process_controls ( int cardno )
1999-05-02 18:21:40 +02:00
{
int err ;
1999-06-02 02:40:31 +02:00
snd_ctl_t * ctlhandle = NULL ;
1999-05-02 18:21:40 +02:00
struct soundcard * soundcard ;
2000-07-15 12:21:59 +02:00
struct ctl_control * ctl ;
1999-05-02 18:21:40 +02:00
for ( soundcard = soundcards ; soundcard ; soundcard = soundcard - > next ) {
if ( cardno > = 0 & & soundcard - > no ! = cardno )
continue ;
2000-07-15 12:21:59 +02:00
for ( ctl = soundcard - > control . controls ; ctl ; ctl = ctl - > next ) {
if ( ctl - > change )
1999-05-02 18:21:40 +02:00
if ( ! soundcard_open_ctl ( & ctlhandle , soundcard ) ) {
2000-07-15 12:21:59 +02:00
if ( ( err = snd_ctl_cwrite ( ctlhandle , & ctl - > c ) ) < 0 )
error ( " Control '%s' write error: %s " , control_id ( & ctl - > c . id ) , snd_strerror ( err ) ) ;
1999-05-02 18:21:40 +02:00
}
}
2000-01-11 14:19:03 +01:00
if ( ctlhandle ) {
1999-05-02 18:21:40 +02:00
snd_ctl_close ( ctlhandle ) ;
ctlhandle = NULL ;
}
}
return 0 ;
}