mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 18:46:32 +01:00
Changed syntax of configuration file and added better parsing.
This commit is contained in:
parent
67aefd9f3e
commit
50658ad2e7
5 changed files with 135 additions and 89 deletions
|
@ -8,4 +8,3 @@ YFLAGS=-d
|
|||
# lexer / parser debug
|
||||
#CFLAGS=-pipe -g -DYYDEBUG
|
||||
#LFLAGS=-d
|
||||
|
||||
|
|
|
@ -62,6 +62,18 @@ rawmidi return L_RAWMIDI;
|
|||
timer return L_TIMER;
|
||||
sequencer return L_SEQUENCER;
|
||||
|
||||
ident return L_IDENT;
|
||||
iface return L_IFACE;
|
||||
name return L_NAME;
|
||||
device return L_DEVICE;
|
||||
subdevice return L_SUBDEVICE;
|
||||
index return L_INDEX;
|
||||
|
||||
bool return L_BOOL;
|
||||
int return L_INT;
|
||||
enum return L_ENUM;
|
||||
byte return L_BYTE;
|
||||
|
||||
/* boolean */
|
||||
|
||||
false|off|no return L_FALSE;
|
||||
|
@ -72,26 +84,6 @@ true|on|yes return L_TRUE;
|
|||
[0-9]+ { yylval.i_value = strtol(yytext, (char **)NULL, 10); return L_INTEGER; }
|
||||
0x[0-9a-f]+ { yylval.i_value = strtol(yytext, (char **)NULL, 0); return L_INTEGER; }
|
||||
|
||||
/* byte array */
|
||||
|
||||
"@"([0-9a-f]{2}:){0,31}([0-9a-f]{2})"@" {
|
||||
char *p = yytext + 1, x[3];
|
||||
unsigned char *d;
|
||||
int val;
|
||||
yylval.a_value.data = d = (unsigned char *)malloc( 32 );
|
||||
yylval.a_value.datalen = 0;
|
||||
while (*p) {
|
||||
strncpy(x, p, 2); x[2] = '\0';
|
||||
sscanf(x, "%02x", &val);
|
||||
*d++ = val;
|
||||
++yylval.a_value.datalen;
|
||||
p += 2;
|
||||
if (*p == '@')
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
return L_BYTEARRAY; }
|
||||
|
||||
/* strings */
|
||||
|
||||
\"[^\"]*\" { yytext[strlen(yytext) - 1] = 0;
|
||||
|
|
|
@ -44,11 +44,16 @@ struct bytearray {
|
|||
static void yyerror(char *, ...);
|
||||
|
||||
static void build_soundcard(char *name);
|
||||
static void build_control_begin(int iface, unsigned int device, unsigned int subdevice, char *name, unsigned int index);
|
||||
static void build_control_begin(void);
|
||||
static void build_control_end(void);
|
||||
static void set_control_iface(int iface);
|
||||
static void set_control_device(int dev);
|
||||
static void set_control_subdevice(int subdev);
|
||||
static void set_control_name(char *name);
|
||||
static void set_control_index(int idx);
|
||||
static void set_control_type(snd_control_type_t type);
|
||||
static void set_control_boolean(int val);
|
||||
static void set_control_integer(long val);
|
||||
static void set_control_bytearray(struct bytearray val);
|
||||
|
||||
/* local variables */
|
||||
|
||||
|
@ -82,7 +87,8 @@ static snd_control_type_t Xtype = SND_CONTROL_TYPE_NONE;
|
|||
/* other keywords */
|
||||
%token L_SOUNDCARD L_CONTROL L_RAWDATA
|
||||
%token L_GLOBAL L_HWDEP L_MIXER L_PCM L_RAWMIDI L_TIMER L_SEQUENCER
|
||||
|
||||
%token L_IDENT L_IFACE L_NAME L_DEVICE L_SUBDEVICE L_INDEX
|
||||
%token L_BOOL L_INT L_ENUM L_BYTE
|
||||
|
||||
%type <b_value> boolean
|
||||
%type <i_value> integer iface
|
||||
|
@ -104,22 +110,42 @@ soundcards :
|
|||
| soundcards soundcard
|
||||
;
|
||||
|
||||
soundcard : L_CONTROL '(' iface ',' integer ',' integer ',' string ',' integer
|
||||
{ build_control_begin($3, $5, $7, $9, $11); }
|
||||
',' controls ')' { build_control_end(); }
|
||||
| error { yyerror( "an unknown keyword in the soundcard{} level"); }
|
||||
soundcard : L_CONTROL '(' L_IDENT '=' { build_control_begin(); }
|
||||
'{' ctlids '}' ',' controls ')' { build_control_end(); }
|
||||
| error { yyerror("an unknown keyword in the soundcard{} level"); }
|
||||
;
|
||||
|
||||
ctlids : ctlid
|
||||
| ctlids ',' ctlid
|
||||
;
|
||||
|
||||
ctlid : L_IFACE '=' iface { set_control_iface($3); }
|
||||
| L_DEVICE '=' integer { set_control_device($3); }
|
||||
| L_SUBDEVICE '=' integer { set_control_subdevice($3); }
|
||||
| L_NAME '=' string { set_control_name($3); }
|
||||
| L_INDEX '=' integer { set_control_index($3); }
|
||||
| error { yyerror("an unknown keyword in the control ID level"); }
|
||||
;
|
||||
|
||||
controls : control
|
||||
| controls ',' control
|
||||
;
|
||||
|
||||
control : boolean { set_control_boolean($1); }
|
||||
| integer { set_control_integer($1); }
|
||||
| rawdata { set_control_bytearray($1); }
|
||||
control : L_BOOL '=' { set_control_type(SND_CONTROL_TYPE_BOOLEAN); } '{' datas '}'
|
||||
| L_INT '=' { set_control_type(SND_CONTROL_TYPE_INTEGER); } '{' datas '}'
|
||||
| L_ENUM '=' { set_control_type(SND_CONTROL_TYPE_ENUMERATED); } '{' datas '}'
|
||||
| L_BYTE '=' { set_control_type(SND_CONTROL_TYPE_BYTES); } '{' datas '}'
|
||||
| error { yyerror( "an unknown keyword in the control() data parameter" ); }
|
||||
;
|
||||
|
||||
datas : data
|
||||
| datas ',' data
|
||||
;
|
||||
|
||||
data : boolean { set_control_boolean($1); }
|
||||
| integer { set_control_integer($1); }
|
||||
| error { yyerror( "an unknown keyword in the control() data argument" ); }
|
||||
;
|
||||
|
||||
iface : L_INTEGER { $$ = $1; }
|
||||
| L_GLOBAL { $$ = SND_CONTROL_IFACE_CARD; }
|
||||
| L_HWDEP { $$ = SND_CONTROL_IFACE_HWDEP; }
|
||||
|
@ -190,7 +216,7 @@ static void build_soundcard(char *name)
|
|||
free(name);
|
||||
}
|
||||
|
||||
static void build_control_begin(int iface, unsigned int device, unsigned int subdevice, char *name, unsigned int index)
|
||||
static void build_control_begin(void)
|
||||
{
|
||||
struct ctl_control **first;
|
||||
struct ctl_control *ctl;
|
||||
|
@ -198,7 +224,6 @@ static void build_control_begin(int iface, unsigned int device, unsigned int sub
|
|||
first = &Xsoundcard->control.controls;
|
||||
Xcontrol = (struct ctl_control *)malloc(sizeof(struct ctl_control));
|
||||
if (!Xcontrol) {
|
||||
free(name);
|
||||
error_nomem();
|
||||
return;
|
||||
}
|
||||
|
@ -211,12 +236,6 @@ static void build_control_begin(int iface, unsigned int device, unsigned int sub
|
|||
} else {
|
||||
*first = Xcontrol;
|
||||
}
|
||||
Xcontrol->c.id.iface = iface;
|
||||
Xcontrol->c.id.device = device;
|
||||
Xcontrol->c.id.subdevice = subdevice;
|
||||
strncpy(Xcontrol->c.id.name, name, sizeof(Xcontrol->c.id.name));
|
||||
Xcontrol->c.id.index = index;
|
||||
free(name);
|
||||
}
|
||||
|
||||
static void build_control_end(void)
|
||||
|
@ -224,52 +243,77 @@ static void build_control_end(void)
|
|||
Xcontrol = NULL;
|
||||
}
|
||||
|
||||
static void set_control_iface(int iface)
|
||||
{
|
||||
Xcontrol->c.id.iface = iface;
|
||||
}
|
||||
|
||||
static void set_control_device(int dev)
|
||||
{
|
||||
Xcontrol->c.id.device = dev;
|
||||
}
|
||||
|
||||
static void set_control_subdevice(int subdev)
|
||||
{
|
||||
Xcontrol->c.id.subdevice = subdev;
|
||||
}
|
||||
|
||||
static void set_control_name(char *name)
|
||||
{
|
||||
if (name == NULL)
|
||||
return;
|
||||
strncpy(Xcontrol->c.id.name, name, sizeof(Xcontrol->c.id.name));
|
||||
free(name);
|
||||
}
|
||||
|
||||
static void set_control_index(int idx)
|
||||
{
|
||||
Xcontrol->c.id.index = idx;
|
||||
}
|
||||
|
||||
static void set_control_type(snd_control_type_t type)
|
||||
{
|
||||
Xcontrol->type = Xtype = type;
|
||||
}
|
||||
|
||||
static void set_control_boolean(int val)
|
||||
{
|
||||
if (Xposition >= 512)
|
||||
yyerror("Array overflow.");
|
||||
switch (Xtype) {
|
||||
case SND_CONTROL_TYPE_NONE:
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
Xtype = Xcontrol->type = SND_CONTROL_TYPE_BOOLEAN;
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
|
||||
break;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
break;
|
||||
default:
|
||||
yyerror("Unexpected previous type (%i).\n", Xtype);
|
||||
}
|
||||
if (Xposition < 512)
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
|
||||
else
|
||||
yyerror("Array overflow.");
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
Xcontrol->c.value.enumerated.item[Xposition++] = val ? 1 : 0;
|
||||
break;
|
||||
case SND_CONTROL_TYPE_BYTES:
|
||||
Xcontrol->c.value.bytes.data[Xposition++] = val ? 1 : 0;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_control_integer(long val)
|
||||
{
|
||||
unsigned int xx;
|
||||
|
||||
if (Xposition >= 512)
|
||||
yyerror("Array overflow.");
|
||||
switch (Xtype) {
|
||||
case SND_CONTROL_TYPE_NONE:
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
Xtype = Xcontrol->type = SND_CONTROL_TYPE_INTEGER;
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
yyerror("Unexpected previous type (%i).\n", Xtype);
|
||||
}
|
||||
if (Xposition < 512) {
|
||||
xx = val;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val;
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
Xcontrol->c.value.enumerated.item[Xposition++] = (unsigned int)val;
|
||||
break;
|
||||
case SND_CONTROL_TYPE_BYTES:
|
||||
Xcontrol->c.value.bytes.data[Xposition++] = (unsigned char)val;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_control_bytearray(struct bytearray val)
|
||||
{
|
||||
if (Xtype != SND_CONTROL_TYPE_NONE && Xtype != SND_CONTROL_TYPE_BYTES)
|
||||
yyerror("Unexpected previous type (%i).\n", Xtype);
|
||||
Xtype = Xcontrol->type = SND_CONTROL_TYPE_BYTES;
|
||||
|
||||
if (val.datalen + Xposition > 512)
|
||||
yyerror("Byte array too large for control.");
|
||||
|
||||
memcpy(&Xcontrol->c.value.bytes.data[Xposition], val.data, val.datalen);
|
||||
Xposition += val.datalen;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ static int merge_one_control(struct ctl_control *cctl, struct ctl_control *uctl,
|
|||
return 0;
|
||||
switch (cctl->info.type) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
if (uctl->type != SND_CONTROL_TYPE_BOOLEAN && uctl->type != SND_CONTROL_TYPE_INTEGER) {
|
||||
if (uctl->type != SND_CONTROL_TYPE_BOOLEAN) {
|
||||
error("A wrong type %i for the control '%s'. The type integer is expected. Skipping...", uctl->type, control_id(&uctl->c.id));
|
||||
return 1;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ static int merge_one_control(struct ctl_control *cctl, struct ctl_control *uctl,
|
|||
}
|
||||
break;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
if (uctl->type != SND_CONTROL_TYPE_BOOLEAN && uctl->type != SND_CONTROL_TYPE_INTEGER) {
|
||||
if (uctl->type != SND_CONTROL_TYPE_INTEGER) {
|
||||
error("A wrong type %i for the control '%s'. The type integer is expected. Skipping...", uctl->type, control_id(&uctl->c.id));
|
||||
return 1;
|
||||
}
|
||||
|
@ -58,18 +58,18 @@ static int merge_one_control(struct ctl_control *cctl, struct ctl_control *uctl,
|
|||
}
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
if (uctl->type != SND_CONTROL_TYPE_BOOLEAN && uctl->type != SND_CONTROL_TYPE_INTEGER) {
|
||||
if (uctl->type != SND_CONTROL_TYPE_ENUMERATED) {
|
||||
error("A wrong type %i for the control '%s'. The type integer is expected. Skipping...", uctl->type, control_id(&uctl->c.id));
|
||||
return 1;
|
||||
}
|
||||
for (idx = 0; idx < cctl->info.values_count; idx++) {
|
||||
if (cctl->info.value.enumerated.items <= uctl->c.value.integer.value[idx]) {
|
||||
if (cctl->info.value.enumerated.items <= uctl->c.value.enumerated.item[idx]) {
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
if (cctl->c.value.enumerated.item[idx] != uctl->c.value.integer.value[idx]) {
|
||||
if (cctl->c.value.enumerated.item[idx] != uctl->c.value.enumerated.item[idx]) {
|
||||
cctl->change = 1;
|
||||
cctl->c.value.enumerated.item[idx] = uctl->c.value.integer.value[idx];
|
||||
cctl->c.value.enumerated.item[idx] = uctl->c.value.enumerated.item[idx];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -342,32 +342,43 @@ static void soundcard_setup_write_control(FILE * out, const char *space, int car
|
|||
case SND_CONTROL_IFACE_SEQUENCER: s = "sequencer"; break;
|
||||
default: sprintf(v, "%i", info.id.iface); s = v; break;
|
||||
}
|
||||
fprintf(out, "%scontrol(%s, %i, %i, \"%s\", %i", space, s, info.id.device, info.id.subdevice, info.id.name, info.id.index);
|
||||
if (info.type == SND_CONTROL_TYPE_BYTES)
|
||||
fprintf(out, "rawdata(@");
|
||||
fprintf(out, "%scontrol(ident={iface=%s", space, s);
|
||||
if (info.id.device > 0)
|
||||
fprintf(out, ", device=%i", info.id.device);
|
||||
if (info.id.subdevice > 0)
|
||||
fprintf(out, ", subdevice=%i", info.id.subdevice);
|
||||
fprintf(out, ", name='%s'", info.id.name);
|
||||
if (info.id.index > 0)
|
||||
fprintf(out, ", index=%i", info.id.index);
|
||||
fprintf(out, "}, ");
|
||||
switch (info.type) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN: fprintf(out, "bool={"); break;
|
||||
case SND_CONTROL_TYPE_INTEGER: fprintf(out, "int={"); break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED: fprintf(out, "enum={"); break;
|
||||
case SND_CONTROL_TYPE_BYTES: fprintf(out, "byte={"); break;
|
||||
default: break;
|
||||
}
|
||||
for (idx = 0; idx < info.values_count; idx++) {
|
||||
if (idx > 0)
|
||||
fprintf(out, ",");
|
||||
switch (info.type) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
fprintf(out, ", %s", control->c.value.integer.value[idx] ? "true" : "false");
|
||||
fprintf(out, "%s", control->c.value.integer.value[idx] ? "true" : "false");
|
||||
break;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
fprintf(out, ", %li", control->c.value.integer.value[idx]);
|
||||
fprintf(out, "%li", control->c.value.integer.value[idx]);
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
fprintf(out, ", %u", control->c.value.enumerated.item[idx]);
|
||||
fprintf(out, "%u", control->c.value.enumerated.item[idx]);
|
||||
break;
|
||||
case SND_CONTROL_TYPE_BYTES:
|
||||
if (idx > 0)
|
||||
fprintf(out, ":");
|
||||
fprintf(out, "%02x", control->c.value.bytes.data[idx]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info.type == SND_CONTROL_TYPE_BYTES)
|
||||
fprintf(out, ")");
|
||||
fprintf(out, ")\n");
|
||||
fprintf(out, "})\n");
|
||||
}
|
||||
|
||||
static void soundcard_setup_write_controls(FILE *out, const char *space, int card, struct ctl_control **controls)
|
||||
|
|
Loading…
Reference in a new issue