properly handling config paths
This commit is contained in:
62
Makefile
62
Makefile
@@ -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
|
||||
|
||||
@@ -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
45
glava.c
@@ -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
186
render.c
@@ -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;
|
||||
|
||||
3
render.h
3
render.h
@@ -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*);
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user