mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 12:06:31 +01:00
Rewritten alsactl
This commit is contained in:
parent
6add1cdfb5
commit
8c4e1aa769
7 changed files with 929 additions and 1281 deletions
|
@ -1,10 +1,4 @@
|
|||
sbin_PROGRAMS=alsactl
|
||||
noinst_HEADERS=alsactl.h
|
||||
man_MANS=alsactl.1
|
||||
|
||||
alsactl_SOURCES=alsactl.c alsactl_parser.y setup.c merge.c alsactl_lexer.l
|
||||
YFLAGS=-d
|
||||
|
||||
# lexer / parser debug
|
||||
#CFLAGS=-pipe -g -DYYDEBUG
|
||||
#LFLAGS=-d
|
||||
alsactl_SOURCES=alsactl.c
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture Control Program
|
||||
* Copyright (c) 1997 by Perex, APS, University of South Bohemia
|
||||
*
|
||||
*
|
||||
* 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 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/asoundlib.h>
|
||||
|
||||
#define ALSACTL_FILE "/etc/asound.conf"
|
||||
|
||||
#define LEFT 1
|
||||
#define RIGHT 2
|
||||
|
||||
#define OUTPUT 0
|
||||
#define INPUT 1
|
||||
|
||||
extern int debugflag;
|
||||
|
||||
extern void error(const char *fmt,...);
|
||||
|
||||
struct ctl_control {
|
||||
int change;
|
||||
snd_control_type_t type;
|
||||
snd_control_info_t info;
|
||||
snd_control_t c;
|
||||
struct ctl_control *next;
|
||||
};
|
||||
|
||||
struct ctl {
|
||||
snd_ctl_hw_info_t hwinfo;
|
||||
struct ctl_control *controls;
|
||||
};
|
||||
|
||||
struct soundcard {
|
||||
int no; /* card number */
|
||||
struct ctl control;
|
||||
struct soundcard *next;
|
||||
};
|
||||
|
||||
extern struct soundcard *soundcards;
|
||||
extern struct soundcard *rsoundcards; /* read soundcards */
|
||||
|
||||
void soundcard_setup_init(void);
|
||||
void soundcard_setup_done(void);
|
||||
int soundcard_setup_load(const char *filename, int skip);
|
||||
int soundcard_setup_write(const char *filename, int cardno);
|
||||
int soundcard_setup_collect_controls(int cardno);
|
||||
int soundcard_setup_merge_controls(int cardno);
|
||||
int soundcard_setup_process_controls(int cardno);
|
||||
|
||||
char *control_id(snd_control_id_t *id);
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture Control Program
|
||||
* Copyright (c) 1998 by Perex, APS, University of South Bohemia
|
||||
*
|
||||
*
|
||||
* 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 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include "alsactl.h"
|
||||
|
||||
struct bytearray {
|
||||
unsigned char *data;
|
||||
size_t datalen;
|
||||
};
|
||||
|
||||
#include "alsactl_parser.h"
|
||||
|
||||
#define YY_NO_UNPUT
|
||||
#undef YY_CDECL
|
||||
#define YY_CDECL int YY_PROTO(yylex( void ));
|
||||
|
||||
int linecount;
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
/* special characters */
|
||||
|
||||
"{"|"}" return yytext[0];
|
||||
"("|")" return yytext[0];
|
||||
"["|"]" return yytext[0];
|
||||
")"[ \t]*"{" return L_DOUBLE1;
|
||||
"," return yytext[0];
|
||||
"=" return yytext[0];
|
||||
|
||||
/* tokens */
|
||||
|
||||
soundcard return L_SOUNDCARD;
|
||||
control return L_CONTROL;
|
||||
|
||||
global return L_GLOBAL;
|
||||
hwdep return L_HWDEP;
|
||||
mixer return L_MIXER;
|
||||
pcm return L_PCM;
|
||||
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;
|
||||
true|on|yes return L_TRUE;
|
||||
|
||||
/* integers */
|
||||
|
||||
[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; }
|
||||
|
||||
/* strings */
|
||||
|
||||
\"[^\"]*\" { yytext[strlen(yytext) - 1] = 0;
|
||||
yylval.s_value = strdup(&yytext[1]);
|
||||
return L_STRING; }
|
||||
\'[^\']*\' { yytext[strlen(yytext) - 1] = 0;
|
||||
yylval.s_value = strdup(&yytext[1]);
|
||||
return L_STRING; }
|
||||
[a-z0-9/\~@-Za-z_]+ { yylval.s_value = strdup(yytext);
|
||||
return L_STRING; }
|
||||
$[a-z0-9/\~@-Za-z_]+ { yylval.s_value = strdup(getenv(&yytext[1]));
|
||||
return L_STRING; }
|
||||
|
||||
/* comments & whitespaces */
|
||||
|
||||
[#\;][^\n]*\n { linecount++; }
|
||||
[ \t]+ ;
|
||||
\n { linecount++; }
|
||||
. fprintf( stderr, "alsactl: discarding char '%c' - line %i\n", yytext[0], linecount + 1 );
|
||||
|
||||
%%
|
||||
|
||||
#ifndef yywrap
|
||||
int yywrap(void) /* do this avoid to do -lfl */
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
|
@ -1,319 +0,0 @@
|
|||
%{
|
||||
|
||||
/*
|
||||
* Advanced Linux Sound Architecture Control Program
|
||||
* Copyright (c) 1998 by Perex, APS, University of South Bohemia
|
||||
*
|
||||
*
|
||||
* 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 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "alsactl.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
/* insgus_lexer.c */
|
||||
|
||||
int yylex( void );
|
||||
|
||||
extern char cfgfile[];
|
||||
extern int linecount;
|
||||
extern FILE *yyin;
|
||||
|
||||
/* structure for byte arrays */
|
||||
|
||||
struct bytearray {
|
||||
unsigned char *data;
|
||||
size_t datalen;
|
||||
};
|
||||
|
||||
/* local functions */
|
||||
|
||||
static void yyerror(char *, ...);
|
||||
|
||||
static void build_soundcard(char *name);
|
||||
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);
|
||||
|
||||
/* local variables */
|
||||
|
||||
static struct soundcard *Xsoundcard = NULL;
|
||||
static struct ctl_control *Xcontrol = NULL;
|
||||
static int Xposition = 0;
|
||||
static snd_control_type_t Xtype = SND_CONTROL_TYPE_NONE;
|
||||
|
||||
%}
|
||||
|
||||
%start lines
|
||||
|
||||
%union {
|
||||
int b_value;
|
||||
long i_value;
|
||||
char *s_value;
|
||||
struct bytearray a_value;
|
||||
};
|
||||
|
||||
%token <b_value> L_TRUE L_FALSE
|
||||
%token <i_value> L_INTEGER
|
||||
%token <s_value> L_STRING
|
||||
%token <a_value> L_BYTEARRAY
|
||||
|
||||
/* types */
|
||||
%token L_INTEGER L_STRING
|
||||
/* boolean */
|
||||
%token L_FALSE L_TRUE
|
||||
/* misc */
|
||||
%token L_DOUBLE1
|
||||
/* 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
|
||||
%type <s_value> string
|
||||
%type <a_value> rawdata
|
||||
|
||||
%%
|
||||
|
||||
lines : line
|
||||
| lines line
|
||||
;
|
||||
|
||||
line : L_SOUNDCARD '(' string { build_soundcard($3); }
|
||||
L_DOUBLE1 soundcards '}' { build_soundcard(NULL); }
|
||||
| error { yyerror("unknown keyword in top level"); }
|
||||
;
|
||||
|
||||
soundcards :
|
||||
| soundcards soundcard
|
||||
;
|
||||
|
||||
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
|
||||
;
|
||||
|
||||
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; }
|
||||
| L_MIXER { $$ = SND_CONTROL_IFACE_MIXER; }
|
||||
| L_PCM { $$ = SND_CONTROL_IFACE_PCM; }
|
||||
| L_RAWMIDI { $$ = SND_CONTROL_IFACE_RAWMIDI; }
|
||||
| L_TIMER { $$ = SND_CONTROL_IFACE_TIMER; }
|
||||
| L_SEQUENCER { $$ = SND_CONTROL_IFACE_SEQUENCER; }
|
||||
| error { yyerror( "an unknown keyword in the interface field"); }
|
||||
;
|
||||
|
||||
boolean : L_TRUE { $$ = 1; }
|
||||
| L_FALSE { $$ = 0; }
|
||||
;
|
||||
|
||||
integer : L_INTEGER { $$ = $1; }
|
||||
;
|
||||
|
||||
string : L_STRING { $$ = $1; }
|
||||
;
|
||||
|
||||
rawdata : L_RAWDATA '(' L_BYTEARRAY ')' { $$ = $3; }
|
||||
| L_RAWDATA error { yyerror( "malformed rawdata value" ); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
static void yyerror(char *string,...)
|
||||
{
|
||||
char errstr[1024];
|
||||
|
||||
va_list vars;
|
||||
va_start(vars, string);
|
||||
vsprintf(errstr, string, vars);
|
||||
va_end(vars);
|
||||
error("Error in configuration file '%s' (line %i): %s", cfgfile, linecount + 1, errstr);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void error_nomem(void)
|
||||
{
|
||||
yyerror("No enough memory...\n");
|
||||
}
|
||||
|
||||
static void build_soundcard(char *name)
|
||||
{
|
||||
struct soundcard *soundcard;
|
||||
|
||||
if (!name) {
|
||||
Xsoundcard = NULL;
|
||||
return;
|
||||
}
|
||||
Xsoundcard = (struct soundcard *)malloc(sizeof(struct soundcard));
|
||||
if (!Xsoundcard) {
|
||||
free(name);
|
||||
error_nomem();
|
||||
return;
|
||||
}
|
||||
bzero(Xsoundcard, sizeof(*Xsoundcard));
|
||||
for (soundcard = rsoundcards; soundcard && soundcard->next; soundcard = soundcard->next);
|
||||
if (soundcard) {
|
||||
soundcard->next = Xsoundcard;
|
||||
} else {
|
||||
rsoundcards = Xsoundcard;
|
||||
}
|
||||
strncpy(Xsoundcard->control.hwinfo.id, name, sizeof(Xsoundcard->control.hwinfo.id));
|
||||
free(name);
|
||||
}
|
||||
|
||||
static void build_control_begin(void)
|
||||
{
|
||||
struct ctl_control **first;
|
||||
struct ctl_control *ctl;
|
||||
|
||||
first = &Xsoundcard->control.controls;
|
||||
Xcontrol = (struct ctl_control *)malloc(sizeof(struct ctl_control));
|
||||
if (!Xcontrol) {
|
||||
error_nomem();
|
||||
return;
|
||||
}
|
||||
Xposition = 0;
|
||||
Xtype = SND_CONTROL_TYPE_NONE;
|
||||
bzero(Xcontrol, sizeof(*Xcontrol));
|
||||
for (ctl = *first; ctl && ctl->next; ctl = ctl->next);
|
||||
if (ctl) {
|
||||
ctl->next = Xcontrol;
|
||||
} else {
|
||||
*first = Xcontrol;
|
||||
}
|
||||
}
|
||||
|
||||
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_BOOLEAN:
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
|
||||
break;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
|
||||
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)
|
||||
{
|
||||
if (Xposition >= 512)
|
||||
yyerror("Array overflow.");
|
||||
switch (Xtype) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
170
alsactl/merge.c
170
alsactl/merge.c
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture Control Program
|
||||
* Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
|
||||
*
|
||||
*
|
||||
* 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 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "alsactl.h"
|
||||
|
||||
static int merge_one_control(struct ctl_control *cctl, struct ctl_control *uctl, int cardno)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (!(cctl->info.access & SND_CONTROL_ACCESS_WRITE))
|
||||
return 0;
|
||||
switch (cctl->info.type) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
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;
|
||||
}
|
||||
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];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
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.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.enumerated.item[idx]) {
|
||||
cctl->change = 1;
|
||||
cctl->c.value.enumerated.item[idx] = uctl->c.value.enumerated.item[idx];
|
||||
}
|
||||
}
|
||||
break;
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("The control type %i is not known.", cctl->type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int soundcard_setup_merge_control(struct ctl_control *cctl, struct ctl_control *uctl, int cardno)
|
||||
{
|
||||
struct ctl_control *cctl1;
|
||||
|
||||
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 &&
|
||||
!strncmp(cctl1->c.id.name, uctl->c.id.name, sizeof(cctl1->c.id.name)) &&
|
||||
cctl1->c.id.index == uctl->c.id.index) {
|
||||
merge_one_control(cctl1, uctl, cardno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cctl1) {
|
||||
error("Cannot find the control %s...", control_id(&uctl->c.id));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int soundcard_setup_merge_controls(int cardno)
|
||||
{
|
||||
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;
|
||||
soundcard_setup_merge_control(soundcard->control.controls, rsoundcard->control.controls, soundcard->no);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int soundcard_open_ctl(snd_ctl_t **ctlhandle, struct soundcard *soundcard)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int soundcard_setup_process_controls(int cardno)
|
||||
{
|
||||
int err;
|
||||
snd_ctl_t *ctlhandle = NULL;
|
||||
struct soundcard *soundcard;
|
||||
struct ctl_control *ctl;
|
||||
|
||||
for (soundcard = soundcards; soundcard; soundcard = soundcard->next) {
|
||||
if (cardno >= 0 && soundcard->no != cardno)
|
||||
continue;
|
||||
for (ctl = soundcard->control.controls; ctl; ctl = ctl->next) {
|
||||
if (ctl->change)
|
||||
if (!soundcard_open_ctl(&ctlhandle, soundcard)) {
|
||||
if ((err = snd_ctl_cwrite(ctlhandle, &ctl->c)) < 0)
|
||||
error("Control '%s' write error: %s", control_id(&ctl->c.id), snd_strerror(err));
|
||||
}
|
||||
}
|
||||
if (ctlhandle) {
|
||||
snd_ctl_close(ctlhandle);
|
||||
ctlhandle = NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
530
alsactl/setup.c
530
alsactl/setup.c
|
@ -1,530 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture Control Program
|
||||
* Copyright (c) 1997 by Perex, APS, University of South Bohemia
|
||||
*
|
||||
*
|
||||
* 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 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "alsactl.h"
|
||||
|
||||
#define SND_INTERFACE_CONTROL 0
|
||||
#define SND_INTERFACE_MIXER 1
|
||||
#define SND_INTERFACE_PCM 2
|
||||
#define SND_INTERFACE_RAWMIDI 3
|
||||
|
||||
extern int yyparse(void);
|
||||
extern int linecount;
|
||||
extern FILE *yyin;
|
||||
extern int yydebug;
|
||||
struct soundcard *soundcards = NULL;
|
||||
struct soundcard *rsoundcards = NULL;
|
||||
|
||||
/*
|
||||
* misc functions
|
||||
*/
|
||||
|
||||
char *control_id(snd_control_id_t *id)
|
||||
{
|
||||
static char str[128];
|
||||
|
||||
if (!id)
|
||||
return "???";
|
||||
sprintf(str, "%i,%i,%i,%s,%i", id->iface, id->device, id->subdevice, id->name, id->index);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* free functions
|
||||
*/
|
||||
|
||||
static void soundcard_ctl_control_free(struct ctl_control *first)
|
||||
{
|
||||
struct ctl_control *next;
|
||||
|
||||
while (first) {
|
||||
next = first->next;
|
||||
free(first);
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void soundcard_free1(struct soundcard *soundcard)
|
||||
{
|
||||
if (!soundcard)
|
||||
return;
|
||||
soundcard_ctl_control_free(soundcard->control.controls);
|
||||
free(soundcard);
|
||||
}
|
||||
|
||||
static void soundcard_free(struct soundcard *first)
|
||||
{
|
||||
struct soundcard *next;
|
||||
|
||||
while (first) {
|
||||
next = first->next;
|
||||
soundcard_free1(first);
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
static int soundcard_remove(int cardno)
|
||||
{
|
||||
struct soundcard *first, *prev = NULL, *next;
|
||||
|
||||
first = soundcards;
|
||||
while (first) {
|
||||
next = first->next;
|
||||
if (first->no == cardno) {
|
||||
soundcard_free1(first);
|
||||
if (!prev)
|
||||
soundcards = next;
|
||||
else
|
||||
prev->next = next;
|
||||
return 0;
|
||||
}
|
||||
prev = first;
|
||||
first = first->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* exported functions
|
||||
*/
|
||||
|
||||
void soundcard_setup_init(void)
|
||||
{
|
||||
soundcards = NULL;
|
||||
}
|
||||
|
||||
void soundcard_setup_done(void)
|
||||
{
|
||||
soundcard_free(soundcards);
|
||||
soundcard_free(rsoundcards);
|
||||
soundcards = NULL;
|
||||
}
|
||||
|
||||
static int determine_controls(void *handle, struct ctl_control **cctl)
|
||||
{
|
||||
int err, idx;
|
||||
snd_control_list_t list;
|
||||
snd_control_id_t *item;
|
||||
snd_control_t ctl;
|
||||
struct ctl_control *prev_control;
|
||||
struct ctl_control *new_control;
|
||||
|
||||
*cctl = NULL;
|
||||
bzero(&list, sizeof(list));
|
||||
if ((err = snd_ctl_clist(handle, &list)) < 0) {
|
||||
error("Cannot determine controls: %s", snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
if (list.controls <= 0)
|
||||
return 0;
|
||||
list.controls_request = list.controls + 16;
|
||||
list.controls_offset = list.controls_count = 0;
|
||||
list.pids = malloc(sizeof(snd_control_id_t) * list.controls_request);
|
||||
if (!list.pids) {
|
||||
error("No enough memory...");
|
||||
return 1;
|
||||
}
|
||||
if ((err = snd_ctl_clist(handle, &list)) < 0) {
|
||||
error("Cannot determine controls (2): %s", snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
for (idx = 0, prev_control = NULL; idx < list.controls_count; idx++) {
|
||||
item = &list.pids[idx];
|
||||
bzero(&ctl, sizeof(ctl));
|
||||
ctl.id = *item;
|
||||
if ((err = snd_ctl_cread(handle, &ctl)) < 0) {
|
||||
error("Cannot read control '%s': %s", control_id(item), snd_strerror(err));
|
||||
free(list.pids);
|
||||
return 1;
|
||||
}
|
||||
new_control = malloc(sizeof(*new_control));
|
||||
if (!new_control) {
|
||||
error("No enough memory...");
|
||||
free(list.pids);
|
||||
return 1;
|
||||
}
|
||||
bzero(new_control, sizeof(*new_control));
|
||||
memcpy(&new_control->c, &ctl, sizeof(new_control->c));
|
||||
new_control->info.id = ctl.id;
|
||||
if ((err = snd_ctl_cinfo(handle, &new_control->info)) < 0) {
|
||||
error("Cannot read control info '%s': %s", control_id(item), snd_strerror(err));
|
||||
free(new_control);
|
||||
free(list.pids);
|
||||
return 1;
|
||||
}
|
||||
if (*cctl) {
|
||||
prev_control->next = new_control;
|
||||
prev_control = new_control;
|
||||
} else {
|
||||
*cctl = prev_control = new_control;
|
||||
}
|
||||
}
|
||||
free(list.pids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int soundcard_setup_collect_controls1(int cardno)
|
||||
{
|
||||
snd_ctl_t *handle;
|
||||
struct soundcard *card, *first, *prev;
|
||||
int err;
|
||||
|
||||
soundcard_remove(cardno);
|
||||
if ((err = snd_ctl_open(&handle, cardno)) < 0) {
|
||||
error("SND CTL open error: %s", snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
/* --- */
|
||||
card = (struct soundcard *) malloc(sizeof(struct soundcard));
|
||||
if (!card) {
|
||||
snd_ctl_close(handle);
|
||||
error("malloc error");
|
||||
return 1;
|
||||
}
|
||||
bzero(card, sizeof(struct soundcard));
|
||||
card->no = cardno;
|
||||
for (first = soundcards, prev = NULL; first; first = first->next) {
|
||||
if (first->no > cardno) {
|
||||
if (!prev) {
|
||||
soundcards = card;
|
||||
} else {
|
||||
prev->next = card;
|
||||
}
|
||||
card->next = first;
|
||||
break;
|
||||
}
|
||||
prev = first;
|
||||
}
|
||||
if (!first) {
|
||||
if (!soundcards) {
|
||||
soundcards = card;
|
||||
} else {
|
||||
prev->next = card;
|
||||
}
|
||||
}
|
||||
if ((err = snd_ctl_hw_info(handle, &card->control.hwinfo)) < 0) {
|
||||
snd_ctl_close(handle);
|
||||
error("SND CTL HW INFO error: %s", snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
/* --- */
|
||||
if (determine_controls(handle, &card->control.controls)) {
|
||||
snd_ctl_close(handle);
|
||||
return 1;
|
||||
}
|
||||
/* --- */
|
||||
snd_ctl_close(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int soundcard_setup_collect_controls(int cardno)
|
||||
{
|
||||
int err;
|
||||
unsigned int mask;
|
||||
|
||||
if (cardno >= 0) {
|
||||
return soundcard_setup_collect_controls1(cardno);
|
||||
} else {
|
||||
mask = snd_cards_mask();
|
||||
for (cardno = 0; cardno < SND_CARDS; cardno++) {
|
||||
if (!(mask & (1 << cardno)))
|
||||
continue;
|
||||
err = soundcard_setup_collect_controls1(cardno);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int soundcard_setup_load(const char *cfgfile, int skip)
|
||||
{
|
||||
extern int yyparse(void);
|
||||
extern int linecount;
|
||||
extern FILE *yyin;
|
||||
#ifdef YYDEBUG
|
||||
extern int yydebug;
|
||||
#endif
|
||||
int xtry;
|
||||
|
||||
#ifdef YYDEBUG
|
||||
yydebug = 1;
|
||||
#endif
|
||||
if (debugflag)
|
||||
printf("cfgfile = '%s'\n", cfgfile);
|
||||
if (skip && access(cfgfile, R_OK))
|
||||
return 0;
|
||||
if ((yyin = fopen(cfgfile, "r")) == NULL) {
|
||||
error("Cannot open configuration file '%s'...", cfgfile);
|
||||
return 1;
|
||||
}
|
||||
linecount = 0;
|
||||
xtry = yyparse();
|
||||
fclose(yyin);
|
||||
if (debugflag)
|
||||
printf("Config ok..\n");
|
||||
if (xtry)
|
||||
error("Ignored error in configuration file '%s'...", cfgfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void soundcard_setup_write_control(FILE * out, const char *space, int card, struct ctl_control *control)
|
||||
{
|
||||
char *s, v[16];
|
||||
int err, idx;
|
||||
snd_ctl_t *handle;
|
||||
snd_control_info_t info;
|
||||
|
||||
memcpy(&info, &control->info, sizeof(info));
|
||||
v[0] = '\0';
|
||||
switch (info.type) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN: s = "bool"; break;
|
||||
case SND_CONTROL_TYPE_INTEGER: s = "integer"; break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED: s = "enumerated"; break;
|
||||
case SND_CONTROL_TYPE_BYTES: s = "bytes"; break;
|
||||
default: s = "unknown";
|
||||
}
|
||||
fprintf(out, "\n%s; The type is '%s'. Access:", space, s);
|
||||
if (info.access & SND_CONTROL_ACCESS_READ)
|
||||
fprintf(out, " read");
|
||||
if (info.access & SND_CONTROL_ACCESS_WRITE)
|
||||
fprintf(out, " write");
|
||||
if (info.access & SND_CONTROL_ACCESS_INACTIVE)
|
||||
fprintf(out, " inactive");
|
||||
fprintf(out, ". Count is %i.\n", info.values_count);
|
||||
switch (info.type) {
|
||||
case SND_CONTROL_TYPE_BOOLEAN:
|
||||
if (info.value.integer.min != 0 || info.value.integer.max != 1 ||
|
||||
info.value.integer.step != 0)
|
||||
error("Wrong control '%s' (boolean)\n", control_id(&info.id));
|
||||
break;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
fprintf(out, "%s; The range is %li-%li (step %li)\n", space, info.value.integer.min, info.value.integer.max, info.value.integer.step);
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
if ((err = snd_ctl_open(&handle, card)) >= 0) {
|
||||
for (idx = 0; idx < info.value.enumerated.items; idx++) {
|
||||
info.value.enumerated.item = idx;
|
||||
if (snd_ctl_cinfo(handle, &info) >= 0)
|
||||
fprintf(out, "%s; Item #%i - %s\n", space, idx, info.value.enumerated.name);
|
||||
}
|
||||
snd_ctl_close(handle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (info.id.iface) {
|
||||
case SND_CONTROL_IFACE_CARD: s = "global"; break;
|
||||
case SND_CONTROL_IFACE_HWDEP: s = "hwdep"; break;
|
||||
case SND_CONTROL_IFACE_MIXER: s = "mixer"; break;
|
||||
case SND_CONTROL_IFACE_PCM: s = "pcm"; break;
|
||||
case SND_CONTROL_IFACE_RAWMIDI: s = "rawmidi"; break;
|
||||
case SND_CONTROL_IFACE_TIMER: s = "timer"; break;
|
||||
case SND_CONTROL_IFACE_SEQUENCER: s = "sequencer"; break;
|
||||
default: sprintf(v, "%i", info.id.iface); s = v; break;
|
||||
}
|
||||
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");
|
||||
break;
|
||||
case SND_CONTROL_TYPE_INTEGER:
|
||||
fprintf(out, "%li", control->c.value.integer.value[idx]);
|
||||
break;
|
||||
case SND_CONTROL_TYPE_ENUMERATED:
|
||||
fprintf(out, "%u", control->c.value.enumerated.item[idx]);
|
||||
break;
|
||||
case SND_CONTROL_TYPE_BYTES:
|
||||
fprintf(out, "%02x", control->c.value.bytes.data[idx]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(out, "})\n");
|
||||
}
|
||||
|
||||
static void soundcard_setup_write_controls(FILE *out, const char *space, int card, struct ctl_control **controls)
|
||||
{
|
||||
struct ctl_control *ctl;
|
||||
|
||||
if (!(*controls))
|
||||
return;
|
||||
for (ctl = *controls; ctl; ctl = ctl->next)
|
||||
soundcard_setup_write_control(out, space, card, ctl);
|
||||
}
|
||||
|
||||
#define MAX_LINE (32 * 1024)
|
||||
|
||||
int soundcard_setup_write(const char *cfgfile, int cardno)
|
||||
{
|
||||
FILE *out, *out1, *out2, *in;
|
||||
char *tmpfile1, *tmpfile2;
|
||||
struct soundcard *first, *sel = NULL;
|
||||
char *line, cardname[sizeof(first->control.hwinfo.name)+16], *ptr1;
|
||||
int mark, size, ok;
|
||||
|
||||
tmpfile1 = (char *)malloc(strlen(cfgfile) + 16);
|
||||
tmpfile2 = (char *)malloc(strlen(cfgfile) + 16);
|
||||
if (!tmpfile1 || !tmpfile2) {
|
||||
error("No enough memory...\n");
|
||||
if (tmpfile1)
|
||||
free(tmpfile1);
|
||||
if (tmpfile2)
|
||||
free(tmpfile2);
|
||||
return 1;
|
||||
}
|
||||
strcpy(tmpfile1, cfgfile);
|
||||
strcat(tmpfile1, ".new");
|
||||
strcpy(tmpfile2, cfgfile);
|
||||
strcat(tmpfile2, ".insert");
|
||||
|
||||
if (cardno >= 0) {
|
||||
line = (char *)malloc(MAX_LINE);
|
||||
if (!line) {
|
||||
error("No enough memory...\n");
|
||||
return 1;
|
||||
}
|
||||
if ((in = fopen(cfgfile, "r")) == NULL)
|
||||
cardno = -1;
|
||||
} else {
|
||||
line = NULL;
|
||||
in = NULL;
|
||||
}
|
||||
if ((out = out1 = fopen(tmpfile1, "w+")) == NULL) {
|
||||
error("Cannot open file '%s' for writing...\n", tmpfile1);
|
||||
return 1;
|
||||
}
|
||||
fprintf(out, "# ALSA driver configuration\n");
|
||||
fprintf(out, "# This configuration is generated with the alsactl program.\n");
|
||||
fprintf(out, "\n");
|
||||
if (cardno >= 0) {
|
||||
if ((out = out2 = fopen(tmpfile2, "w+")) == NULL) {
|
||||
error("Cannot open file '%s' for writing...\n", tmpfile2);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
out2 = NULL;
|
||||
}
|
||||
for (first = soundcards; first; first = first->next) {
|
||||
if (cardno >= 0 && first->no != cardno)
|
||||
continue;
|
||||
sel = first;
|
||||
fprintf(out, "soundcard(\"%s\") {\n", first->control.hwinfo.id);
|
||||
if (first->control.controls) {
|
||||
soundcard_setup_write_controls(out, " ", first->no, &first->control.controls);
|
||||
}
|
||||
fprintf(out, "}\n%s", cardno < 0 && first->next ? "\n" : "");
|
||||
}
|
||||
/* merge the old and new text */
|
||||
if (cardno >= 0) {
|
||||
fseek(out2, 0, SEEK_SET);
|
||||
mark = ok = 0;
|
||||
__1:
|
||||
while (fgets(line, MAX_LINE - 1, in)) {
|
||||
line[MAX_LINE - 1] = '\0';
|
||||
if (!strncmp(line, "soundcard(", 10))
|
||||
break;
|
||||
}
|
||||
while (!feof(in)) {
|
||||
ptr1 = line + 10;
|
||||
while (*ptr1 && *ptr1 != '"')
|
||||
ptr1++;
|
||||
if (*ptr1)
|
||||
ptr1++;
|
||||
strncpy(cardname, sel->control.hwinfo.id, sizeof(sel->control.hwinfo.id));
|
||||
cardname[sizeof(sel->control.hwinfo.id)] = '\0';
|
||||
strcat(cardname, "\"");
|
||||
if (!strncmp(ptr1, cardname, strlen(cardname))) {
|
||||
if (mark)
|
||||
fprintf(out1, "\n");
|
||||
do {
|
||||
size = fread(line, 1, MAX_LINE, out2);
|
||||
if (size > 0)
|
||||
fwrite(line, 1, size, out1);
|
||||
} while (size > 0);
|
||||
mark = ok = 1;
|
||||
goto __1;
|
||||
} else {
|
||||
if (mark)
|
||||
fprintf(out1, "\n");
|
||||
fprintf(out1, line);
|
||||
while (fgets(line, MAX_LINE - 1, in)) {
|
||||
line[MAX_LINE - 1] = '\0';
|
||||
fprintf(out1, line);
|
||||
if (line[0] == '}') {
|
||||
mark = 1;
|
||||
goto __1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
if (mark)
|
||||
fprintf(out1, "\n");
|
||||
do {
|
||||
size = fread(line, 1, MAX_LINE, out2);
|
||||
printf("size = %i\n", size);
|
||||
if (size > 0)
|
||||
fwrite(line, 1, size, out1);
|
||||
} while (size > 0);
|
||||
}
|
||||
}
|
||||
if (in)
|
||||
fclose(in);
|
||||
if (out2)
|
||||
fclose(out2);
|
||||
if (!access(cfgfile, F_OK) && remove(cfgfile))
|
||||
error("Cannot remove file '%s'...", cfgfile);
|
||||
if (rename(tmpfile1, cfgfile) < 0)
|
||||
error("Cannot rename file '%s' to '%s'...", tmpfile1, cfgfile);
|
||||
fclose(out1);
|
||||
if (line)
|
||||
free(line);
|
||||
if (tmpfile2) {
|
||||
remove(tmpfile2);
|
||||
free(tmpfile2);
|
||||
}
|
||||
if (tmpfile1) {
|
||||
remove(tmpfile1);
|
||||
free(tmpfile1);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue