From 395b36e75b2e8c2b35349e01f24719b61c42b10a Mon Sep 17 00:00:00 2001 From: karl Date: Sun, 4 Aug 2024 23:02:10 +0200 Subject: [PATCH] added horizontal split view for default noncurses output #575 --- cava.c | 32 ++++++++++++++--- config.c | 39 ++++++++++++++++----- config.h | 9 ++++- example_files/config | 10 +++--- output/terminal_noncurses.c | 68 +++++++++++++++++++++++-------------- output/terminal_noncurses.h | 6 ++-- 6 files changed, 118 insertions(+), 46 deletions(-) diff --git a/cava.c b/cava.c index 5dc7ad6e..ec4b6889 100644 --- a/cava.c +++ b/cava.c @@ -330,6 +330,11 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co if (p.disable_blanking) system("setterm -blank 0"); #endif + if (p.orientation != ORIENT_BOTTOM) { + cleanup(); + fprintf(stderr, "only default bottom orientation is supported in tty\n"); + exit(EXIT_FAILURE); + } } // We use unicode block characters to draw the bars and @@ -581,7 +586,7 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co init_terminal_noncurses(inAtty, p.color, p.bcolor, p.col, p.bgcol, p.gradient, p.gradient_count, p.gradient_colors, width, lines, - p.bar_width); + p.bar_width, p.orientation); height = lines * 8; break; #ifndef _MSC_VER @@ -949,7 +954,9 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co p.sens *= 0.999; else p.sens *= 1.00001; - cava_out[n] = (cava_out[n] + 1.0) / 2.0; + + if (p.orientation != ORIENT_SPLIT_H) + cava_out[n] = (cava_out[n] + 1.0) / 2.0; } if (output_mode == OUTPUT_SDL_GLSL) { @@ -959,6 +966,9 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co cava_out[n] = 0.0; } else { cava_out[n] *= *dimension_value; + if (p.orientation == ORIENT_SPLIT_H || p.orientation == ORIENT_SPLIT_V) { + cava_out[n] /= 2; + } } if (p.waveform) { bars_raw[n] = cava_out[n]; @@ -1122,9 +1132,21 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co break; #endif case OUTPUT_NONCURSES: - rc = draw_terminal_noncurses(inAtty, lines, width, number_of_bars, p.bar_width, - p.bar_spacing, remainder, bars, previous_frame, - p.gradient, x_axis_info, p.orientation); + if (p.orientation == ORIENT_SPLIT_H) { + rc = draw_terminal_noncurses(inAtty, lines, width, number_of_bars, + p.bar_width, p.bar_spacing, remainder, bars, + previous_frame, p.gradient, x_axis_info, + ORIENT_BOTTOM, 1); + rc = draw_terminal_noncurses(inAtty, lines, width, number_of_bars, + p.bar_width, p.bar_spacing, remainder, bars, + previous_frame, p.gradient, x_axis_info, + ORIENT_TOP, 1); + } else { + rc = draw_terminal_noncurses(inAtty, lines, width, number_of_bars, + p.bar_width, p.bar_spacing, remainder, bars, + previous_frame, p.gradient, x_axis_info, + p.orientation, 0); + } break; case OUTPUT_NCURSES: #ifdef NCURSES diff --git a/config.c b/config.c index 7b154119..dc5c4b9e 100644 --- a/config.c +++ b/config.c @@ -285,18 +285,39 @@ bool validate_config(struct config_params *p, struct error_s *error) { } p->orientation = ORIENT_BOTTOM; - if (p->output == OUTPUT_SDL || p->output == OUTPUT_NCURSES || p->output == OUTPUT_NONCURSES) { - if (strcmp(orientation, "top") == 0) { - p->orientation = ORIENT_TOP; - } - if (strcmp(orientation, "left") == 0) { - p->orientation = ORIENT_LEFT; - } - if (strcmp(orientation, "right") == 0) { - p->orientation = ORIENT_RIGHT; + if (strcmp(orientation, "top") == 0) { + p->orientation = ORIENT_TOP; + } + if (strcmp(orientation, "left") == 0) { + p->orientation = ORIENT_LEFT; + } + if (strcmp(orientation, "right") == 0) { + p->orientation = ORIENT_RIGHT; + } + if (strcmp(orientation, "horizontal") == 0) { + if (p->output != OUTPUT_NONCURSES) { + write_errorf(error, "only noncurses output suports horizontal orientation\n"); + return false; } + p->orientation = ORIENT_SPLIT_H; + } + if ((p->orientation == ORIENT_LEFT || p->orientation == ORIENT_RIGHT) && + !(p->output == OUTPUT_SDL || p->output == OUTPUT_NCURSES)) { + write_errorf(error, "only ncurses and sdl supports left/right orientation\n"); + return false; + } + if ((p->orientation == ORIENT_TOP) && + !(p->output == OUTPUT_SDL || p->output == OUTPUT_NCURSES || + p->output == OUTPUT_NONCURSES)) { + write_errorf(error, "only noncurses, ncurses and sdl supports top orientation\n"); + return false; } + if ((p->orientation != ORIENT_BOTTOM && p->output == OUTPUT_SDL && p->gradient != 0)) { + write_errorf(error, + "gradient in sdl is not supported with top, left or right orientation\n"); + return false; + } p->xaxis = NONE; if (strcmp(xaxisScale, "none") == 0) { p->xaxis = NONE; diff --git a/config.h b/config.h index e4885c6c..15bc7244 100644 --- a/config.h +++ b/config.h @@ -93,7 +93,14 @@ enum data_format { FORMAT_ASCII = 0, FORMAT_BINARY = 1, FORMAT_NTK3000 = 2 }; enum xaxis_scale { NONE, FREQUENCY, NOTE }; -enum orientation { ORIENT_BOTTOM, ORIENT_TOP, ORIENT_LEFT, ORIENT_RIGHT }; +enum orientation { + ORIENT_BOTTOM, + ORIENT_TOP, + ORIENT_LEFT, + ORIENT_RIGHT, + ORIENT_SPLIT_H, + ORIENT_SPLIT_V +}; struct config_params { char *color, *bcolor, *raw_target, *audio_source, diff --git a/example_files/config b/example_files/config index 7c5b3308..c1789b4d 100644 --- a/example_files/config +++ b/example_files/config @@ -144,10 +144,12 @@ # use one of the predefined ones. ; method = noncurses -# Orientation of the visualization. Can be 'bottom', 'top', 'left' or 'right'. -# Default is 'bottom'. Other orientations are only supported on sdl and ncruses -# output. Note: many fonts have weird glyphs for 'top' and 'right' characters, -# which can make ncurses not look right. +# Orientation of the visualization. Can be 'bottom', 'top', 'left', 'right' or +# 'horizontal'. Default is 'bottom'. 'left and 'right' are only supported on sdl +# and ncruses output. 'horizontal' (bars go up and down from center) is only supported +# on noncurses output. +# Note: many fonts have weird or missing glyphs for characters used in orientations +# other than 'bottom', which can make output not look right. ; orientation = bottom # Visual channels. Can be 'stereo' or 'mono'. diff --git a/output/terminal_noncurses.c b/output/terminal_noncurses.c index 08c213f5..65913c30 100644 --- a/output/terminal_noncurses.c +++ b/output/terminal_noncurses.c @@ -89,7 +89,8 @@ void free_terminal_noncurses(void) { int init_terminal_noncurses(int tty, char *const fg_color_string, char *const bg_color_string, int col, int bgcol, int gradient, int gradient_count, - char **gradient_color_strings, int width, int lines, int bar_width) { + char **gradient_color_strings, int width, int lines, int bar_width, + enum orientation orientation) { free_terminal_noncurses(); @@ -188,7 +189,33 @@ int init_terminal_noncurses(int tty, char *const fg_color_string, char *const bg printf("\033[%dm", col); // setting color } + if (bgcol != 0) { + + bgcol += 40; + + if (bgcol == 48) { + struct colors bg_color = parse_color(bg_color_string); + printf("\033[48;2;%d;%d;%dm", bg_color.rgb[0], bg_color.rgb[1], bg_color.rgb[2]); + } else { + printf("\033[%dm", bgcol); + } + + for (int n = lines; n >= 0; n--) { + for (int i = 0; i < width; i++) { + printf(" "); // setting backround color + } + if (n != 0) + printf("\n"); + else + printf("\r"); + } + printf("\033[%dA", lines); // moving cursor back up + } + if (gradient) { + if (orientation == ORIENT_SPLIT_H || orientation == ORIENT_SPLIT_V) { + lines = lines / 2; + } struct colors gradient_color_defs[MAX_GRADIENT_COLOR_DEFS]; for (int i = 0; i < gradient_count; i++) { gradient_color_defs[i] = parse_color(gradient_color_strings[i]); @@ -224,28 +251,6 @@ int init_terminal_noncurses(int tty, char *const fg_color_string, char *const bg gradient_colors[lines - 1] = gradient_color_defs[gradient_count - 1]; } - if (bgcol != 0) { - - bgcol += 40; - - if (bgcol == 48) { - struct colors bg_color = parse_color(bg_color_string); - printf("\033[48;2;%d;%d;%dm", bg_color.rgb[0], bg_color.rgb[1], bg_color.rgb[2]); - } else { - printf("\033[%dm", bgcol); - } - - for (int n = lines; n >= 0; n--) { - for (int i = 0; i < width; i++) { - printf(" "); // setting backround color - } - if (n != 0) - printf("\n"); - else - printf("\r"); - } - printf("\033[%dA", lines); // moving cursor back up - } #ifdef _MSC_VER setecho(1, 0); #else @@ -274,7 +279,8 @@ void get_terminal_dim_noncurses(int *width, int *lines) { int draw_terminal_noncurses(int tty, int lines, int width, int number_of_bars, int bar_width, int bar_spacing, int rest, int bars[], int previous_frame[], - int gradient, int x_axis_info, enum orientation orientation) { + int gradient, int x_axis_info, enum orientation orientation, + int offset) { int current_cell, prev_cell, same_line, new_line, cx; @@ -291,7 +297,7 @@ int draw_terminal_noncurses(int tty, int lines, int width, int number_of_bars, i int new_width; get_terminal_dim_noncurses(&new_width, &new_lines); - if (new_lines != (lines) || new_width != width) + if (new_lines != lines || new_width != width) return -1; if (x_axis_info) @@ -303,6 +309,14 @@ int draw_terminal_noncurses(int tty, int lines, int width, int number_of_bars, i else if (!tty) frame_buffer[0] = '\0'; + if (offset) + lines /= 2; + + if (orientation == ORIENT_TOP && offset) { + cx += swprintf(frame_buffer + cx, buf_length - cx, L"\033[%dB", + lines); // move down + } + for (int current_line = lines - 1; current_line >= 0; current_line--) { if (orientation == ORIENT_BOTTOM) { @@ -440,6 +454,10 @@ int draw_terminal_noncurses(int tty, int lines, int width, int number_of_bars, i same_line++; } } + if (orientation == ORIENT_TOP && offset) { + cx += swprintf(frame_buffer + cx, buf_length - cx, L"\033[%dA", + lines); // move up + } if (same_line != lines) { if (tty) printf("%s\r\033[%dA", ttyframe_buffer, new_line); diff --git a/output/terminal_noncurses.h b/output/terminal_noncurses.h index 2f8c23a4..f2208288 100644 --- a/output/terminal_noncurses.h +++ b/output/terminal_noncurses.h @@ -2,9 +2,11 @@ int init_terminal_noncurses(int inAtty, char *const fg_color_string, char *const bg_color_string, int col, int bgcol, int gradient, int gradient_count, - char **gradient_colors, int w, int h, int bar_width); + char **gradient_colors, int w, int h, int bar_width, + enum orientation orientation); void get_terminal_dim_noncurses(int *w, int *h); int draw_terminal_noncurses(int inAtty, int lines, int width, int number_of_bars, int bar_width, int bar_spacing, int rest, int bars[], int previous_frame[], - int gradient, int x_axis_info, enum orientation orientation); + int gradient, int x_axis_info, enum orientation orientation, + int offset); void cleanup_terminal_noncurses(void);