properly handling config paths

This commit is contained in:
Jarcode
2017-12-01 22:46:31 -08:00
parent 11b50f1ee4
commit 75033a09aa
6 changed files with 199 additions and 108 deletions

View File

@@ -1,17 +1,56 @@
src = $(wildcard *.c)
obj = $(src:.c=.o)
# Build type parameter
ifeq ($(BUILD),debug)
CFLAGS_BUILD = -ggdb
GLAD_GEN = c-debug
else
CFLAGS_BUILD = -O2 -march=native
GLAD_GEN = c
endif
# Detect OS if not specified (OSX, Linux, BSD are supported)
ifndef INSTALL
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
INSTALL = osx
else
INSTALL = unix
endif
endif
# Install type parameter
ifeq ($(INSTALL),standalone)
CFLAGS_INSTALL = -DGLAVA_STANDALONE
endif
ifeq ($(INSTALL),unix)
CFLAGS_INSTALL = -DGLAVA_UNIX
ifdef XDG_CONFIG_DIRS
SHADER_DIR = $(firstword $(subst :, ,$XDG_CONFIG_DIR))/glava
else
SHADER_DIR = /etc/xdg/glava
endif
endif
ifeq ($(INSTALL),osx)
CFLAGS_INSTALL = -DGLAVA_OSX
SHADER_DIR = /Library/glava
endif
LDFLAGS = -lpulse -lpulse-simple -pthread -lOpenGL -lglfw -ldl -lm -lX11
PYTHON = python
GLAD_INSTALL_DIR = glad
GLAD_SRCFILE = ./glad/src/glad.c
GLAD_ARGS_RELEASE = --generator=c --extensions=GL_EXT_framebuffer_multisample,GL_EXT_texture_filter_anisotropic
GLAD_ARGS_DEBUG = --generator=c-debug --extensions=GL_EXT_framebuffer_multisample,GL_EXT_texture_filter_anisotropic
GLAD_ARGS = --generator=$(GLAD_GEN) --extensions=GL_EXT_framebuffer_multisample,GL_EXT_texture_filter_anisotropic
CFLAGS_COMMON = -I glad/include
CFLAGS_USE = $(CFLAGS_COMMON) $(CFLAGS)
CFLAGS_USE = $(CFLAGS_COMMON) $(CFLAGS_BUILD) $(CFLAGS_INSTALL) $(CFLAGS)
all: glad glava
@@ -23,16 +62,17 @@ glava: $(obj)
.PHONY: glad
glad:
cd $(GLAD_INSTALL_DIR) && $(PYTHON) -m glad $(GLAD_ARGS_RELEASE) --out-path=.
$(CC) $(CFLAGS_USE) -o glad.o $(GLAD_SRCFILE) -c
.PHONY: glad-debug
glad-debug:
cd $(GLAD_INSTALL_DIR) && $(PYTHON) -m glad $(GLAD_ARGS_DEBUG) --out-path=.
cd $(GLAD_INSTALL_DIR) && $(PYTHON) -m glad $(GLAD_ARGS) --out-path=.
$(CC) $(CFLAGS_USE) -o glad.o $(GLAD_SRCFILE) -c
.PHONY: clean
clean:
rm -f $(obj) glava glad.o
CFLAGS = -ggdb
ifneq ($(INSTALL),standalone)
.PHONY: install
install:
cp glava /usr/bin/glava
mkdir -p $(SHADER_DIR)
cp -Rv shaders/* $(SHADER_DIR)
endif

View File

@@ -8,10 +8,10 @@ GLava is an (in development) OpenGL audio spectrum visualizer. Its primary use c
$ git clone --recursive https://github.com/wacossusca34/glava
$ cd glava
$ make
$ ./glava
$ sudo make install
```
There are currently no make rules (or configure script) for installing anywhere else on the system, and the shaders are hardcoded to be read from the current directory. When development is complete, I will finish the configure & build process.
You can pass `BUILD=debug` (environment variable) to the makefile for debug builds of both glad and glava, and you can manually specify install targets with `INSTALL=...`, possible arguments are `unix` (FHS compliant Linux and BSD distros), `osx`, and `standalone` (used for running in the build directory).
Note: GLFW's most recent stable version is 3.2, whereas 3.3 is needed in order to support transparency (older versions still work, just without transparency). You can either find a more recent build or compile it yourself. Arch users can install `glfw-x11-git` from the AUR.

45
glava.c
View File

@@ -4,6 +4,7 @@
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include "fifo.h"
@@ -11,10 +12,43 @@
#include "render.h"
#include "xwin.h"
int main(int argc, char** argv) {
const char* audio_source = argc >= 2 ? argv[1] : NULL; //TODO: change
renderer* r = rd_new("shaders");
#define FORMAT(...) \
({ \
char* buf = malloc(PATH_MAX); \
snprintf(buf, PATH_MAX, __VA_ARGS__); \
buf; \
})
#define ENV(e, ...) \
({ \
const char* _e = getenv(e); \
if (!_e) \
_e = FORMAT(__VA_ARGS__); \
_e; \
})
#ifdef GLAVA_STANDALONE
#define SHADER_INSTALL_PATH "shaders"
#define SHADER_USER_PATH "userconf"
/* FHS compliant systems */
#elif defined(__unix__) || defined(GLAVA_UNIX)
#define SHADER_INSTALL_PATH FORMAT("%s/glava", ENV("XDG_CONFIG_DIRS", "/etc/xdg"))
#define SHADER_USER_PATH FORMAT("%s/glava", ENV("XDG_CONFIG_HOME", "%s/.config", ENV("HOME", "/home")))
/* OSX */
#elif (defined(__APPLE__) && defined(__MACH__)) || defined(GLAVA_OSX)
#define SHADER_INSTALL_PATH "/Library/glava"
#define SHADER_USER_PATH FORMAT("%s/Library/Preferences/glava", ENV("HOME", "/"))
#else
#error "Unsupported target system"
#endif
int main(int argc, char** argv) {
const char* entry = "rc.glsl";
const char* system_shader_paths[] = { SHADER_INSTALL_PATH, SHADER_USER_PATH, NULL };
renderer* r = rd_new(system_shader_paths, entry);
float b0[r->bufsize_request], b1[r->bufsize_request];
size_t t;
@@ -26,9 +60,8 @@ int main(int argc, char** argv) {
struct audio_data audio = {
.source = ({
char* src = NULL;
if (audio_source && strcmp(audio_source, "auto") != 0) {
src = malloc(1 + strlen(audio_source));
strcpy(src, audio_source);
if (r->audio_source_request && strcmp(r->audio_source_request, "auto") != 0) {
src = strdup(r->audio_source_request);
}
src;
}),

186
render.c
View File

@@ -95,8 +95,6 @@ static GLuint shaderload(const char* rpath,
}
memcpy(buf + written, ext.processed, ext.p_len);
if (!raw) munmap((void*) map, st.st_size);
printf("[DEBUG]\n%.*s\n", ext.p_len, ext.processed);
GLuint s = glCreateShader(type);
GLint sl = (GLint) (ext.p_len + written);
@@ -413,7 +411,6 @@ static void glad_debugcb(const char* name, void *funcptr, int len_args, ...) {
#define SHADER_EXT_VERT "vert"
#define SHADER_EXT_FRAG "frag"
#define SHADER_ENTRY "rc.glsl"
static struct gl_bind_src bind_sources[] = {
#define SRC_PREV 0
@@ -590,15 +587,16 @@ static struct gl_bind_src* lookup_bind_src(const char* str) {
return NULL;
}
struct renderer* rd_new(const char* data) {
struct renderer* rd_new(const char** paths, const char* entry) {
renderer* r = malloc(sizeof(struct renderer));
*r = (struct renderer) {
.alive = true,
.gl = malloc(sizeof(struct gl_data)),
.bufsize_request = 8192,
.rate_request = 22000,
.samplesize_request = 1024
.alive = true,
.gl = malloc(sizeof(struct gl_data)),
.bufsize_request = 8192,
.rate_request = 22000,
.samplesize_request = 1024,
.audio_source_request = NULL
};
struct gl_data* gl = r->gl;
@@ -645,7 +643,7 @@ struct renderer* rd_new(const char* data) {
printf("WARNING: the linked version of GLFW3 does not have transparency support"
" (GLFW_TRANSPARENT[_FRAMEBUFFER])!\n");
#endif
if (!(gl->w = glfwCreateWindow(500, 400, "GLava", NULL, NULL))) {
glfwTerminate();
abort();
@@ -716,6 +714,9 @@ struct renderer* rd_new(const char* data) {
glfwSetWindowSize(gl->w, gl->geometry[2], gl->geometry[3]);
})
},
{ .name = "setsource", .fmt = "s",
.handler = RHANDLER(name, args, {
r->audio_source_request = strdup((char*) args[0]); }) },
{ .name = "setforcegeometry", .fmt = "b",
.handler = RHANDLER(name, args, { gl->force_geometry = *(bool*) args[0]; }) },
{ .name = "setxwintype", .fmt = "s",
@@ -749,8 +750,6 @@ struct renderer* rd_new(const char* data) {
{
.name = "transform", .fmt = "ss",
.handler = RHANDLER(name, args, {
printf("[DEBUG] setting transform '%s' to '%s'\n",
(const char*) args[1], (const char*) args[0]);
size_t t;
struct gl_bind* bind = NULL;
for (t = 0; t < current->binds_sz; ++t) {
@@ -798,8 +797,6 @@ struct renderer* rd_new(const char* data) {
" (load a module first!)\n", (const char*) args[0]);
exit(EXIT_FAILURE);
}
printf("[DEBUG] binding '%s' -> '%s'\n",
(const char*) args[0], (const char*) args[1]);
struct gl_bind_src* src = lookup_bind_src((const char*) args[0]);
if (!src) {
fprintf(stderr, "Cannot bind uniform '%s': bind type does not exist!\n",
@@ -819,23 +816,34 @@ struct renderer* rd_new(const char* data) {
},
{ .name = NULL }
};
#undef WINDOW_WINT
size_t d_len = strlen(data);
{
size_t se_len = strlen(SHADER_ENTRY);
/* Find entry point in data directory list. The first entry point found will indicate
the path to use for future shader files and modules. Generally, user configuration
directories will be populated with symlinks to the installed modules. */
const char* data;
size_t d_len;
for (const char** i = paths; (data = *i) != NULL; ++i) {
d_len = strlen(data);
size_t se_len = strlen(entry);
size_t bsz = se_len + d_len + 2;
char se_buf[bsz];
snprintf(se_buf, bsz, "%s/%s", data, SHADER_ENTRY);
snprintf(se_buf, bsz, "%s/%s", data, entry);
struct stat st;
int fd = open(se_buf, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "failed to load entry '%s': %s\n", se_buf, strerror(errno));
exit(EXIT_FAILURE);
/* If the file exists but there was an error opening it, complain and exit */
if (errno != ENOENT &&
errno != ENOTDIR &&
errno != ELOOP ) {
fprintf(stderr, "failed to load entry '%s': %s\n", se_buf, strerror(errno));
exit(EXIT_FAILURE);
} else continue;
}
fstat(fd, &st);
@@ -851,13 +859,15 @@ struct renderer* rd_new(const char* data) {
ext_process(&ext, se_buf);
munmap((void*) map, st.st_size);
break;
}
if (!module) {
fprintf(stderr,
"No module was selected, edit %s/%s to load "
"No module was selected, edit %s to load "
"a module with `#request mod [name]`\n",
data, SHADER_ENTRY);
entry);
exit(EXIT_FAILURE);
}
@@ -882,85 +892,85 @@ struct renderer* rd_new(const char* data) {
DIR* dir = opendir(shaders);
if (dir == NULL) {
fprintf(stderr, "shaders folder '%s' does not exist!", shaders);
abort();
}
closedir(dir);
struct dirent* d;
size_t idx = 1;
bool found;
do {
found = false;
} else {
closedir(dir);
struct dirent* d;
size_t idx = 1;
bool found;
do {
found = false;
dir = opendir(shaders);
while ((d = readdir(dir)) != NULL) {
if (d->d_type == DT_REG || d->d_type == DT_UNKNOWN) {
snprintf(buf, sizeof(buf), "%d." SHADER_EXT_FRAG, idx);
if (!strcmp(buf, d->d_name)) {
printf("found GLSL stage: '%s'\n", d->d_name);
++count;
found = true;
dir = opendir(shaders);
while ((d = readdir(dir)) != NULL) {
if (d->d_type == DT_REG || d->d_type == DT_UNKNOWN) {
snprintf(buf, sizeof(buf), "%d." SHADER_EXT_FRAG, idx);
if (!strcmp(buf, d->d_name)) {
printf("found GLSL stage: '%s'\n", d->d_name);
++count;
found = true;
}
}
}
}
closedir(dir);
++idx;
} while (found);
closedir(dir);
++idx;
} while (found);
stages = malloc(sizeof(struct gl_sfbo) * count);
stages = malloc(sizeof(struct gl_sfbo) * count);
idx = 1;
do {
found = false;
idx = 1;
do {
found = false;
dir = opendir(shaders);
while ((d = readdir(dir)) != NULL) {
if (d->d_type == DT_REG || d->d_type == DT_UNKNOWN) {
snprintf(buf, sizeof(buf), "%d." SHADER_EXT_FRAG, idx);
if (!strcmp(buf, d->d_name)) {
printf("compiling: '%s'\n", d->d_name);
dir = opendir(shaders);
while ((d = readdir(dir)) != NULL) {
if (d->d_type == DT_REG || d->d_type == DT_UNKNOWN) {
snprintf(buf, sizeof(buf), "%d." SHADER_EXT_FRAG, idx);
if (!strcmp(buf, d->d_name)) {
printf("compiling: '%s'\n", d->d_name);
struct gl_sfbo* s = &stages[idx - 1];
*s = (struct gl_sfbo) {
.name = strdup(d->d_name),
.shader = 0,
.valid = false,
.binds = malloc(1),
.binds_sz = 0
};
struct gl_sfbo* s = &stages[idx - 1];
*s = (struct gl_sfbo) {
.name = strdup(d->d_name),
.shader = 0,
.valid = false,
.binds = malloc(1),
.binds_sz = 0
};
current = s;
GLuint id = shaderbuild(shaders, handlers, shader_version, d->d_name);
if (!id) {
abort();
}
current = s;
GLuint id = shaderbuild(shaders, handlers, shader_version, d->d_name);
if (!id) {
abort();
}
s->shader = id;
s->shader = id;
/* Only setup a framebuffer and texture if this isn't the final step,
as it can rendered directly */
if (idx != count) {
int w, h;
glfwGetFramebufferSize(gl->w, &w, &h);
setup_sfbo(&stages[idx - 1], w, h);
}
/* Only setup a framebuffer and texture if this isn't the final step,
as it can rendered directly */
if (idx != count) {
int w, h;
glfwGetFramebufferSize(gl->w, &w, &h);
setup_sfbo(&stages[idx - 1], w, h);
}
glUseProgram(id);
glUseProgram(id);
/* Setup uniform bindings */
size_t b;
for (b = 0; b < s->binds_sz; ++b) {
s->binds[b].uniform = glGetUniformLocation(id, s->binds[b].name);
}
glBindFragDataLocation(id, 1, "fragment");
glUseProgram(0);
/* Setup uniform bindings */
size_t b;
for (b = 0; b < s->binds_sz; ++b) {
s->binds[b].uniform = glGetUniformLocation(id, s->binds[b].name);
}
glBindFragDataLocation(id, 1, "fragment");
glUseProgram(0);
found = true;
found = true;
}
}
}
}
closedir(dir);
++idx;
} while (found);
closedir(dir);
++idx;
} while (found);
}
}
gl->stages = stages;

View File

@@ -4,10 +4,11 @@ struct gl_data;
typedef struct renderer {
bool alive;
size_t bufsize_request, rate_request, samplesize_request;
char* audio_source_request;
struct gl_data* gl;
} renderer;
struct renderer* rd_new(const char* shader_path);
struct renderer* rd_new(const char** paths, const char* entry);
void rd_update(struct renderer*, float* lb, float* rb, size_t bsz, bool modified);
void rd_destroy(struct renderer*);
void rd_time(struct renderer*);

View File

@@ -45,6 +45,11 @@
*/
#request setxwintype "normal"
/* PulseAudio source. Can be a number or a name of an audio
sink or device to record from. Set to "auto" to use the
default output device. */
#request setsource "auto"
/* GLFW buffer swap interval (vsync), set to '0' to prevent
waiting for refresh, '1' (or more) to wait for the specified
amount of frames. */
@@ -139,3 +144,5 @@
you _absolutely_ know what you are doing. */
#request setversion 3 3
#request setshaderversion 330
#include "custom.glsl"