alsa-utils/alsactl/utils.c
Jaroslav Kysela cc5c3357cf alsactl: add the daemon mode
For the plug-and-play hardware, like USB devices, it may be helpful
to manage the sound state periodically, before the devices are removed.

This change implements new commands 'daemon' and 'rdaemon' to save
the sound state in defined intervals when the sound controls are changed.

The udev rules can notify the daemon using the 'kill' or 'nrestore'
commands to rescan available cards in the system.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
2013-04-05 13:47:18 +02:00

180 lines
3.8 KiB
C

/*
* Advanced Linux Sound Architecture Control Program - Support routines
* Copyright (c) by Jaroslav Kysela <perex@perex.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <dirent.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <alsa/asoundlib.h>
#include "alsactl.h"
int file_map(const char *filename, char **buf, size_t *bufsize)
{
struct stat stats;
int fd;
fd = open(filename, O_RDONLY);
if (fd < 0) {
return -1;
}
if (fstat(fd, &stats) < 0) {
close(fd);
return -1;
}
*buf = mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (*buf == MAP_FAILED) {
close(fd);
return -1;
}
*bufsize = stats.st_size;
close(fd);
return 0;
}
void file_unmap(void *buf, size_t bufsize)
{
munmap(buf, bufsize);
}
size_t line_width(const char *buf, size_t bufsize, size_t pos)
{
int esc = 0;
size_t count;
for (count = pos; count < bufsize; count++) {
if (!esc && buf[count] == '\n')
break;
esc = buf[count] == '\\';
}
return count - pos;
}
void initfailed(int cardnumber, const char *reason, int exitcode)
{
int fp;
char *str;
char sexitcode[16];
if (statefile == NULL)
return;
if (snd_card_get_name(cardnumber, &str) < 0)
return;
sprintf(sexitcode, "%i", exitcode);
fp = open(statefile, O_WRONLY|O_CREAT|O_APPEND, 0644);
write(fp, str, strlen(str));
write(fp, ":", 1);
write(fp, reason, strlen(reason));
write(fp, ":", 1);
write(fp, sexitcode, strlen(sexitcode));
write(fp, "\n", 1);
close(fp);
free(str);
}
static void syslog_(int prio, const char *fcn, long line,
const char *fmt, va_list ap)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%s: %s:%ld", command, fcn, line);
buf[sizeof(buf)-1] = '\0';
vsnprintf(buf + strlen(buf), sizeof(buf)-strlen(buf), fmt, ap);
buf[sizeof(buf)-1] = '\0';
syslog(LOG_INFO, buf);
}
void info_(const char *fcn, long line, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (use_syslog) {
syslog_(LOG_INFO, fcn, line, fmt, ap);
} else {
fprintf(stdout, "%s: %s:%ld: ", command, fcn, line);
vfprintf(stdout, fmt, ap);
putc('\n', stdout);
}
va_end(ap);
}
void error_(const char *fcn, long line, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (use_syslog) {
syslog_(LOG_ERR, fcn, line, fmt, ap);
} else {
fprintf(stderr, "%s: %s:%ld: ", command, fcn, line);
vfprintf(stderr, fmt, ap);
putc('\n', stderr);
}
va_end(ap);
}
void cerror_(const char *fcn, long line, int cond, const char *fmt, ...)
{
va_list ap;
if (!cond && !debugflag)
return;
if (use_syslog) {
syslog_(LOG_ERR, fcn, line, fmt, ap);
} else {
va_start(ap, fmt);
fprintf(stderr, "%s: %s:%ld: ", command, fcn, line);
vfprintf(stderr, fmt, ap);
putc('\n', stderr);
va_end(ap);
}
}
void dbg_(const char *fcn, long line, const char *fmt, ...)
{
va_list ap;
if (!debugflag)
return;
if (use_syslog) {
syslog_(LOG_DEBUG, fcn, line, fmt, ap);
} else {
va_start(ap, fmt);
fprintf(stderr, "%s: %s:%ld: ", command, fcn, line);
vfprintf(stderr, fmt, ap);
putc('\n', stderr);
va_end(ap);
}
}