diff --git a/README.md b/README.md
index 665e061..3f38698 100644
--- a/README.md
+++ b/README.md
@@ -315,8 +315,9 @@ If cava quits unexpectedly or is force killed, echo must be turned on manually w
| --- | ----------- |
| up / down| increase/decrease sensitivity |
| left / right| increase/decrease bar width |
-| c / b| change forground/background color |
+| f / b| change forground/background color |
| r | Reload configuration |
+| c | Reload colors only |
| q or CTRL-C| Quit C.A.V.A. |
Configuration
@@ -332,6 +333,10 @@ For example:
$ pkill -USR1 cava
```
+Similarly, sending cava a SIGUSR2 signal will reload the colors fromt he configuring file, which is the same as pressing c in the terminal.
+```
+$ pkill -USR2 cava
+```
**Examples on how the equalizer works:**
diff --git a/cava.c b/cava.c
index 83c7cb0..f0f6ea7 100644
--- a/cava.c
+++ b/cava.c
@@ -85,6 +85,8 @@ int output_mode;
// whether we should reload the config or not
int should_reload = 0;
+// whether we should only reload colors or not
+int reload_colors = 0;
// general: cleanup
@@ -110,6 +112,11 @@ void sig_handler(int sig_no)
return;
}
+ if (sig_no == SIGUSR2) {
+ reload_colors = 1;
+ return;
+ }
+
cleanup();
if (sig_no == SIGINT) {
printf("CTRL-C pressed -- goodbye\n");
@@ -252,7 +259,8 @@ Keys:\n\
Left Decrease number of bars\n\
Right Increase number of bars\n\
r Reload config\n\
- c Cycle foreground color\n\
+ c Reload colors only\n\
+ f Cycle foreground color\n\
b Cycle background color\n\
q Quit\n\
\n\
@@ -286,6 +294,7 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
sigaction(SIGUSR1, &action, NULL);
+ sigaction(SIGUSR2, &action, NULL);
// general: handle command-line arguments
while ((c = getopt (argc, argv, "p:vh")) != -1) {
@@ -330,7 +339,12 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
while (1) {
//config: load
- load_config(configPath, supportedInput, (void *)&p);
+ struct error_s error;
+ error.length = 0;
+ if (!load_config(configPath, supportedInput, (void *)&p, 0, &error)) {
+ fprintf(stderr, "Error loading config. %s", error.message);
+ exit(EXIT_FAILURE);
+ }
output_mode = p.om;
@@ -627,7 +641,10 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
case 'r': //reload config
should_reload = 1;
break;
- case 'c': //change forground color
+ case 'c': //reload colors
+ reload_colors = 1;
+ break;
+ case 'f': //change forground color
if (p.col < 7) p.col++;
else p.col = 0;
resizeTerminal = true;
@@ -651,6 +668,18 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
}
+ if (reload_colors) {
+ struct error_s error;
+ error.length = 0;
+ if (!load_config(configPath, supportedInput, (void *)&p, 1, &error)) {
+ cleanup();
+ fprintf(stderr, "Error loading config. %s", error.message);
+ exit(EXIT_FAILURE);
+ }
+ resizeTerminal = true;
+ reload_colors = 0;
+ }
+
//if (cont == 0) break;
#ifdef DEBUG
diff --git a/config.c b/config.c
index 9caec1f..597c7d6 100644
--- a/config.c
+++ b/config.c
@@ -1,3 +1,4 @@
+#define MAX_ERROR_LEN 1024
double smoothDef[64] = {0.8, 0.8, 1, 1, 0.8, 0.8, 1, 0.8, 0.8, 1, 1, 0.8,
1, 1, 0.8, 0.6, 0.6, 0.7, 0.8, 0.8, 0.8, 0.8, 0.8,
@@ -21,17 +22,28 @@ int smcount, customEQ, im, om, col, bgcol, autobars, stereo, is_bin, ascii_range
};
+struct error_s {
+ char message[MAX_ERROR_LEN];
+ int length;
+};
+void write_errorf(void* err, const char* fmt, ...) {
+ struct error_s *error = (struct error_s *)err;
+ va_list args;
+ va_start(args, fmt);
+ error->length += vsnprintf((char*)error->message+error->length, MAX_ERROR_LEN-error->length, fmt, args);
+ va_end(args);
+}
-
-int validate_color(char *checkColor, int om)
+int validate_color(char *checkColor, int om, void* err)
{
+struct error_s *error = (struct error_s *)err;
int validColor = 0;
if (checkColor[0] == '#' && strlen(checkColor) == 7) {
// If the output mode is not ncurses, tell the user to use a named colour instead of hex colours.
if (om != 1 && om != 2) {
- fprintf(stderr, "Only 'ncurses' output method supports HTML colors. Please change the colours or the output method.\n");
- exit(EXIT_FAILURE);
+ write_errorf(error, "Only 'ncurses' output method supports HTML colors. Please change the colours or the output method.\n");
+ return 0;
}
// 0 to 9 and a to f
for (int i = 1; checkColor[i]; ++i) {
@@ -60,19 +72,73 @@ if (checkColor[0] == '#' && strlen(checkColor) == 7) {
return validColor;
}
-void validate_config(char supportedInput[255], void* params)
+bool validate_colors(void* params, void* err) {
+struct config_params *p = (struct config_params *)params;
+struct error_s *error = (struct error_s *)err;
+
+// validate: color
+if (!validate_color(p->color, p->om, error)) {
+ write_errorf(error, "The value for 'foreground' is invalid. It can be either one of the 7 named colors or a HTML color of the form '#xxxxxx'.\n");
+ return false;
+}
+
+// validate: background color
+if (!validate_color(p->bcolor, p->om, error)) {
+ write_errorf(error, "The value for 'background' is invalid. It can be either one of the 7 named colors or a HTML color of the form '#xxxxxx'.\n");
+ return false;
+}
+
+
+if (p->gradient) {
+ for(int i = 0;i < p->gradient_count;i++){
+ if (!validate_color(p->gradient_colors[i], p->om, error)) {
+ write_errorf(error, "Gradient color %d is invalid. It must be HTML color of the form '#xxxxxx'.\n", i+1);
+ return false;
+ }
+ }
+}
+
+// In case color is not html format set bgcol and col to predefinedint values
+p->col = 6;
+if (strcmp(p->color, "black") == 0) p->col = 0;
+if (strcmp(p->color, "red") == 0) p->col = 1;
+if (strcmp(p->color, "green") == 0) p->col = 2;
+if (strcmp(p->color, "yellow") == 0) p->col = 3;
+if (strcmp(p->color, "blue") == 0) p->col = 4;
+if (strcmp(p->color, "magenta") == 0) p->col = 5;
+if (strcmp(p->color, "cyan") == 0) p->col = 6;
+if (strcmp(p->color, "white") == 0) p->col = 7;
+// default if invalid
+
+// validate: background color
+if (strcmp(p->bcolor, "black") == 0) p->bgcol = 0;
+if (strcmp(p->bcolor, "red") == 0) p->bgcol = 1;
+if (strcmp(p->bcolor, "green") == 0) p->bgcol = 2;
+if (strcmp(p->bcolor, "yellow") == 0) p->bgcol = 3;
+if (strcmp(p->bcolor, "blue") == 0) p->bgcol = 4;
+if (strcmp(p->bcolor, "magenta") == 0) p->bgcol = 5;
+if (strcmp(p->bcolor, "cyan") == 0) p->bgcol = 6;
+if (strcmp(p->bcolor, "white") == 0) p->bgcol = 7;
+// default if invalid
+
+return true;
+}
+
+
+bool validate_config(char supportedInput[255], void* params, void* err)
{
struct config_params *p = (struct config_params *)params;
+struct error_s *error = (struct error_s *)err;
// validate: input method
p->im = 0;
if (strcmp(inputMethod, "alsa") == 0) {
p->im = 1;
#ifndef ALSA
- fprintf(stderr,
+ write_errorf(error,
"cava was built without alsa support, install alsa dev files and run make clean && ./configure && make again\n");
- exit(EXIT_FAILURE);
+ return false;
#endif
}
if (strcmp(inputMethod, "fifo") == 0) {
@@ -81,24 +147,23 @@ if (strcmp(inputMethod, "fifo") == 0) {
if (strcmp(inputMethod, "pulse") == 0) {
p->im = 3;
#ifndef PULSE
- fprintf(stderr,
+ write_errorf(error,
"cava was built without pulseaudio support, install pulseaudio dev files and run make clean && ./configure && make again\n");
- exit(EXIT_FAILURE);
+ return false;
#endif
}
if (strcmp(inputMethod, "sndio") == 0) {
p->im = 4;
#ifndef SNDIO
- fprintf(stderr, "cava was built without sndio support\n");
- exit(EXIT_FAILURE);
+ write_errorf(error, "cava was built without sndio support\n");
+ return false;
#endif
}
if (p->im == 0) {
- fprintf(stderr,
- "input method '%s' is not supported, supported methods are: %s\n",
+ write_errorf(error, "input method '%s' is not supported, supported methods are: %s\n",
inputMethod, supportedInput);
- exit(EXIT_FAILURE);
+ return false;
}
// validate: output method
@@ -107,17 +172,17 @@ if (strcmp(outputMethod, "ncurses") == 0) {
p->om = 1;
p->bgcol = -1;
#ifndef NCURSES
- fprintf(stderr,
+ write_errorf(error,
"cava was built without ncurses support, install ncursesw dev files and run make clean && ./configure && make again\n");
- exit(EXIT_FAILURE);
+ return false;
#endif
}
if (strcmp(outputMethod, "circle") == 0) {
p->om = 2;
#ifndef NCURSES
- fprintf(stderr,
+ write_errorf(error,
"cava was built without ncurses support, install ncursesw dev files and run make clean && ./configure && make again\n");
- exit(EXIT_FAILURE);
+ return false;
#endif
}
if (strcmp(outputMethod, "noncurses") == 0) {
@@ -133,24 +198,23 @@ if (strcmp(outputMethod, "raw") == 0) {//raw:
p->is_bin = 1;
//checking bit format:
if (p->bit_format != 8 && p->bit_format != 16 ) {
- fprintf(stderr,
+ write_errorf(error,
"bit format %d is not supported, supported data formats are: '8' and '16'\n",
p->bit_format );
- exit(EXIT_FAILURE);
+ return false;
}
} else if (strcmp(p->data_format, "ascii") == 0) {
p->is_bin = 0;
if (p->ascii_range < 1 ) {
- fprintf(stderr,
- "ascii max value must be a positive integer\n");
- exit(EXIT_FAILURE);
+ write_errorf(error, "ascii max value must be a positive integer\n");
+ return false;
}
} else {
- fprintf(stderr,
+ write_errorf(error,
"data format %s is not supported, supported data formats are: 'binary' and 'ascii'\n",
p->data_format);
- exit(EXIT_FAILURE);
+ return false;
}
@@ -159,17 +223,17 @@ if (strcmp(outputMethod, "raw") == 0) {//raw:
}
if (p->om == 0) {
#ifndef NCURSES
- fprintf(stderr,
+ write_errorf(error,
"output method %s is not supported, supported methods are: 'noncurses'\n",
outputMethod);
- exit(EXIT_FAILURE);
+ return false;
#endif
#ifdef NCURSES
- fprintf(stderr,
+ write_errorf(error,
"output method %s is not supported, supported methods are: 'ncurses' and 'noncurses'\n",
outputMethod);
- exit(EXIT_FAILURE);
+ return false;
#endif
}
@@ -178,10 +242,10 @@ p->stereo = -1;
if (strcmp(channels, "mono") == 0) p->stereo = 0;
if (strcmp(channels, "stereo") == 0) p->stereo = 1;
if (p->stereo == -1) {
- fprintf(stderr,
+ write_errorf(error,
"output channels %s is not supported, supported channelss are: 'mono' and 'stereo'\n",
channels);
- exit(EXIT_FAILURE);
+ return false;
}
@@ -196,55 +260,14 @@ if (p->bw < 1) p->bw = 1;
// validate: framerate
if (p->framerate < 0) {
- fprintf(stderr,
- "framerate can't be negative!\n");
- exit(EXIT_FAILURE);
+ write_errorf(error, "framerate can't be negative!\n");
+ return false;
}
-// validate: color
-if (!validate_color(p->color, p->om)) {
- fprintf(stderr, "The value for 'foreground' is invalid. It can be either one of the 7 named colors or a HTML color of the form '#xxxxxx'.\n");
- exit(EXIT_FAILURE);
+if (!validate_colors(p, error)) {
+ return false;
}
-// validate: background color
-if (!validate_color(p->bcolor, p->om)) {
- fprintf(stderr, "The value for 'background' is invalid. It can be either one of the 7 named colors or a HTML color of the form '#xxxxxx'.\n");
- exit(EXIT_FAILURE);
-}
-
-if (p->gradient) {
- for(int i = 0;i < p->gradient_count;i++){
- if (!validate_color(p->gradient_colors[i], p->om)) {
- fprintf(stderr, "The first gradient color is invalid. It must be HTML color of the form '#xxxxxx'.\n");
- exit(EXIT_FAILURE);
- }
- }
-}
-
-// In case color is not html format set bgcol and col to predefinedint values
-p->col = 6;
-if (strcmp(p->color, "black") == 0) p->col = 0;
-if (strcmp(p->color, "red") == 0) p->col = 1;
-if (strcmp(p->color, "green") == 0) p->col = 2;
-if (strcmp(p->color, "yellow") == 0) p->col = 3;
-if (strcmp(p->color, "blue") == 0) p->col = 4;
-if (strcmp(p->color, "magenta") == 0) p->col = 5;
-if (strcmp(p->color, "cyan") == 0) p->col = 6;
-if (strcmp(p->color, "white") == 0) p->col = 7;
-// default if invalid
-
-// validate: background color
-if (strcmp(p->bcolor, "black") == 0) p->bgcol = 0;
-if (strcmp(p->bcolor, "red") == 0) p->bgcol = 1;
-if (strcmp(p->bcolor, "green") == 0) p->bgcol = 2;
-if (strcmp(p->bcolor, "yellow") == 0) p->bgcol = 3;
-if (strcmp(p->bcolor, "blue") == 0) p->bgcol = 4;
-if (strcmp(p->bcolor, "magenta") == 0) p->bgcol = 5;
-if (strcmp(p->bcolor, "cyan") == 0) p->bgcol = 6;
-if (strcmp(p->bcolor, "white") == 0) p->bgcol = 7;
-// default if invalid
-
// validate: gravity
p->gravity = p->gravity / 100;
@@ -264,21 +287,54 @@ if (p->integral < 0) {
// validate: cutoff
if (p->lowcf == 0 ) p->lowcf++;
if (p->lowcf > p->highcf) {
- fprintf(stderr,
+ write_errorf(error,
"lower cutoff frequency can't be higher than higher cutoff frequency\n");
- exit(EXIT_FAILURE);
+ return false;
}
//setting sens
p->sens = p->sens / 100;
+return true;
+}
+bool load_colors(struct config_params * p, dictionary* ini, void* err) {
+ struct error_s *error = (struct error_s *)err;
+ p->color = (char *)iniparser_getstring(ini, "color:foreground", "default");
+ p->bcolor = (char *)iniparser_getstring(ini, "color:background", "default");
+
+ p->gradient = iniparser_getint(ini, "color:gradient", 0);
+ if (p->gradient) {
+ p->gradient_count = iniparser_getint(ini, "color:gradient_count", 2);
+ if(p->gradient_count < 2){
+ write_errorf(error, "\nAtleast two colors must be given as gradient!\n");
+ return false;
+ }
+ if(p->gradient_count > 8){
+ write_errorf(error, "\nMaximum 8 colors can be specified as gradient!\n");
+ return false;
+ }
+ p->gradient_colors = (char **)malloc(sizeof(char*) * p->gradient_count);
+ for(int i = 0;i < p->gradient_count;i++){
+ char ini_config[23];
+ sprintf(ini_config, "color:gradient_color_%d", (i + 1));
+ p->gradient_colors[i] = (char *)iniparser_getstring(ini, ini_config, NULL);
+ if(p->gradient_colors[i] == NULL){
+ write_errorf(error, "\nGradient color not specified : gradient_color_%d\n", (i + 1));
+ return false;
+ }
+ }
+ //p->gradient_color_1 = (char *)iniparser_getstring(ini, "color:gradient_color_1", "#0099ff");
+ //p->gradient_color_2 = (char *)iniparser_getstring(ini, "color:gradient_color_2", "#ff3399");
+ }
+ return true;
}
-void load_config(char configPath[255], char supportedInput[255], void* params)
+bool load_config(char configPath[255], char supportedInput[255], void* params, bool colorsOnly, void* err)
{
struct config_params *p = (struct config_params *)params;
+struct error_s *error = (struct error *)err;
FILE *fp;
//config: creating path to default config file
@@ -292,8 +348,8 @@ if (configPath[0] == '\0') {
if (configHome != NULL) {
sprintf(configPath,"%s/%s/%s/", configHome, ".config", PACKAGE);
} else {
- printf("No HOME found (ERR_HOMELESS), exiting...");
- exit(EXIT_FAILURE);
+ write_errorf(error, "No HOME found (ERR_HOMELESS), exiting...");
+ return false;
}
}
@@ -307,8 +363,8 @@ if (configPath[0] == '\0') {
if (fp) {
fclose(fp);
} else {
- printf("Unable to access config '%s', exiting...\n", configPath);
- exit(EXIT_FAILURE);
+ write_errorf(error, "Unable to access config '%s', exiting...\n", configPath);
+ return false;
}
@@ -318,8 +374,8 @@ if (configPath[0] == '\0') {
if (fp) {
fclose(fp);
} else {
- printf("Unable to open file '%s', exiting...\n", configPath);
- exit(EXIT_FAILURE);
+ write_errorf(error, "Unable to open file '%s', exiting...\n", configPath);
+ return false;
}
}
@@ -327,6 +383,13 @@ if (configPath[0] == '\0') {
dictionary* ini;
ini = iniparser_load(configPath);
+if (colorsOnly) {
+ if (!load_colors(p, ini, error)) {
+ return false;
+ }
+ return validate_colors(p, error);
+}
+
//setting fifo to defaualt if no other input modes supported
inputMethod = (char *)iniparser_getstring(ini, "input:method", "fifo");
@@ -353,32 +416,8 @@ p->integral = iniparser_getdouble(ini, "smoothing:integral", 90);
p->gravity = iniparser_getdouble(ini, "smoothing:gravity", 100);
p->ignore = iniparser_getdouble(ini, "smoothing:ignore", 0);
-p->color = (char *)iniparser_getstring(ini, "color:foreground", "default");
-p->bcolor = (char *)iniparser_getstring(ini, "color:background", "default");
-
-p->gradient = iniparser_getint(ini, "color:gradient", 0);
-if (p->gradient) {
- p->gradient_count = iniparser_getint(ini, "color:gradient_count", 2);
- if(p->gradient_count < 2){
- printf("\nAtleast two colors must be given as gradient!\n");
- exit(EXIT_FAILURE);
- }
- if(p->gradient_count > 8){
- printf("\nMaximum 8 colors can be specified as gradient!\n");
- exit(EXIT_FAILURE);
- }
- p->gradient_colors = (char **)malloc(sizeof(char*) * p->gradient_count);
- for(int i = 0;i < p->gradient_count;i++){
- char ini_config[23];
- sprintf(ini_config, "color:gradient_color_%d", (i + 1));
- p->gradient_colors[i] = (char *)iniparser_getstring(ini, ini_config, NULL);
- if(p->gradient_colors[i] == NULL){
- printf("\nGradient color not specified : gradient_color_%d\n", (i + 1));
- exit(EXIT_FAILURE);
- }
- }
- //p->gradient_color_1 = (char *)iniparser_getstring(ini, "color:gradient_color_1", "#0099ff");
- //p->gradient_color_2 = (char *)iniparser_getstring(ini, "color:gradient_color_2", "#ff3399");
+if (!load_colors(p, ini, error)) {
+ return false;
}
p->fixedbars = iniparser_getint(ini, "general:bars", 0);
@@ -442,7 +481,6 @@ if (strcmp(inputMethod, "sndio") == 0) {
}
#endif
-validate_config(supportedInput, params);
+return validate_config(supportedInput, params, error);
//iniparser_freedict(ini);
-
}
diff --git a/config.h b/config.h
index f4be5b3..a2dc137 100644
--- a/config.h
+++ b/config.h
@@ -1 +1,5 @@
-void load_config(char configPath[255], char supportedInput[255], void* p);
+#include
+#include
+#include
+
+bool load_config(char configPath[255], char supportedInput[255], void* p, bool colorsOnly, void* error);