18 Commits
v1.2 ... v1.3

Author SHA1 Message Date
Jarcode
c8cce220d8 fixed GLFW_MAXIMIZED macro for GLFW 3.1 2018-02-08 06:36:40 -08:00
Jarcode
be63f40dc2 Merge branch 'unstable' 2018-02-07 20:57:00 -08:00
Jarcode
f5a9f801d1 Backported for GLFW 3.1, fixes #13, *again* 2018-02-07 20:56:41 -08:00
Jarcode
53bd657226 Added debian(-based) compile instructions 2018-02-07 20:42:05 -08:00
Jarcode
e6f2507b53 Merge branch 'unstable' 2018-02-07 20:23:15 -08:00
Jarcode
2805528d43 fixed directive issue 2018-02-07 20:22:54 -08:00
Jarcode
1de3a5215b updated changelog 2018-02-07 20:18:05 -08:00
Jarcode
1db4ea3ded updated changelog 2018-02-07 20:17:43 -08:00
Jarcode
901cdb7d67 Merge branch 'unstable' 2018-02-07 20:06:09 -08:00
Jarcode
d82762a471 changed version, added -V (--version) flag 2018-02-07 20:02:24 -08:00
Jarcode
ec6d4d0c37 exempted glsl color syntax from string contents 2018-02-07 19:53:23 -08:00
Jarcode
aea30abf67 added RGBA hex color parsing for GLSL, fixed alpha blending bug 2018-02-07 19:29:56 -08:00
Jarcode
79d391938d moved hex color parsing to ext_parse_color, removed debug message 2018-02-07 17:46:34 -08:00
Jarcode
8c3a404f37 fixed include order in xwin.c, fixes #13 2018-02-07 17:17:58 -08:00
Jarcode
f539f18135 Always define GLFW_EXPOSE_NATIVE_GLX 2018-02-07 17:12:45 -08:00
Jarcode
ab55156826 Set window types and state ealier during initialization, fixed #17 2018-02-07 16:58:39 -08:00
Jarcode
5e813e25a9 Changed position of 'glfwShowWindow' call, related to #17 2018-02-07 16:41:12 -08:00
Jarcode
83f5583eeb Updated version 2018-02-06 19:04:25 -08:00
11 changed files with 234 additions and 88 deletions

View File

@@ -1,7 +1,17 @@
## 1.3
* Added RGBA color parsing for GLSL code and directives (does not work within `#request` directives). The behaviour converts `#3ef708ff` -> `vec4(0.243, 0.967, 0.031, 1.0)`. If the alpha component is omitted, it is assumed to be `1.0`. The parsing occurs during compile time, so it does not incurr any performance penalty.
* Fixed stray `[DEBUG]` messages that were errornously being printed
* _Actually_ added support for GLFW 3.1, see issue #13
* Fixed issue with some WMs not responding to GLava's window types and hints, see #17
* Fixed alpha blending not working, `radial` and `circle` image quality should be drastically improved on `xroot` and `none` opacity settings.
* Added `--version` command line flag
## 1.2
* Added support for GLFW 3.1, see issue #13
* Attempted to add support for GLFW 3.1, see issue #13
* Added configurable solid background color, see #16
* Fixed issue with excessive file reads from `~/.Xauthority` see #15

View File

@@ -28,6 +28,11 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla
- python (required to generate bindings with glad)
- GCC (this program uses GNU C features)
**Ubuntu/Debian users:** the following command ensures you have all the needed packages and headers to compile and run GLava:
```bash
sudo apt-get install libpulse libpulse-dev libglfw3 libglfw3-dev libxext6 libxext6-dev python make gcc
```
## [Configuration](https://github.com/wacossusca34/glava/wiki)
GLava will start by looking for an entry point in the user configuration folder (`~/.config/glava/rc.glsl`\*), and will fall back to loading from the shader installation folder (`/etc/xdg/glava`\*). The entry point will specify a module to load and should set global configuration variables. Configuration for specific modules can be done in their respective `.glsl` files, which the module itself will include.

15
glava.c
View File

@@ -18,7 +18,7 @@
#include "render.h"
#include "xwin.h"
#define GLAVA_VERSION "1.2"
#define GLAVA_VERSION "1.3"
#ifdef GLAD_DEBUG
#define GLAVA_RELEASE_TYPE_PREFIX "debug, "
#else
@@ -151,6 +151,8 @@ static void copy_cfg(const char* path, const char* dest, bool verbose) {
closedir(dir);
}
#define GLAVA_VERSION_STRING "GLava (glava) " GLAVA_VERSION " (" GLAVA_RELEASE_TYPE ")"
static const char* help_str =
"Usage: %s [OPTIONS]...\n"
"Opens a window with an OpenGL context to draw an audio visualizer.\n"
@@ -165,17 +167,19 @@ static const char* help_str =
"-C, --copy-config creates copies and symbolic links in the user configuration\n"
" directory for glava, copying any files in the root directory\n"
" of the installed shader directory, and linking any modules.\n"
"-V, --version print application version and exit\n"
"\n"
"GLava (glava) " GLAVA_VERSION " (" GLAVA_RELEASE_TYPE ")\n"
GLAVA_VERSION_STRING "\n"
" -- Copyright (C) 2017 Levi Webb\n";
static const char* opt_str = "hve:Cm:";
static const char* opt_str = "hvVe:Cm:";
static struct option p_opts[] = {
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
{"entry", required_argument, 0, 'e'},
{"force-mod", required_argument, 0, 'm'},
{"copy-config", no_argument, 0, 'C'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0 }
};
@@ -198,10 +202,15 @@ int main(int argc, char** argv) {
case 'e': entry = optarg; break;
case 'm': force = optarg; break;
case '?': exit(EXIT_FAILURE); break;
case 'V':
puts(GLAVA_VERSION_STRING);
exit(EXIT_SUCCESS);
break;
default:
case 'h':
printf(help_str, argc > 0 ? argv[0] : "glava");
exit(EXIT_SUCCESS);
break;
}
}

View File

@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <errno.h>
@@ -51,7 +52,7 @@ static void se_append(struct sbuf* sbuf, size_t elen, const char* fmt, ...) {
int written;
if ((written = vsnprintf(sbuf->buf + sbuf->at, space, fmt, args)) < 0)
abort();
sbuf->at += space;
sbuf->at += written;
va_end(args);
}
@@ -68,6 +69,42 @@ struct schar {
size_t sz;
};
bool ext_parse_color(const char* str, size_t elem_sz, float** results) {
size_t t, len = strlen(str), i = 0, s = 0;
uint8_t elem_bytes[elem_sz];
/* Ignore '0x' prefix, if present */
if (len >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
len -= 2;
str += 2;
}
for (t = 0; t < len && t < 8; ++t) {
char c = str[t];
uint8_t b;
/* obtain value from character */
switch (c) {
case 'a' ... 'f': b = (c - 'a') + 10; break;
case 'A' ... 'F': b = (c - 'A') + 10; break;
case '0' ... '9': b = c - '0'; break;
default: return false;
}
elem_bytes[s] = b;
if (s >= elem_sz - 1) { /* advance to next element */
uint32_t e = 0; /* component storage */
/* mask storage with input data */
for (size_t v = 0; v < elem_sz; ++v) {
e |= (uint32_t) elem_bytes[v] << (((elem_sz - 1) - v) * 4);
}
/* convert to [0, 1] as floating point value */
*results[i] = (float) e / (float) ((1 << (elem_sz * 4)) - 1);
s = 0;
++i;
} else { /* advance character */
++s;
}
}
return true;
}
/* handle raw arguments for #include and #request directives */
/* NOTE: munmap needs to be called on the result */
static struct schar directive(struct glsl_ext* ext, char** args,
@@ -91,7 +128,8 @@ static struct schar directive(struct glsl_ext* ext, char** args,
int fd = open(path, O_RDONLY);
if (fd == -1) {
parse_error(line, f, "failed to load GLSL shader source specified by #include directive '%s': %s\n",
parse_error(line, f, "failed to load GLSL shader source "
"specified by #include directive '%s': %s\n",
path, strerror(errno));
}
@@ -100,7 +138,8 @@ static struct schar directive(struct glsl_ext* ext, char** args,
char* map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (!map) {
parse_error(line, f, "failed to map GLSL shader source specified by #include directive '%s': %s\n",
parse_error(line, f, "failed to map GLSL shader source "
"specified by #include directive '%s': %s\n",
path, strerror(errno));
}
@@ -128,7 +167,7 @@ static struct schar directive(struct glsl_ext* ext, char** args,
struct request_handler* handler;
bool found = false;
size_t t, i;
size_t t;
for (t = 0; (handler = &ext->handlers[t])->name != NULL; ++t) {
if(!strcmp(handler->name, request)) {
found = true;
@@ -173,10 +212,12 @@ static struct schar directive(struct glsl_ext* ext, char** args,
case '1': { v = true; break; }
case '0': { v = false; break; }
default:
parse_error_s(line, f, "tried to parse invalid raw string into a boolean");
parse_error_s(line, f,
"tried to parse invalid raw string into a boolean");
}
} else {
parse_error_s(line, f, "tried to parse invalid raw string into a boolean");
parse_error_s(line, f,
"tried to parse invalid raw string into a boolean");
}
processed_args[i] = malloc(sizeof(bool));
*(bool*) processed_args[i] = v;
@@ -211,10 +252,11 @@ static struct schar directive(struct glsl_ext* ext, char** args,
void ext_process(struct glsl_ext* ext, const char* f) {
#define LINE_START 0
#define IGNORING 1
#define GLSL 1
#define MACRO 2
#define REQUEST 3
#define INCLUDE 4
#define COLOR 5
struct sbuf sbuf = {
.buf = malloc(256),
@@ -226,12 +268,16 @@ void ext_process(struct glsl_ext* ext, const char* f) {
size_t t;
char at;
int state = LINE_START;
size_t macro_start_idx, arg_start_idx;
size_t macro_start_idx, arg_start_idx, cbuf_idx;
size_t line = 1;
bool quoted = false, arg_start;
char cbuf[9];
char** args = NULL;
size_t args_sz = 0;
bool prev_slash = false, comment = false, comment_line = false, prev_asterix = false,
prev_escape = false, string = false;
for (t = 0; t <= source_len; ++t) {
at = source_len == t ? '\0' : ext->source[t];
if (at == '\n')
@@ -244,40 +290,128 @@ void ext_process(struct glsl_ext* ext, const char* f) {
macro_start_idx = t;
state = MACRO;
continue; }
case ' ':
case '\t':
case '\n':
if (comment && comment_line) {
comment = false;
comment_line = false;
}
case '\t':
case ' ':
goto copy;
default: {
state = IGNORING;
goto copy; }
default: state = GLSL;
/* let execution continue into next state */
}
}
case IGNORING: /* copying GLSL source or unrelated preprocessor syntax */
if (at == '\n') {
state = LINE_START;
case GLSL: /* copying GLSL source or unrelated preprocessor syntax */
{
switch (at) {
case '"':
if (!comment && !prev_escape)
string = !string;
goto normal_char;
case '\\':
if (!comment) {
prev_escape = !prev_escape;
prev_asterix = false;
prev_slash = false;
goto copy;
} else goto normal_char;
case '/':
if (!comment) {
if (prev_slash) {
comment = true;
comment_line = true;
prev_slash = false;
} else prev_slash = true;
} else if (!comment_line) {
if (prev_asterix) {
comment = false;
prev_asterix = false;
}
}
prev_escape = false;
goto copy;
case '*':
if (!comment) {
if (prev_slash) {
comment = true;
prev_slash = false;
}
} else prev_asterix = true;
prev_escape = false;
goto copy;
case '#': {
/* handle hex color syntax */
if (!comment && !string) {
state = COLOR;
cbuf_idx = 0;
continue;
} else goto normal_char;
}
case '\n':
if (comment && comment_line) {
comment = false;
comment_line = false;
}
state = LINE_START;
normal_char:
default:
prev_asterix = false;
prev_slash = false;
prev_escape = false;
goto copy;
}
}
case COLOR: /* parse hex color syntax (#ffffffff -> vec4(1.0, 1.0, 1.0, 1.0)) */
{
switch (at) {
case 'a' ... 'z':
case 'A' ... 'Z':
case '0' ... '9': {
cbuf[cbuf_idx] = at;
++cbuf_idx;
if (cbuf_idx >= 8)
goto emit_color;
else continue;
}
emit_color:
default:
cbuf[cbuf_idx] = '\0'; /* null terminate */
float r = 0.0F, g = 0.0F, b = 0.0F, a = 1.0F;
if (ext_parse_color(cbuf, 2, (float*[]) { &r, &g, &b, &a })) {
se_append(&sbuf, 64, " vec4(%.6f, %.6f, %.6f, %.6f) ", r, g, b, a);
} else {
parse_error(line, f, "Invalid color format '#%s' while "
"parsing GLSL color syntax extension", cbuf);
}
state = at == '\n' ? LINE_START : GLSL;
if (cbuf_idx >= 8)
continue;
else goto copy; /* copy character if it ended the sequence */
}
}
goto copy;
case MACRO: /* processing start of macro */
{
switch (at) {
case '\n':
case ' ':
case '\t':
case '\0':
case '\0':
{
/* end parsing directive */
if (!strncmp("#request", &ext->source[macro_start_idx], t - macro_start_idx)
|| !strncmp("#REQUEST", &ext->source[macro_start_idx], t - macro_start_idx)) {
state = REQUEST;
goto prepare_arg_parse;
} else if (!strncmp("#include", &ext->source[macro_start_idx], t - macro_start_idx)
|| !strncmp("#INCLUDE", &ext->source[macro_start_idx], t - macro_start_idx)) {
} else if (!strncmp("#include", &ext->source[macro_start_idx],
t - macro_start_idx)
|| !strncmp("#INCLUDE", &ext->source[macro_start_idx],
t - macro_start_idx)) {
state = INCLUDE;
goto prepare_arg_parse;
} else {
n_append(&sbuf, t - macro_start_idx, &ext->source[macro_start_idx]);
state = IGNORING;
state = at == '\n' ? LINE_START : GLSL;
goto copy;
}
prepare_arg_parse:

View File

@@ -35,3 +35,4 @@ struct glsl_ext {
void ext_process(struct glsl_ext* ext, const char* f);
void ext_free (struct glsl_ext* ext);
bool ext_parse_color(const char* hex, size_t elem_sz, float** results);

View File

@@ -16,6 +16,14 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
/* Fixes for old GLFW versions */
#ifndef GLFW_TRUE
#define GLFW_TRUE GL_TRUE
#endif
#ifndef GLFW_FALSE
#define GLFW_FALSE GL_FALSE
#endif
#include "render.h"
#include "xwin.h"
#include "glsl_ext.h"
@@ -742,6 +750,12 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
{ .name = request, .fmt = "b", \
.handler = RHANDLER(name, args, { glfwWindowHint(attr, *(bool*) args[0]); }) }
#define STUB(request, f) \
{ .name = request, .fmt = f, \
.handler = RHANDLER(name, args, { \
fprintf(stderr, "warning: '%s' request is not implemented for this build\n", \
request); }) }
struct request_handler handlers[] = {
{
.name = "setopacity", .fmt = "s",
@@ -753,10 +767,10 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
#ifdef GLFW_TRANSPARENT_FRAMEBUFFER
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, native_opacity ? GLFW_TRUE : GLFW_FALSE);
gl->use_alpha = false;
if (native_opacity) gl->use_alpha = false;
#elif GLFW_TRANSPARENT
glfwWindowHint(GLFW_TRANSPARENT, native_opacity ? GLFW_TRUE : GLFW_FALSE);
gl->use_alpha = false;
if (native_opacity) gl->use_alpha = false;
#else
if (native_opacity)
printf("WARNING: the linked version of GLFW3 does not have transparency support"
@@ -783,42 +797,9 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
&gl->clear_color.b,
&gl->clear_color.a
};
const size_t elem_sz = 2;
char* str = (char*) args[0];
size_t t, len = strlen(str), i = 0, s = 0;
uint8_t elem_bytes[elem_sz];
/* Ignore '0x' prefix, if present */
if (len >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
len -= 2;
str += 2;
}
for (t = 0; t < len && t < 8; ++t) {
char c = str[t];
uint8_t b;
/* obtain value from character */
switch (c) {
case 'a' ... 'f': b = (c - 'a') + 10; break;
case 'A' ... 'F': b = (c - 'A') + 10; break;
case '0' ... '9': b = c - '0'; break;
default:
fprintf(stderr, "Invalid value for `setbg` request: '%s'\n", (char*) args[0]);
exit(EXIT_FAILURE);
}
elem_bytes[s] = b;
if (s >= elem_sz - 1) { /* advance to next element */
uint32_t e = 0; /* component storage */
/* mask storage with input data */
for (size_t v = 0; v < elem_sz; ++v) {
e |= (uint32_t) elem_bytes[v] << (((elem_sz - 1) - v) * 4);
}
/* convert to [0, 1] as floating point value */
*results[i] = (float) e / (float) ((1 << (elem_sz * 4)) - 1);
printf("[DEBUG] component %d value: %d (float: %f)\n", i, e, *results[i]);
s = 0;
++i;
} else { /* advance character */
++s;
}
if (!ext_parse_color((char*) args[0], 2, results)) {
fprintf(stderr, "Invalid value for `setbg` request: '%s'\n", (char*) args[0]);
exit(EXIT_FAILURE);
}
})
},
@@ -845,7 +826,11 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
WINDOW_HINT("setfloating", GLFW_FLOATING),
WINDOW_HINT("setdecorated", GLFW_DECORATED),
WINDOW_HINT("setfocused", GLFW_FOCUSED),
#ifdef GLFW_MAXIMIZED
WINDOW_HINT("setmaximized", GLFW_MAXIMIZED),
#else
STUB("setmaximized", "b"),
#endif
{
.name = "setversion", .fmt = "ii",
.handler = RHANDLER(name, args, {
@@ -1055,6 +1040,16 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
abort();
}
if (xwintype) {
xwin_settype(r, xwintype);
free(xwintype);
}
for (size_t t = 0; t < xwinstates_sz; ++t) {
xwin_addstate(r, xwinstates[t]);
}
free(xwinstates);
glfwSetWindowPos(gl->w, gl->geometry[0], gl->geometry[1]);
glfwSetWindowSize(gl->w, gl->geometry[2], gl->geometry[3]);
@@ -1086,7 +1081,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
struct gl_sfbo* stages;
size_t count = 0;
{
char buf[32];
DIR* dir = opendir(shaders);
@@ -1219,20 +1214,10 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
}
overlay(&gl->overlay);
glfwShowWindow(gl->w);
glClearColor(gl->clear_color.r, gl->clear_color.g, gl->clear_color.b, gl->clear_color.a);
if (xwintype) {
xwin_settype(r, xwintype);
free(xwintype);
}
for (size_t t = 0; t < xwinstates_sz; ++t) {
xwin_addstate(r, xwinstates[t]);
}
free(xwinstates);
glfwShowWindow(gl->w);
return r;
}

View File

@@ -7,13 +7,13 @@
/* width (in pixels) of each bar gap */
#define BAR_GAP 2
/* outline color */
#define BAR_OUTLINE vec4(0.15, 0.15, 0.15, 1)
#define BAR_OUTLINE #262626
/* outline width (in pixels, set to 0 to disable outline drawing) */
#define BAR_OUTLINE_WIDTH 0
/* Amplify magnitude of the results each bar displays */
#define AMPLIFY 300
/* Bar color */
#define COLOR (vec4(0.2, 0.4, 0.7, 1) * ((d / 60) + 1))
#define COLOR (#3366b2 * ((d / 60) + 1))
/* Direction that the bars are facing, 0 for inward, 1 for outward */
#define DIRECTION 0
/* Whether to switch left/right audio buffers */

View File

@@ -3,7 +3,7 @@
/* center line thickness (pixels) */
#define C_LINE 2
/* outline color */
#define OUTLINE vec4(0.20, 0.20, 0.20, 1)
#define OUTLINE #333333
/* Amplify magnitude of the results each bar displays */
#define AMPLIFY 150
/* Angle (in radians) for how much to rotate the visualizer */

View File

@@ -17,7 +17,7 @@
/* actual color definition */
#define COLOR vec4((0.3 + RCOL_OFF) + LSTEP, 0.6 - LSTEP, (0.3 + LCOL_OFF) + LSTEP, 1)
/* outline color */
#define OUTLINE vec4(0.15, 0.15, 0.15, 1)
#define OUTLINE #262626
/* 1 to invert (vertically), 0 otherwise */
#define INVERT 0

View File

@@ -4,7 +4,7 @@
/* center line thickness (pixels) */
#define C_LINE 2
/* outline color */
#define OUTLINE vec4(0.20, 0.20, 0.20, 1)
#define OUTLINE #333333
/* number of bars (use even values for best results) */
#define NBARS 180
/* width (in pixels) of each bar*/
@@ -15,8 +15,8 @@
#define BAR_OUTLINE_WIDTH 0
/* Amplify magnitude of the results each bar displays */
#define AMPLIFY 300
/* Bar color */
#define COLOR (vec4(0.8, 0.2, 0.2, 1) * ((d / 40) + 1))
/* Bar color */
#define COLOR (#cc3333 * ((d / 40) + 1))
/* Angle (in radians) for how much to rotate the visualizer */
#define ROTATE (PI / 2)
/* Whether to switch left/right audio buffers */

12
xwin.c
View File

@@ -16,13 +16,15 @@
#include <X11/extensions/XShm.h>
#define GLFW_EXPOSE_NATIVE_X11
/* Hack to make GLFW 3.1 headers work with GLava. We don't use the context APIs from GLFW, but
the old headers require one of them to be selected for exposure in glfw3native.h. */
#if (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR <= 1)
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include <glad/glad.h>
#include <GLFW/glfw3.h>
/* Hack to make GLFW 3.1 headers work with GLava. We don't use the context APIs from GLFW, but
the old headers require one of them to be selected for exposure in glfw3native.h. */
#if GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR <= 1
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include <GLFW/glfw3native.h>
#include "render.h"