Reworked noncurses output mode and made it defualt.

The reworked noncurses mode uses a custom framebuffer technique that
only draws changes per frame and only writes to the terminal once per
frame. This results in far less cpu usage then ncurses. It is also
free of the flickering that we se in ncurses mode #196

Colors are no longer set by default so hopefully cava will change
color automatically in noncurses mode when using tools such as
pywall #340 #181

Unfortunently html colors, gradient and key controls are not supported
in noncurses.
master
karlstav 6 years ago
parent a0ab48bddc
commit 90159e5de3
  1. 2
      README.md
  2. 10
      config.c
  3. 13
      example_files/config
  4. 206
      output/terminal_noncurses.c

@ -378,6 +378,8 @@ If cava quits unexpectedly or is force killed, echo must be turned on manually w
### Controls
NOTE: only works in ncurses output mode.
| Key | Description |
| --- | ----------- |
| <kbd>up</kbd> / <kbd>down</kbd>| increase/decrease sensitivity |

@ -59,8 +59,10 @@ int validate_color(char *checkColor, int om, void *err) {
// If the output mode is not ncurses, tell the user to use a named colour instead of hex
// colours.
if (om != OUTPUT_NCURSES) {
write_errorf(error, "Only 'ncurses' output method supports HTML colors. Please change "
"the colours or the output method.\n");
write_errorf(
error, "Only 'ncurses' output method supports HTML colors. Please change "
"the colours or the output method.\nAs of version 0.7.0 ncurses is no longer"
" the default output method\n");
return 0;
}
// 0 to 9 and a to f
@ -118,7 +120,7 @@ bool validate_colors(void *params, void *err) {
}
// In case color is not html format set bgcol and col to predefinedint values
p->col = 6;
p->col = -1;
if (strcmp(p->color, "black") == 0)
p->col = 0;
if (strcmp(p->color, "red") == 0)
@ -406,7 +408,7 @@ bool load_config(char configPath[PATH_MAX], struct config_params *p, bool colors
}
#ifdef NCURSES
outputMethod = (char *)iniparser_getstring(ini, "output:method", "ncurses");
outputMethod = (char *)iniparser_getstring(ini, "output:method", "noncurses");
#endif
#ifndef NCURSES
outputMethod = (char *)iniparser_getstring(ini, "output:method", "noncurses");

@ -77,7 +77,9 @@
[output]
# Output method. Can be 'ncurses', 'noncurses' or 'raw'.
# 'noncurses' is for systems that does not suport ncurses.
# 'noncurses' uses a custom framebuffer technique and draws only changes
# from frame to frame. As of version 0.7.0 'noncurses' is default.
#
# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
# stream of the bar heights that can be used to send to other applications.
# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above.
@ -112,10 +114,11 @@
[color]
# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires a
# terminal that can change color definitions such as Gnome-terminal or rxvt.
; background = black
; foreground = cyan
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
# ncurses output method and a terminal that can change color definitions such as Gnome-terminal or rxvt.
# default is to keep current terminal color
; background = default
; foreground = default
# Gradient mode, only hex defined colors are supported, background must also be defined in hex
# or remain commented out. 1 = on, 0 = off. Warning: for certain terminal emulators cava will

@ -8,9 +8,14 @@
#include <unistd.h>
#include <wchar.h>
wchar_t barstring[8][100];
int ttybarstring[8];
char spacestring[100];
wchar_t *line_buffer;
wchar_t *barstring[8];
wchar_t *wspacestring;
int buf_length;
char *ttyline_buffer;
char ttybarstring[8][100];
char ttyspacestring[100];
int ttybuf_length;
int setecho(int fd, int onoff) {
@ -33,13 +38,24 @@ int setecho(int fd, int onoff) {
int init_terminal_noncurses(int col, int bgcol, int w, int h, int bar_width) {
int n, i;
ttybuf_length = sizeof(char) * w * h * 10;
ttyline_buffer = (char *)malloc(ttybuf_length);
buf_length = sizeof(wchar_t) * w * h * 10;
line_buffer = (wchar_t *)malloc(buf_length);
wspacestring = (wchar_t *)malloc(sizeof(wchar_t) * bar_width);
// clearing barstrings
for (n = 0; n < 8; n++) {
ttybarstring[n] = 0;
barstring[n] = (wchar_t *)malloc(sizeof(wchar_t) * bar_width);
ttybarstring[n][0] = '\0';
barstring[n][0] = '\0';
spacestring[0] = '\0';
ttyspacestring[0] = '\0';
}
wspacestring[0] = '\0';
line_buffer[0] = '\0';
ttyline_buffer[0] = '\0';
// creating barstrings for drawing
for (n = 0; n < bar_width; n++) {
@ -52,11 +68,17 @@ int init_terminal_noncurses(int col, int bgcol, int w, int h, int bar_width) {
wcscat(barstring[5], L"\u2585");
wcscat(barstring[6], L"\u2586");
wcscat(barstring[7], L"\u2587");
strcat(spacestring, " ");
for (i = 0; i < 8; i++) {
ttybarstring[i] += (i + 1) * pow(10, n);
}
wcscat(wspacestring, L" ");
strcat(ttybarstring[0], "8");
strcat(ttybarstring[1], "1");
strcat(ttybarstring[2], "2");
strcat(ttybarstring[3], "3");
strcat(ttybarstring[4], "4");
strcat(ttybarstring[5], "5");
strcat(ttybarstring[6], "6");
strcat(ttybarstring[7], "7");
strcat(ttyspacestring, " ");
}
col += 30;
@ -68,9 +90,10 @@ int init_terminal_noncurses(int col, int bgcol, int w, int h, int bar_width) {
printf("\033[0m\n");
system("clear");
if (col)
printf("\033[%dm", col); // setting color
printf("\033[1m"); // setting "bright" color mode, looks cooler... I think
// printf("\033[1m"); // setting "bright" color mode, looks cooler... I think
if (bgcol != 0) {
@ -106,68 +129,151 @@ void get_terminal_dim_noncurses(int *w, int *h) {
int draw_terminal_noncurses(int tty, int h, int w, int bars, int bar_width, int bs, int rest,
int f[200], int flastd[200]) {
int c, move, n, o;
int current_char, last_char, n, o, same_line, new_line, cx;
struct winsize dim;
// output: check if terminal has been resized
if (!tty) {
same_line = 0;
new_line = 0;
cx = 0;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &dim);
if (tty) {
if ((int)dim.ws_row != h || (int)dim.ws_col != w) {
return -1;
}
}
ttyline_buffer[0] = '\0';
for (n = h - 1; n >= 0; n--) {
move = rest; // center adjustment
int same_bar = 0;
int center_adjusted = 0;
for (o = 0; o < bars; o++) {
// output: draw and move to another one, check whether we're not too far
current_char = f[o] - n * 8;
last_char = flastd[o] - n * 8;
if (f[o] != flastd[o]) { // change?
// same as last frame
if ((current_char < 1 && last_char < 1) || (current_char > 7 && last_char > 7) ||
(current_char == last_char)) {
same_bar++;
} else {
if (same_line > 0) {
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, "\033[%dB",
same_line); // move down
new_line += same_line;
same_line = 0;
}
if (move != 0)
printf("\033[%dC", move);
move = 0;
if (same_bar > 0) {
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, "\033[%dC",
(bar_width + bs) * same_bar); // move forward
same_bar = 0;
}
c = f[o] - n * 8;
if (!center_adjusted) {
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, "\033[%dC", rest);
center_adjusted = 1;
}
if (c < 1) {
if (n * 8 < flastd[o])
printf("%s", spacestring); // blank
else
move += bar_width;
} else if (c > 7) {
if (n > flastd[o] / 8 - 1) {
if (tty)
printf("%d", ttybarstring[7]); // block tty
if (current_char < 1)
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, ttyspacestring);
else if (current_char > 7)
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, ttybarstring[0]);
else
printf("%ls", barstring[0]); // block
} else
move += bar_width;
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx,
ttybarstring[current_char]);
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, "\033[%dC", bs);
}
}
if (same_bar != bars) {
if (n != 0) {
cx += snprintf(ttyline_buffer + cx, ttybuf_length - cx, "\n");
new_line++;
}
} else {
if (tty)
printf("%d", ttybarstring[c - 1]); // fractioned block tty
else
printf("%ls", barstring[c]); // fractioned block vt
same_line++;
}
}
if (same_line != h) {
printf("%s\r\033[%dA", ttyline_buffer,
new_line); //\r\033[%dA", ttyline_buffer, h - same_line);
fflush(stdout);
}
} else if (!tty) {
} else
move += bar_width; // no change, moving along
// output: check if terminal has been resized
ioctl(STDOUT_FILENO, TIOCGWINSZ, &dim);
move += bs; // move to next bar
if ((int)dim.ws_row != h || (int)dim.ws_col != w) {
free(line_buffer);
free(wspacestring);
for (int i = 0; i < 8; i++)
free(barstring[i]);
return -1;
}
if (n != 0)
printf("\n");
line_buffer[0] = '\0';
for (n = h - 1; n >= 0; n--) {
int same_bar = 0;
int center_adjusted = 0;
for (o = 0; o < bars; o++) {
current_char = f[o] - n * 8;
last_char = flastd[o] - n * 8;
// same as last frame
if ((current_char < 1 && last_char < 1) || (current_char > 7 && last_char > 7) ||
(current_char == last_char)) {
same_bar++;
} else {
if (same_line > 0) {
cx += swprintf(line_buffer + cx, buf_length - cx, L"\033[%dB",
same_line); // move down
new_line += same_line;
same_line = 0;
}
if (same_bar > 0) {
cx += swprintf(line_buffer + cx, buf_length - cx, L"\033[%dC",
(bar_width + bs) * same_bar); // move forward
same_bar = 0;
}
if (!center_adjusted && rest) {
cx += swprintf(line_buffer + cx, buf_length - cx, L"\033[%dC", rest);
center_adjusted = 1;
}
if (current_char < 1)
cx += swprintf(line_buffer + cx, buf_length - cx, wspacestring);
else if (current_char > 7)
cx += swprintf(line_buffer + cx, buf_length - cx, barstring[0]);
else
printf("\r");
cx += swprintf(line_buffer + cx, buf_length - cx, barstring[current_char]);
cx += swprintf(line_buffer + cx, buf_length - cx, L"\033[%dC", bs);
}
}
printf("\033[%dA", h);
if (same_bar != bars) {
if (n != 0) {
cx += swprintf(line_buffer + cx, buf_length - cx, L"\n");
new_line++;
}
} else {
same_line++;
}
}
if (same_line != h) {
printf("%ls\r\033[%dA", line_buffer,
new_line); //\r\033[%dA", line_buffer, h - same_line);
fflush(stdout);
}
}
return 0;
}

Loading…
Cancel
Save