├── src ├── output │ ├── shared │ │ ├── cairo │ │ │ ├── modules │ │ │ │ ├── kinetic │ │ │ │ │ ├── config.ini │ │ │ │ │ ├── build.cmake │ │ │ │ │ └── main.c │ │ │ │ ├── media_info │ │ │ │ │ ├── config.ini │ │ │ │ │ └── build.cmake │ │ │ │ ├── oscilloscope │ │ │ │ │ ├── config.ini │ │ │ │ │ └── build.cmake │ │ │ │ ├── bars │ │ │ │ │ ├── config.ini │ │ │ │ │ └── build.cmake │ │ │ │ ├── stars │ │ │ │ │ ├── config.ini │ │ │ │ │ └── build.cmake │ │ │ │ └── shared │ │ │ │ │ ├── config.h │ │ │ │ │ └── config.c │ │ │ ├── util │ │ │ │ ├── feature_compat.c │ │ │ │ ├── region.h │ │ │ │ ├── region.c │ │ │ │ ├── feature_compat.h │ │ │ │ ├── module.c │ │ │ │ └── module.h │ │ │ └── main.h │ │ ├── gl │ │ │ ├── modules │ │ │ │ ├── bars │ │ │ │ │ ├── vertex.glsl │ │ │ │ │ ├── fragment.glsl │ │ │ │ │ └── build.cmake │ │ │ │ ├── bars_circle │ │ │ │ │ ├── vertex.glsl │ │ │ │ │ ├── config.ini │ │ │ │ │ ├── fragment.glsl │ │ │ │ │ └── build.cmake │ │ │ │ └── stars │ │ │ │ │ ├── vertex.glsl │ │ │ │ │ ├── fragment.glsl │ │ │ │ │ ├── config.ini │ │ │ │ │ └── build.cmake │ │ │ ├── util │ │ │ │ ├── misc.h │ │ │ │ ├── shader.h │ │ │ │ └── misc.c │ │ │ ├── glew.h │ │ │ ├── post.h │ │ │ ├── glew.c │ │ │ ├── egl.h │ │ │ ├── egl.c │ │ │ └── main.h │ │ ├── util │ │ │ └── media │ │ │ │ ├── media_data.h │ │ │ │ ├── artwork.h │ │ │ │ ├── artwork_taglib.cpp │ │ │ │ ├── artwork.c │ │ │ │ └── media_data.c │ │ └── graphical.h │ ├── graphical_wayland │ │ ├── gen │ │ │ └── .gitignore │ │ ├── egl.h │ │ ├── cairo.h │ │ ├── registry.h │ │ ├── test.c │ │ ├── zwlr.h │ │ ├── xdg.h │ │ ├── shm.h │ │ ├── cairo.c │ │ ├── wl_output.h │ │ ├── egl.c │ │ ├── main.h │ │ ├── registry.c │ │ ├── xdg.c │ │ ├── shm.c │ │ └── wl_output.c │ ├── graphical_win │ │ ├── main.h │ │ ├── test.c │ │ └── build.cmake │ ├── graphical_sdl2 │ │ ├── test.c │ │ └── build.cmake │ ├── graphical_x11 │ │ └── test.c │ ├── default │ │ ├── build.cmake │ │ └── main.c │ └── unsupported │ │ └── terminal_ncurses │ │ └── build.cmake ├── shared │ ├── io │ │ ├── unix.h │ │ ├── io.h │ │ └── unix.c │ ├── module │ │ ├── internal.h │ │ ├── module.h │ │ ├── abstractions.c │ │ ├── unix.c │ │ └── windows.c │ ├── util │ │ ├── types.h │ │ ├── version.h │ │ ├── array.h │ │ └── version.c │ ├── ionotify.h │ ├── build.cmake │ ├── ionotify.c │ ├── config │ │ └── config.h │ ├── log.h │ └── log.c ├── input │ ├── wasapi │ │ ├── main.h │ │ └── build.cmake │ ├── shmem │ │ ├── build.cmake │ │ └── main.c │ ├── fifo │ │ ├── build.cmake │ │ └── main.c │ ├── sndio │ │ ├── build.cmake │ │ └── main.c │ ├── alsa │ │ └── build.cmake │ ├── pipewire │ │ └── build.cmake │ ├── pulseaudio │ │ └── build.cmake │ ├── portaudio │ │ └── build.cmake │ └── cubeb │ │ ├── build.cmake │ │ └── main.c ├── config.h ├── cmake │ ├── utilities.cmake │ ├── build-fix.cmake │ ├── install_and_configure.cmake │ ├── modules.cmake │ ├── os-prerequisites.cmake │ └── copy_gl_shaders.cmake └── filters │ └── default │ └── build.cmake ├── assets ├── windows │ ├── xava.ico │ ├── readme.txt │ ├── xava.rc.template │ └── xava.nsi.template └── linux │ ├── wava.desktop │ └── wava.svg ├── example_files ├── etc │ ├── modprobe.d │ │ └── alsa-aloop.conf │ └── asound.conf └── gl │ └── shaders │ ├── default │ ├── config.ini │ ├── vertex.glsl │ └── fragment.glsl │ ├── kinetic │ ├── config.ini │ ├── vertex.glsl │ └── fragment.glsl │ └── shadow │ ├── config.ini │ ├── vertex.glsl │ └── fragment.glsl ├── CONTRIBUTING.md ├── .gitignore ├── .github ├── docker │ ├── windows │ │ ├── make │ │ │ └── action.yaml │ │ ├── send │ │ │ └── action.yaml │ │ ├── Dockerfile │ │ └── build.sh │ └── archlinux │ │ ├── make │ │ └── action.yaml │ │ ├── send │ │ └── action.yaml │ │ ├── Dockerfile │ │ └── build.sh ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── actions │ ├── upload │ │ └── action.yaml │ ├── compile │ │ └── action.yaml │ └── prepare │ │ └── action.yaml └── workflows │ └── main.yaml ├── default.nix ├── .gitmodules ├── LICENSE └── CMakeLists.txt /src/output/shared/cairo/modules/kinetic/config.ini: -------------------------------------------------------------------------------- 1 | # noop 2 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/media_info/config.ini: -------------------------------------------------------------------------------- 1 | # noop 2 | -------------------------------------------------------------------------------- /assets/windows/xava.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dominara1/wava/HEAD/assets/windows/xava.ico -------------------------------------------------------------------------------- /src/shared/io/unix.h: -------------------------------------------------------------------------------- 1 | #ifdef UNIX_INDEPENDENT_PATHS 2 | char *find_prefix(void); 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /example_files/etc/modprobe.d/alsa-aloop.conf: -------------------------------------------------------------------------------- 1 | options snd-aloop index=1 enable=1 pcm_substreams=4 id=Loopback 2 | -------------------------------------------------------------------------------- /example_files/gl/shaders/default/config.ini: -------------------------------------------------------------------------------- 1 | [features] 2 | intensity = false 3 | time = false 4 | colors = true 5 | -------------------------------------------------------------------------------- /example_files/gl/shaders/kinetic/config.ini: -------------------------------------------------------------------------------- 1 | [features] 2 | intensity = true 3 | time = false 4 | colors = true 5 | -------------------------------------------------------------------------------- /example_files/gl/shaders/shadow/config.ini: -------------------------------------------------------------------------------- 1 | [features] 2 | intensity = false 3 | time = false 4 | colors = true 5 | -------------------------------------------------------------------------------- /src/input/wasapi/main.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | #define external extern "C" 3 | #else 4 | #define external 5 | #endif 6 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/gen/.gitignore: -------------------------------------------------------------------------------- 1 | # This folder should only contain Wayland-related 2 | # glue code, this is why everything is ignored here 3 | * 4 | -------------------------------------------------------------------------------- /src/output/graphical_win/main.h: -------------------------------------------------------------------------------- 1 | #ifdef assert 2 | #define vertify(expr) if(!expr) assert(0) 3 | #else 4 | #define vertify(expr) expr 5 | #endif 6 | 7 | #define WGL_WGLEXT_PROTOTYPES 8 | 9 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/oscilloscope/config.ini: -------------------------------------------------------------------------------- 1 | # Config options related to the "bars" cairo module 2 | # Remove ';' for the config options to apply 3 | 4 | [oscilloscope] 5 | # noop 6 | 7 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/bars/vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // input vertex 4 | in vec4 fft_bars; 5 | 6 | uniform mat4 projection_matrix; 7 | 8 | void main() { 9 | gl_Position = fft_bars*projection_matrix; 10 | } 11 | -------------------------------------------------------------------------------- /src/shared/module/internal.h: -------------------------------------------------------------------------------- 1 | #include "shared/module/module.h" 2 | 3 | // these functions are only meant to be called within 4 | // the "modules" part of the library and NEVER outside 5 | WAVAMODULE *wava_module_load(char *name); 6 | 7 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/bars_circle/vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // input vertex 4 | in vec4 fft_bars; 5 | 6 | uniform mat4 projection_matrix; 7 | 8 | void main() { 9 | gl_Position = fft_bars*projection_matrix; 10 | } 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | TODO: Readjust the coding conventions. 2 | 3 | # Coding conventions 4 | * 4 spaces for indents 5 | * curly braces on same line as if, while, for statements 6 | 7 | Generally please try to keep the style consistent with the code as it is. 8 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/bars_circle/config.ini: -------------------------------------------------------------------------------- 1 | [bars] 2 | start_height = 0.5 3 | minimum_height = 0.01 4 | width = 1.0 5 | invert = false 6 | [rotation] 7 | per_minute = 1.0 8 | invert = false 9 | using_intensity = false 10 | intensity_scale = 1.0 11 | 12 | -------------------------------------------------------------------------------- /src/output/graphical_sdl2/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool am_i_sdl2(void) { 5 | int val = SDL_Init(SDL_INIT_EVERYTHING); 6 | if(val != 0) 7 | return false; 8 | 9 | SDL_Quit(); 10 | return true; 11 | } 12 | -------------------------------------------------------------------------------- /assets/linux/wava.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Version=1.1 4 | Name=WAVA 5 | GenericName=Graphical Audio Visualizer 6 | Comment=X11 Audio Visualizer for ALSA 7 | Exec=wava 8 | Icon=wava_visualizer 9 | Terminal=false 10 | Categories=Audio;AudioVideo 11 | 12 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/stars/vertex.glsl: -------------------------------------------------------------------------------- 1 | // input vertex 2 | attribute vec4 pos; 3 | attribute vec4 color; 4 | 5 | varying vec4 vcolor; 6 | 7 | uniform mat4 projection_matrix; 8 | 9 | void main() { 10 | gl_Position = pos*projection_matrix; 11 | vcolor = color; 12 | } 13 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/egl.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_EGL_H 2 | #define __WAYLAND_EGL_H 3 | #include 4 | #include "main.h" 5 | 6 | void waylandEGLWindowResize(struct waydata *wd, int w, int h); 7 | void waylandEGLCreateWindow(struct waydata *wd); 8 | #endif 9 | -------------------------------------------------------------------------------- /src/output/shared/gl/util/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef __GL_MODULE_SHARED_UTIl_H 2 | #define __GL_MODULE_SHARED_UTIl_H 3 | 4 | #include "output/shared/gl/main.h" 5 | 6 | float wava_gl_module_util_calculate_intensity(WAVA *wava); 7 | float wava_gl_module_util_obtain_time(void); 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | build*/ 3 | !build.cmake 4 | *.files 5 | *.includes 6 | *.user 7 | *.config 8 | CMakeLists.txt.* 9 | compile_commands.json 10 | Debug/ 11 | .cache/ 12 | .vimspector.json 13 | INSTALLER/ 14 | 15 | *.patch 16 | 17 | !src/output/graphical_wayland/gen/.gitignore 18 | 19 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/cairo.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_OUTPUT_WAYLAND_CAIRO_H 2 | #define __WAVA_OUTPUT_WAYLAND_CAIRO_H 3 | 4 | #include "main.h" 5 | 6 | void wava_output_wayland_cairo_init(struct waydata *wd); 7 | void wava_output_wayland_cairo_resize(struct waydata *wd); 8 | 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/registry.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_REGISTRY_H 2 | #define __WAYLAND_REGISTRY_H 3 | 4 | #include 5 | 6 | #include "shared.h" 7 | 8 | extern struct wl_registry *wavaWLRegistry; 9 | extern const struct wl_registry_listener wava_wl_registry_listener; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/output/graphical_win/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool am_i_win32(void) { 5 | HMODULE module = GetModuleHandle(NULL); 6 | if(module == NULL) 7 | return false; 8 | 9 | // don't close the handle as it would mess up windows 10 | return true; 11 | } 12 | -------------------------------------------------------------------------------- /src/output/graphical_x11/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool am_i_x11(void) { 6 | Display *display = XOpenDisplay(NULL); 7 | if(display == NULL) 8 | return false; 9 | 10 | XCloseDisplay(display); 11 | return true; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool am_i_wayland(void) { 5 | struct wl_display *display = wl_display_connect(NULL); 6 | if(display == NULL) 7 | return false; 8 | 9 | wl_display_disconnect(display); 10 | return true; 11 | } 12 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/bars/config.ini: -------------------------------------------------------------------------------- 1 | # Config options related to the "bars" cairo module 2 | # Remove ';' for the config options to apply 3 | 4 | [bars] 5 | 6 | # Mirrors the bars into the horizontal axis, so that 7 | # the vertical middle is the start poistion of every 8 | # bar 9 | ; mirror = true 10 | 11 | -------------------------------------------------------------------------------- /example_files/gl/shaders/shadow/vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // input vertex and texture coordinate 4 | in vec4 v_texCoord; // vertex 5 | in vec2 m_texCoord; // mapping 6 | 7 | // output texture map coordinate 8 | out vec2 texCoord; 9 | 10 | void main() { 11 | gl_Position = v_texCoord; 12 | texCoord = m_texCoord; 13 | } 14 | -------------------------------------------------------------------------------- /example_files/gl/shaders/default/vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // input vertex and texture coordinate 4 | in vec4 v_texCoord; // vertex 5 | in vec2 m_texCoord; // mapping 6 | 7 | // output texture map coordinate 8 | out vec2 texCoord; 9 | 10 | void main() { 11 | gl_Position = v_texCoord; 12 | texCoord = m_texCoord; 13 | } 14 | -------------------------------------------------------------------------------- /example_files/gl/shaders/kinetic/vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // input vertex and texture coordinate 4 | in vec4 v_texCoord; // vertex 5 | in vec2 m_texCoord; // mapping 6 | 7 | // output texture map coordinate 8 | out vec2 texCoord; 9 | 10 | void main() { 11 | gl_Position = v_texCoord; 12 | texCoord = m_texCoord; 13 | } 14 | -------------------------------------------------------------------------------- /src/shared/util/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_SHARED_TYPES_H 2 | #define __WAVA_SHARED_TYPES_H 3 | 4 | #include 5 | #include 6 | 7 | #define u8 uint8_t 8 | #define u16 uint16_t 9 | #define u32 uint32_t 10 | #define u64 uint64_t 11 | #define i8 int8_t 12 | #define i16 int16_t 13 | #define i32 int32_t 14 | #define i64 int64_t 15 | #define f32 float 16 | #define f64 double 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /.github/docker/windows/make/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'windows' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | runs: 12 | using: docker 13 | image: docker://xava-build-windows:latest 14 | entrypoint: './.github/docker/windows/build.sh' 15 | args: 16 | - ${{ inputs.arch }} 17 | -------------------------------------------------------------------------------- /src/output/shared/gl/glew.h: -------------------------------------------------------------------------------- 1 | #ifndef __GL_H 2 | #define __GL_H 3 | 4 | #include "main.h" 5 | 6 | #include "shared.h" 7 | 8 | 9 | void GLConfigLoad(WAVA *wava); 10 | void GLInit(WAVA *wava); 11 | void GLClear(WAVA *wava); 12 | void GLApply(WAVA *wava); 13 | XG_EVENT_STACK *GLEvent(WAVA *wava); 14 | void GLDraw(WAVA *wava); 15 | void GLCleanup(WAVA *wava); 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /.github/docker/archlinux/make/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'archlinux' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | runs: 12 | using: docker 13 | image: docker://xava-build-archlinux:latest 14 | entrypoint: './.github/docker/archlinux/build.sh' 15 | args: 16 | - ${{ inputs.arch }} 17 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/zwlr.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_ZWLR_LAYER_SHELL_H 2 | #define __WAYLAND_ZWLR_LAYER_SHELL_H 3 | 4 | #include "gen/wlr-layer-shell-unstable-v1-client-protocol.h" 5 | 6 | #include "main.h" 7 | 8 | extern const struct zwlr_layer_surface_v1_listener layer_surface_listener; 9 | extern struct zwlr_layer_shell_v1 *wavaWLRLayerShell; 10 | 11 | void zwlr_init(struct waydata *s); 12 | void zwlr_cleanup(struct waydata *s); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/output/shared/cairo/util/feature_compat.c: -------------------------------------------------------------------------------- 1 | #include "feature_compat.h" 2 | 3 | // check for logic errors in the feature_compat list 4 | bool wava_cairo_feature_compatibility_assert(WAVA_CAIRO_FEATURE a) { 5 | if(a&WAVA_CAIRO_FEATURE_DRAW_REGION_SAFE) { 6 | if(!(a&WAVA_CAIRO_FEATURE_DRAW_REGION)) return false; 7 | if(!(a&WAVA_CAIRO_FEATURE_FULL_DRAW)) return false; 8 | } 9 | if(a == 0) return false; 10 | return true; 11 | } 12 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/xdg.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_XDG_SURFACE_H 2 | #define __WAYLAND_XDG_SURFACE_H 3 | 4 | #include "gen/xdg-shell-client-protocol.h" 5 | 6 | #include "main.h" 7 | 8 | extern const struct xdg_surface_listener xdg_surface_listener; 9 | extern const struct xdg_wm_base_listener xdg_wm_base_listener; 10 | extern struct xdg_wm_base *wavaXDGWMBase; 11 | 12 | extern void xdg_init(struct waydata *s); 13 | extern void xdg_cleanup(); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/input/shmem/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(SHMEM "SHMEM" OFF) 3 | 4 | if(SHMEM) 5 | add_definitions(-DSHMEM) 6 | add_library(in_shmem SHARED "${WAVA_MODULE_DIR}/main.c" 7 | "${GLOBAL_FUNCTION_SOURCES}") 8 | target_link_libraries(in_shmem wava-shared "-lrt") 9 | set_target_properties(in_shmem PROPERTIES PREFIX "") 10 | install(TARGETS in_shmem DESTINATION lib/wava) 11 | 12 | # Maybe license? pls no sue 13 | endif() 14 | 15 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef H_CONFIG 2 | #define H_CONFIG 3 | // This is changed by the CMake build file, don't touch :) 4 | #ifndef WAVA_DEFAULT_INPUT 5 | #define WAVA_DEFAULT_INPUT "pulseaudio" 6 | #endif 7 | #ifndef WAVA_DEFAULT_OUTPUT 8 | #define WAVA_DEFAULT_OUTPUT "opengl" 9 | #endif 10 | #ifndef WAVA_DEFAULT_FILTER 11 | #define WAVA_DEFAULT_FILTER "default" 12 | #endif 13 | 14 | #include "shared.h" 15 | 16 | char *load_config(char *configPath, WAVA*); 17 | void clean_config(); 18 | #endif 19 | -------------------------------------------------------------------------------- /.github/docker/windows/send/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'windows' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | runs: 12 | using: 'composite' 13 | steps: 14 | - name: Uploading artifact for ${{ matrix.system }}-${{ matrix.arch }} 15 | uses: actions/upload-artifact@v3 16 | with: 17 | name: xava-installer-${{ matrix.arch }}.exe 18 | path: xava-installer-${{ matrix.arch }}.exe 19 | 20 | -------------------------------------------------------------------------------- /src/input/fifo/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(FIFO "FIFO" ON) 3 | 4 | # Doesn't work on Windows (no shit) 5 | if(MSYS OR MINGW OR MSVC) 6 | set(FIFO OFF) 7 | endif() 8 | 9 | if(FIFO) 10 | message(STATUS "Not a Windows platform, can use POSIX now!") 11 | add_library(in_fifo SHARED "${WAVA_MODULE_DIR}/main.c" 12 | "${GLOBAL_FUNCTION_SOURCES}") 13 | target_link_libraries(in_fifo wava-shared) 14 | set_target_properties(in_fifo PROPERTIES PREFIX "") 15 | install(TARGETS in_fifo DESTINATION lib/wava) 16 | endif() 17 | 18 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | 3 | pkgs.stdenv.mkDerivation { 4 | name = "wava"; 5 | src = ./.; 6 | 7 | buildInputs = with pkgs; 8 | [ 9 | wayland 10 | wayland-protocols 11 | cmake 12 | gcc 13 | egl-wayland 14 | glew 15 | pulseaudio 16 | pipewire 17 | fftw 18 | fftwFloat 19 | pkg-config 20 | imagemagick 21 | librsvg 22 | ]; 23 | 24 | buildPhase = '' 25 | cmake .. -DCMAKE_SKIP_BUILD_RPATH=ON 26 | make -j $(nproc) 27 | ''; 28 | 29 | installPhase = '' 30 | make install 31 | ''; 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/input/wasapi/build.cmake: -------------------------------------------------------------------------------- 1 | # The project default 2 | option(WASAPI "WASAPI" ON) 3 | 4 | if(NOT (MSYS OR MINGW OR MSVC)) 5 | set(WASAPI OFF) 6 | endif() 7 | 8 | # winapi 9 | if(WASAPI) 10 | add_library(in_wasapi SHARED "${WAVA_MODULE_DIR}/main.cpp" 11 | "${GLOBAL_FUNCTION_SOURCES}") 12 | target_link_libraries(in_wasapi wava-shared ole32 oleaut32) 13 | #target_include_directories(in_wasapi PRIVATE "${ALSA_INCLUDE_DIRS}") 14 | #target_link_directories(in_wasapi PRIVATE "${ALSA_LIBRARY_DIRS}") 15 | set_target_properties(in_wasapi PROPERTIES PREFIX "") 16 | endif() 17 | 18 | -------------------------------------------------------------------------------- /src/output/shared/gl/post.h: -------------------------------------------------------------------------------- 1 | #ifndef __GL_MODULE_SHARED_POST_H 2 | #define __GL_MODULE_SHARED_POST_H 3 | 4 | #include "output/shared/gl/main.h" 5 | 6 | void wava_gl_module_post_config_load(WAVAGLHostOptions *vars); 7 | void wava_gl_module_post_init(WAVAGLHostOptions *vars); 8 | void wava_gl_module_post_apply(WAVAGLHostOptions *vars); 9 | void wava_gl_module_post_clear(WAVAGLHostOptions *vars); 10 | void wava_gl_module_post_pre_draw_setup(WAVAGLHostOptions *vars); 11 | void wava_gl_module_post_draw(WAVAGLHostOptions *vars); 12 | void wava_gl_module_post_cleanup(WAVAGLHostOptions *vars); 13 | #endif 14 | 15 | -------------------------------------------------------------------------------- /example_files/etc/asound.conf: -------------------------------------------------------------------------------- 1 | pcm.!default { 2 | type plug # <-- no { here 3 | slave.pcm { 4 | type multi 5 | slaves { 6 | a { channels 2 pcm "hw:0,0" } # the real device 7 | b { channels 2 pcm "hw:Loopback,0" } # the loopback driver 8 | } 9 | bindings { 10 | 0 { slave a channel 0 } 11 | 1 { slave a channel 1 } 12 | 2 { slave b channel 0 } 13 | 3 { slave b channel 1 } 14 | } 15 | } 16 | ttable [ 17 | [ 1 0 1 0 ] # left -> a.left, b.left 18 | [ 0 1 0 1 ] # right -> a.right, b.right 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/iniparser"] 2 | path = lib/iniparser 3 | url = https://github.com/ndevilla/iniparser 4 | [submodule "lib/x-watcher"] 5 | path = lib/x-watcher 6 | url = https://github.com/nikp123/x-watcher 7 | [submodule "thirdparty/mingw-bundledlls"] 8 | path = thirdparty/mingw-bundledlls 9 | url = https://github.com/mpreisler/mingw-bundledlls 10 | [submodule "lib/kiss-mpris-properties"] 11 | path = lib/kiss-mpris-properties 12 | url = https://github.com/nikp123/kiss-mpris-properties 13 | [submodule "lib/stb"] 14 | path = lib/stb 15 | url = https://github.com/nothings/stb.git 16 | [submodule "lib/cubeb"] 17 | path = lib/cubeb 18 | url = https://github.com/mozilla/cubeb 19 | -------------------------------------------------------------------------------- /src/cmake/utilities.cmake: -------------------------------------------------------------------------------- 1 | # Concatenate files in CMake 2 | function(cat IN_FILE OUT_FILE) 3 | file(READ ${IN_FILE} CONTENTS) 4 | file(APPEND ${OUT_FILE} "${CONTENTS}") 5 | endfunction() 6 | 7 | # Windows-only, find and copy missing system libraries 8 | function(find_and_copy_dlls file) 9 | # 1001 reasons to not write shit in C 10 | if(MINGW) 11 | add_custom_command(TARGET ${file} POST_BUILD 12 | COMMAND ${CMAKE_COMMAND} -E env MINGW_BUNDLEDLLS_SEARCH_PATH="${wava_dep_dirs}" 13 | python "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/mingw-bundledlls/mingw-bundledlls" $ --copy 14 | ) 15 | endif() 16 | endfunction() 17 | 18 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/shm.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_SHM_H 2 | #define __WAYLAND_SHM_H 3 | 4 | #include 5 | #include 6 | 7 | #include "shared.h" 8 | 9 | #include "main.h" 10 | 11 | uint32_t wayland_color_blend (uint32_t color, uint8_t alpha); 12 | void update_frame (struct waydata *wd); 13 | void reallocSHM (struct waydata *wd); 14 | void closeSHM (struct waydata *wd); 15 | void wl_surface_frame_done(void *data, 16 | struct wl_callback *cb, 17 | uint32_t time); 18 | 19 | extern const struct wl_callback_listener wl_surface_frame_listener; 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /example_files/gl/shaders/default/fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | in vec2 texCoord; 4 | 5 | uniform sampler2D color_texture; 6 | uniform sampler2D depth_texture; 7 | 8 | uniform vec4 background_color; 9 | 10 | layout(location=0) out vec4 FragColor; 11 | 12 | vec4 correctForAlphaBlend(vec4 color) { 13 | return vec4(color.rgb*color.a, color.a); 14 | } 15 | 16 | vec4 append_color_properly(vec4 source, vec4 target) { 17 | target.rgb += mix(target.rgb, source.rgb, source.a); 18 | target.a = max(target.a, source.a); 19 | return target; 20 | } 21 | 22 | void main() { 23 | // transfer background 24 | FragColor = texture(color_texture, texCoord); 25 | 26 | //FragColor = correctForAlphaBlend(FragColor); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/output/shared/gl/glew.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef GL 4 | #define GL 5 | #endif 6 | #include "glew.h" 7 | 8 | #include "shared.h" 9 | #include "output/shared/graphical.h" 10 | 11 | 12 | void GLConfigLoad(WAVA *wava) { 13 | SGLConfigLoad(wava); 14 | } 15 | 16 | void GLInit(WAVA *wava) { 17 | glewInit(); 18 | 19 | SGLInit(wava); 20 | } 21 | 22 | void GLApply(WAVA *wava) { 23 | SGLApply(wava); 24 | } 25 | 26 | XG_EVENT_STACK *GLEvent(WAVA *wava) { 27 | return SGLEvent(wava); 28 | } 29 | 30 | void GLClear(WAVA *wava) { 31 | SGLClear(wava); 32 | } 33 | 34 | void GLDraw(WAVA *wava) { 35 | SGLDraw(wava); 36 | } 37 | 38 | void GLCleanup(WAVA *wava) { 39 | SGLCleanup(wava); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /.github/docker/archlinux/send/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'archlinux' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | runs: 12 | using: 'composite' 13 | steps: 14 | - name: Upload version artifact 15 | uses: actions/upload-artifact@v3 16 | with: 17 | if-no-files-found: error 18 | name: xava-x86_64.AppImage 19 | path: build/xava-x86_64.AppImage 20 | 21 | - name: Upload version artifact 22 | uses: actions/upload-artifact@v3 23 | with: 24 | if-no-files-found: error 25 | name: version.txt 26 | path: build/version.txt 27 | 28 | -------------------------------------------------------------------------------- /assets/linux/wava.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/output/shared/cairo/util/region.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_OUTPUT_SHARED_CAIRO_REGION_H 2 | #define __WAVA_OUTPUT_SHARED_CAIRO_REGION_H 3 | 4 | #include 5 | // keeping bounding boxes constrained to well,... rectangles. we can make this 6 | // system way simpler than do to bitmask checks which is stupidly memory 7 | // inefficient and computationally expensive 8 | typedef struct wava_cairo_region { 9 | int x; // region starting x coordinate 10 | int y; // region starting y coordinate 11 | int w; // region starting w coordinate 12 | int h; // region starting h coordinate 13 | } wava_cairo_region; 14 | 15 | // functions 16 | bool wava_cairo_region_list_check(wava_cairo_region *A, 17 | wava_cairo_region *B); 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /example_files/gl/shaders/kinetic/fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | in vec2 texCoord; 4 | 5 | uniform sampler2D color_texture; 6 | uniform sampler2D depth_texture; 7 | 8 | uniform vec4 background_color; 9 | 10 | uniform float intensity; 11 | 12 | layout(location=0) out vec4 FragColor; 13 | 14 | vec4 correctForAlphaBlend(vec4 color) { 15 | return vec4(color.rgb*color.a, color.a); 16 | } 17 | 18 | vec4 append_color_properly(vec4 source, vec4 target) { 19 | target.rgb += mix(target.rgb, source.rgb, source.a); 20 | target.a = max(target.a, source.a); 21 | return target; 22 | } 23 | 24 | void main() { 25 | FragColor = append_color_properly( 26 | texture(color_texture, texCoord), 27 | vec4(background_color.rgb, background_color.a*(1.0-intensity))); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /.github/actions/upload/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'archlinux' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | # 12 | # Let's play a game. 13 | # Can you spot the dumb GH Actions design here? 14 | # 15 | 16 | runs: 17 | using: 'composite' 18 | steps: 19 | - uses: ./.github/docker/archlinux/send 20 | if: contains(inputs.system, 'archlinux') 21 | with: 22 | system: ${{ inputs.system }} 23 | arch: ${{ inputs.arch }} 24 | - uses: ./.github/docker/windows/send 25 | if: contains(inputs.system, 'windows') 26 | with: 27 | system: ${{ inputs.system }} 28 | arch: ${{ inputs.arch }} 29 | 30 | -------------------------------------------------------------------------------- /.github/actions/compile/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'archlinux' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | # 12 | # Let's play a game. 13 | # Can you spot the dumb GH Actions design here? 14 | # 15 | 16 | runs: 17 | using: 'composite' 18 | steps: 19 | - uses: ./.github/docker/archlinux/make 20 | if: contains(inputs.system, 'archlinux') 21 | with: 22 | system: ${{ inputs.system }} 23 | arch: ${{ inputs.arch }} 24 | - uses: ./.github/docker/windows/make 25 | if: contains(inputs.system, 'windows') 26 | with: 27 | system: ${{ inputs.system }} 28 | arch: ${{ inputs.arch }} 29 | 30 | 31 | -------------------------------------------------------------------------------- /.github/docker/archlinux/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM archlinux:latest 2 | 3 | LABEL org.opencontainers.image.source https://github.com/nikp123/xava 4 | 5 | WORKDIR /mnt 6 | 7 | # Update Arch 8 | RUN yes | pacman -Syyu --noconfirm; yes | pacman -Scc 9 | 10 | # Install XAVA dependencies 11 | RUN yes | pacman -S --noconfirm make base-devel fftw alsa-lib pulseaudio \ 12 | libx11 libxrender libxrandr sdl2 portaudio cmake git wayland-protocols \ 13 | pipewire cairo wget sndio glew curl taglib imagemagick librsvg rust \ 14 | ; yes | pacman -Scc 15 | 16 | # Download and install linuxdeploy 17 | RUN wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage 18 | RUN chmod +x linuxdeploy-x86_64.AppImage 19 | RUN sudo mv linuxdeploy-x86_64.AppImage /usr/local/bin/linuxdeploy 20 | 21 | -------------------------------------------------------------------------------- /src/output/shared/gl/util/shader.h: -------------------------------------------------------------------------------- 1 | #ifndef __GL_MODULE_SHARED_SHADER_H 2 | #define __GL_MODULE_SHARED_SHADER_H 3 | 4 | #include "output/shared/gl/main.h" 5 | 6 | typedef enum sgl_shader_type { 7 | SGL_PRE, 8 | SGL_POST 9 | } sgl_shader_type; 10 | 11 | typedef enum sgl_shader_stage { 12 | SGL_VERT, 13 | SGL_GEO, 14 | SGL_FRAG, 15 | SGL_CONFIG 16 | } sgl_shader_stage; 17 | 18 | GLint wava_gl_module_shader_build(struct shader *shader, GLenum shader_type); 19 | void wava_gl_module_program_create(wava_gl_module_program *program); 20 | void wava_gl_module_program_destroy(wava_gl_module_program *program); 21 | void wava_gl_module_shader_load(wava_gl_module_program *program, 22 | sgl_shader_type type, sgl_shader_stage stage, 23 | const char *name, WAVAGLModule *module, WAVA *wava); 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /src/output/shared/util/media/media_data.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVA_UTIL_MEDIA_INFO_MEDIA_DATA 2 | #define WAVA_UTIL_MEDIA_INFO_MEDIA_DATA 3 | 4 | #include "artwork.h" 5 | 6 | #define MUSIC_DATA_STRING_LENGTH 1024 7 | 8 | struct media_data { 9 | struct artwork cover; 10 | char album [MUSIC_DATA_STRING_LENGTH]; 11 | char artist[MUSIC_DATA_STRING_LENGTH]; 12 | char title [MUSIC_DATA_STRING_LENGTH]; 13 | char genre [MUSIC_DATA_STRING_LENGTH]; 14 | 15 | uint64_t version; 16 | }; 17 | 18 | struct media_data_thread; 19 | 20 | struct media_data * 21 | wava_util_media_data_thread_data(struct media_data_thread *thread); 22 | struct media_data_thread * 23 | wava_util_media_data_thread_create(void); 24 | void 25 | wava_util_media_data_thread_destroy(struct media_data_thread *data); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/stars/fragment.glsl: -------------------------------------------------------------------------------- 1 | // color passed from the host 2 | uniform vec4 foreground_color; 3 | 4 | // color passed from the host 5 | uniform vec4 background_color; 6 | 7 | // number of secionts that the gradient is divided to 8 | uniform float gradient_sections; 9 | 10 | // each of the gradient colors 11 | uniform vec4 gradient_color[8]; 12 | 13 | // screen width and height 14 | uniform vec2 resolution; 15 | 16 | uniform float intensity; 17 | 18 | layout(location=0) out vec4 FragColor; 19 | 20 | 21 | 22 | void main() { 23 | if(gradient_sections > 0.0) { 24 | float across = (gl_FragCoord.y/resolution.y)*gradient_sections; 25 | int section = int(floor(across)); 26 | float off = mod(across, 1.0); 27 | FragColor = mix(gradient_color[section], gradient_color[section+1], off); 28 | } else { 29 | FragColor = foreground_color; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/bars/fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // color passed from the host 4 | uniform vec4 foreground_color; 5 | 6 | // color passed from the host 7 | uniform vec4 background_color; 8 | 9 | // number of secionts that the gradient is divided to 10 | uniform float gradient_sections; 11 | 12 | // each of the gradient colors 13 | uniform vec4 gradient_color[8]; 14 | 15 | // screen width and height 16 | uniform vec2 resolution; 17 | 18 | uniform float intensity; 19 | 20 | layout(location=0) out vec4 FragColor; 21 | 22 | void main() { 23 | if(gradient_sections > 0.0) { 24 | float across = (gl_FragCoord.y/resolution.y)*gradient_sections; 25 | int section = int(floor(across)); 26 | float off = mod(across, 1.0); 27 | FragColor = mix(gradient_color[section], gradient_color[section+1], off); 28 | } else { 29 | FragColor = foreground_color; 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/cmake/build-fix.cmake: -------------------------------------------------------------------------------- 1 | # Correct CMAKE_INSTALL_PREFIX so that distros don't break 2 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 3 | set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Default installation path" FORCE) 4 | endif() 5 | 6 | # REQUIRE GIT to be present 7 | if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) 8 | message(FATAL_ERROR "WAVA from 0.7.0 onwards requires to be built in a .git directory") 9 | endif() 10 | 11 | # Fix pkg-config for cross-builds (such as MinGW on ArchLinux) 12 | if(CMAKE_FIND_ROOT_PATH) 13 | set(CMAKE_SYSROOT "${CMAKE_FIND_ROOT_PATH}") 14 | 15 | set(ENV{PKG_CONFIG_DIR} "") 16 | set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/lib/pkgconfig:${CMAKE_SYSROOT}/share/pkgconfig") 17 | set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT}) 18 | endif() 19 | 20 | if(UNIX_INDEPENDENT_PATHS) 21 | add_definitions("-DUNIX_INDEPENDENT_PATHS") 22 | endif() 23 | 24 | -------------------------------------------------------------------------------- /src/output/shared/cairo/util/region.c: -------------------------------------------------------------------------------- 1 | #include "shared.h" 2 | #include "region.h" 3 | 4 | // returns false on pass 5 | // returns true on region conflict 6 | bool wava_cairo_region_list_check(wava_cairo_region *A, 7 | wava_cairo_region *B) { 8 | // computational complexity high == low bugs (hopefully) 9 | for(size_t a = 0; a < arr_count(A); a++) { 10 | for(size_t b = 0; b < arr_count(B); b++) { 11 | if(A[a].x+A[a].w < B[b].x) continue; // outside of bounds X positive 12 | if(A[a].x > B[b].x+B[b].w) continue; // outside of bounds X negative 13 | if(A[a].y+A[a].h < B[b].y) continue; // outside of bounds Y positive 14 | if(A[a].y > B[b].y+B[b].h) continue; // outside of bounds Y negative 15 | return true; // all checks failing meaning a box intersection occured 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/output/shared/gl/egl.h: -------------------------------------------------------------------------------- 1 | #ifndef __EGL_H 2 | #define __EGL_H 3 | 4 | #ifndef EGL 5 | #define EGL 6 | #endif 7 | #include "main.h" 8 | 9 | struct _escontext { 10 | // because windowing systems are complicated 11 | EGLNativeDisplayType native_display; 12 | EGLNativeWindowType native_window; 13 | 14 | // EGL display 15 | EGLDisplay display; 16 | // EGL context 17 | EGLContext context; 18 | // EGL surface 19 | EGLSurface surface; 20 | }; 21 | 22 | void EGLConfigLoad(WAVA *wava); 23 | EGLBoolean EGLCreateContext(WAVA *wava, struct _escontext *ESContext); 24 | void EGLInit(WAVA *wava); 25 | void EGLApply(WAVA *wava); 26 | XG_EVENT_STACK *EGLEvent(WAVA *wava); 27 | void EGLClear(WAVA *wava); 28 | void EGLDraw(WAVA *wava); 29 | void EGLCleanup(WAVA *wava, struct _escontext *ESContext); 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/bars_circle/fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | // color passed from the host 4 | uniform vec4 foreground_color; 5 | 6 | // color passed from the host 7 | uniform vec4 background_color; 8 | 9 | // number of secionts that the gradient is divided to 10 | uniform float gradient_sections; 11 | 12 | // each of the gradient colors 13 | uniform vec4 gradient_color[8]; 14 | 15 | // screen width and height 16 | uniform vec2 resolution; 17 | 18 | uniform float intensity; 19 | 20 | layout(location=0) out vec4 FragColor; 21 | 22 | void main() { 23 | if(gradient_sections > 0.0) { 24 | float across = (gl_FragCoord.y/resolution.y)*gradient_sections; 25 | int section = int(floor(across)); 26 | float off = mod(across, 1.0); 27 | FragColor = mix(gradient_color[section], gradient_color[section+1], off); 28 | } else { 29 | FragColor = foreground_color; 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/cairo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef CAIRO 4 | #define CAIRO 5 | #endif 6 | 7 | #ifndef SHM 8 | #define SHM 9 | #endif 10 | 11 | #include "main.h" 12 | #include "output/shared/cairo/main.h" 13 | 14 | void wava_output_wayland_cairo_init(struct waydata *wd) { 15 | wd->cairo_surface = cairo_image_surface_create_for_data(wd->shm.buffer, 16 | CAIRO_FORMAT_ARGB32, wd->shm.dim.w, wd->shm.dim.h, wd->shm.dim.stride); 17 | __internal_wava_output_cairo_init(wd->cairo_handle, 18 | cairo_create(wd->cairo_surface)); 19 | } 20 | 21 | void wava_output_wayland_cairo_resize(struct waydata *wd) { 22 | cairo_surface_destroy(wd->cairo_surface); 23 | wd->cairo_surface = cairo_image_surface_create_for_data(wd->shm.buffer, 24 | CAIRO_FORMAT_ARGB32, wd->shm.dim.w, wd->shm.dim.h, wd->shm.dim.stride); 25 | wd->cairo_handle->cr = cairo_create(wd->cairo_surface); 26 | } 27 | -------------------------------------------------------------------------------- /src/input/sndio/build.cmake: -------------------------------------------------------------------------------- 1 | # The project default 2 | option(SNDIO "SNDIO" ON) 3 | 4 | # sndio 5 | if(SNDIO) 6 | find_library(SNDIO_LIB sndio HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 7 | if(SNDIO_LIB) 8 | add_definitions(-DSNDIO) 9 | add_library(in_sndio SHARED "${WAVA_MODULE_DIR}/main.c" 10 | "${GLOBAL_FUNCTION_SOURCES}") 11 | target_link_libraries(in_sndio wava-shared "-lsndio") 12 | set_target_properties(in_sndio PROPERTIES PREFIX "") 13 | install(TARGETS in_sndio DESTINATION lib/wava) 14 | 15 | # Add legal disclaimer 16 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_sndio.txt" 17 | "SNDIO license can be obtained at: https://en.wikipedia.org/wiki/ISC_license#License_terms on behalf of Alexandre Ratchov (C) 2013\n") 18 | else() 19 | message(WARNING "SNDIO library missing; SNDIO won't build") 20 | endif() 21 | endif() 22 | 23 | -------------------------------------------------------------------------------- /src/output/shared/util/media/artwork.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVA_UTIL_MEDIA_INFO_ARTWORK_H 2 | #define WAVA_UTIL_MEDIA_INFO_ARTWORK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct artwork { 9 | unsigned char *file_data; 10 | unsigned char *image_data; 11 | bool ready; 12 | size_t size; 13 | int w, h, c; 14 | }; 15 | 16 | // probably never used but kept in case they eventually are 17 | #define URI_HEADER_FILE "file://" 18 | #define URI_HEADER_HTTPS "https://" 19 | #define URI_HEADER_HTTP "http://" 20 | #define URI_HEADER_MUSIC "music-file://" 21 | 22 | void wava_util_artwork_destroy(struct artwork *artwork); 23 | void wava_util_artwork_update(const char *url, 24 | struct artwork *artwork, CURL *curl); 25 | 26 | // for internal use ONLY 27 | bool wava_util_artwork_update_by_audio_file(const char *url, 28 | struct artwork *artwork); 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /src/output/default/build.cmake: -------------------------------------------------------------------------------- 1 | 2 | foreach(name out_cairo out_opengl) 3 | add_library(${name} SHARED 4 | "${WAVA_MODULE_DIR}/main.c" 5 | ${DEFAULT_OUTPUT_SOURCES} 6 | "${GLOBAL_FUNCTION_SOURCES}") 7 | 8 | target_link_libraries (${name} wava-shared ${DEFAULT_OUTPUT_LINKLIB}) 9 | target_include_directories(${name} PRIVATE ${DEFAULT_OUTPUT_INCDIR}) 10 | target_link_directories (${name} PRIVATE ${DEFAULT_OUTPUT_LINKDIR}) 11 | set_target_properties (${name} PROPERTIES PREFIX "") 12 | 13 | if(${name} STREQUAL "out_cairo") 14 | set(OUTPUT_DEFAULT_DEFINE "-DCAIRO") 15 | elseif(${name} STREQUAL "out_opengl") 16 | set(OUTPUT_DEFAULT_DEFINE "-DOPENGL") 17 | endif() 18 | 19 | target_compile_definitions(${name} PUBLIC ${OUTPUT_DEFAULT_DEFINE} ${DEFAULT_OUTPUT_DEF}) 20 | 21 | install(TARGETS ${name} DESTINATION lib/wava) 22 | 23 | find_and_copy_dlls(${name}) 24 | endforeach() 25 | -------------------------------------------------------------------------------- /src/output/shared/gl/util/misc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "misc.h" 4 | 5 | float wava_gl_module_util_calculate_intensity(WAVA *wava) { 6 | WAVA_CONFIG *conf = &wava->conf; 7 | 8 | float intensity = 0.0; 9 | 10 | for(register uint32_t i=0; ibars; i++) { 11 | // the not so, speed part 12 | // intensity has a low-freq bias as they are more "physical" 13 | float bar_percentage = (float)(wava->f[i]-1)/(float)conf->h; 14 | if(bar_percentage > 0.0) { 15 | intensity+=powf(bar_percentage, 16 | (float)2.0*(float)i/(float)wava->bars); 17 | } 18 | } 19 | 20 | // since im not bothering to do the math, this'll do 21 | // - used to balance out intensity across various number of bars 22 | intensity /= wava->bars; 23 | 24 | return intensity; 25 | } 26 | 27 | float wava_gl_module_util_obtain_time(void) { 28 | return (float)fmodl((long double)wavaGetTime()/(long double)1000.0, 3600.0); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /.github/actions/prepare/action.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | system: 3 | description: 'Target operating system' 4 | required: true 5 | default: 'archlinux' 6 | arch: 7 | description: 'Target architecture' 8 | required: true 9 | default: 'x86_64' 10 | 11 | runs: 12 | using: 'composite' 13 | steps: 14 | # Differentiate between ACT and actual GitHub Actions 15 | - uses: docker/setup-buildx-action@v2 16 | if: ${{ env.ACT }} 17 | with: 18 | driver: docker 19 | - uses: docker/setup-buildx-action@v2 20 | if: ${{ !env.ACT }} 21 | - name: Prepare image 22 | uses: docker/build-push-action@v3 23 | with: 24 | load: true 25 | file: '.github/docker/${{ inputs.system }}/Dockerfile' 26 | context: .github/docker/${{ inputs.system }} 27 | cache-from: type=gha,scope=buildkit-${{ inputs.system }}-${{ inputs.arch }} 28 | cache-to: type=gha,mode=min,scope=buildkit-${{ inputs.system }}-${{ inputs.arch }} 29 | tags: xava-build-${{ inputs.system }}:latest 30 | 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /src/input/alsa/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(ALSA "ALSA" ON) 3 | 4 | # alsa 5 | if(ALSA) 6 | pkg_check_modules(ALSA QUIET alsa) 7 | if(ALSA_FOUND) 8 | add_definitions(-DALSA) 9 | add_library(in_alsa SHARED "${WAVA_MODULE_DIR}/main.c" 10 | "${GLOBAL_FUNCTION_SOURCES}") 11 | target_link_libraries(in_alsa wava-shared "${ALSA_LIBRARIES}") 12 | target_include_directories(in_alsa PRIVATE "${ALSA_INCLUDE_DIRS}") 13 | target_link_directories(in_alsa PRIVATE "${ALSA_LIBRARY_DIRS}") 14 | set_target_properties(in_alsa PROPERTIES PREFIX "") 15 | install(TARGETS in_alsa DESTINATION lib/wava) 16 | 17 | # Add legal disclaimer 18 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_alsa.txt" 19 | "ALSA-lib license can be obtained at: https://raw.githubusercontent.com/alsa-project/alsa-lib/master/COPYING\n") 20 | else() 21 | message(WARNING "ALSA library not found, ALSA won't build") 22 | endif() 23 | endif() 24 | 25 | -------------------------------------------------------------------------------- /src/shared/util/version.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_SHARED_VERSION_H 2 | #define __WAVA_SHARED_VERSION_H 3 | #include 4 | 5 | typedef enum WAVA_VERSION_COMPATIBILITY { 6 | WAVA_VERSIONS_COMPATIBLE, 7 | WAVA_VERSIONS_INCOMPATIBLE, 8 | WAVA_VERSIONS_UNKNOWN, 9 | } WAVA_VERSION_COMPATIBILITY; 10 | 11 | typedef struct wava_version { 12 | int major; 13 | int minor; 14 | int tweak; 15 | int patch; 16 | } wava_version; 17 | 18 | wava_version wava_version_host_get(void); 19 | bool wava_version_less(wava_version host, wava_version target); 20 | bool wava_version_greater(wava_version host, wava_version target); 21 | bool wava_version_equal(wava_version host, wava_version target); 22 | bool wava_version_breaking_check(wava_version target); 23 | WAVA_VERSION_COMPATIBILITY wava_version_verify(wava_version target); 24 | 25 | #define wava_version_get() (wava_version){WAVA_VERSION_MAJOR, WAVA_VERSION_MINOR, WAVA_VERSION_TWEAK, WAVA_VERSION_PATCH} 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/wl_output.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_WL_OUTPUT_H 2 | #define __WAYLAND_WL_OUTPUT_H 3 | 4 | #include "gen/xdg-output-unstable-v1-client-protocol.h" 5 | #include "gen/wlr-layer-shell-unstable-v1-client-protocol.h" 6 | 7 | #include "main.h" 8 | 9 | struct wlOutput { 10 | struct wl_output *output; 11 | uint32_t scale; 12 | 13 | // im not calling this a "name" because that's **fucking** retarded 14 | uint32_t id; 15 | 16 | uint32_t width; 17 | uint32_t height; 18 | char *name; 19 | uint32_t num; 20 | struct zxdg_output_v1 *xdg_output; 21 | struct wl_list link; 22 | }; 23 | 24 | extern struct zxdg_output_manager_v1 *wavaXDGOutputManager; 25 | extern struct zxdg_output_v1_listener xdg_output_listener; 26 | extern const struct wl_output_listener output_listener; 27 | 28 | struct wlOutput *wl_output_get_desired(); 29 | extern void wl_output_cleanup(struct waydata *wd); 30 | extern void wl_output_init(struct waydata *wd); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /.github/docker/windows/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM archlinux:latest 2 | 3 | LABEL org.opencontainers.image.source https://github.com/nikp123/xava 4 | 5 | WORKDIR /mnt 6 | 7 | # Append ownstuff's repo to the arch install 8 | RUN echo $'\n\ 9 | [ownstuff]\n\ 10 | Server = https://martchus.no-ip.biz/repo/arch/$repo/os/$arch\n\ 11 | Server = https://ftp.f3l.de/~martchus/$repo/os/$arch\n\ 12 | SigLevel = Optional TrustAll' >> /etc/pacman.conf 13 | 14 | # Update Arch 15 | RUN yes | pacman -Syyu --noconfirm; yes | pacman -Scc 16 | 17 | # Install basic C/C++ development tools 18 | RUN yes | pacman --noconfirm -S binutils mingw-w64-binutils mingw-w64-crt \ 19 | mingw-w64-headers mingw-w64-winpthreads mingw-w64-cmake mingw-w64-gcc \ 20 | mingw-w64-extra-cmake-modules mingw-w64-make mingw-w64-pkg-config make \ 21 | ; yes | pacman -Scc 22 | 23 | # Install cross-compiler XAVA dependencies 24 | RUN yes | pacman -S --noconfirm git mingw-w64-fftw nsis mingw-w64-sdl2 \ 25 | mingw-w64-cairo mingw-w64-portaudio mingw-w64-winpthreads python \ 26 | mingw-w64-glew rust mingw-w64-curl \ 27 | ; yes | pacman -Scc 28 | 29 | -------------------------------------------------------------------------------- /src/filters/default/build.cmake: -------------------------------------------------------------------------------- 1 | # Default filter, is well..... default 2 | option(FILTER_DEFAULT "FILTER_DEFAULT" ON) 3 | 4 | # fftw3 5 | pkg_check_modules(FFTW3 REQUIRED fftw3f) 6 | list(APPEND INCLUDE_DIRS "${FFTW3_INCLUDE_DIRS}") 7 | list(APPEND LINK_DIRS "${FFTW3_LIBRARY_DIRS}") 8 | 9 | if(FILTER_DEFAULT) 10 | message(STATUS "Default filter enabled!") 11 | add_library(filter_default SHARED "${WAVA_MODULE_DIR}/main.c" 12 | "${GLOBAL_FUNCTION_SOURCES}") 13 | target_link_libraries(filter_default wava-shared "${FFTW3_LIBRARIES}") 14 | target_link_directories(filter_default PRIVATE "${FFTW3_LIBRARY_DIRS}") 15 | set_target_properties(filter_default PROPERTIES PREFIX "") 16 | target_include_directories(filter_default PRIVATE ${FFTW3_INCLUDE_DIRS}) 17 | install(TARGETS filter_default DESTINATION lib/wava) 18 | 19 | find_and_copy_dlls(filter_default) 20 | 21 | # Add legal disclaimer 22 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_fftw.txt" 23 | "FFTW License can be obtained at: http://fftw.org/doc/License-and-Copyright.html\n") 24 | endif() 25 | 26 | -------------------------------------------------------------------------------- /src/output/unsupported/terminal_ncurses/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(NCURSES "NCURSES" ON) 3 | 4 | # NCURSES 5 | if(NCURSES) 6 | pkg_check_modules(NCURSES QUIET ncurses) 7 | if(NCURSES_FOUND) 8 | add_library(out_ncurses SHARED 9 | "${WAVA_MODULE_DIR}/main.c" 10 | "src/output/shared/graphical.c" 11 | "${GLOBAL_FUNCTION_SOURCES}") 12 | target_link_libraries(out_ncurses wava-shared "${NCURSES_LIBRARIES}") 13 | target_include_directories(out_ncurses PRIVATE "${NCURSES_INCLUDE_DIRS}") 14 | target_link_directories(out_ncurses PRIVATE "${NCURSES_LIBRARY_DIRS}") 15 | set_target_properties(out_ncurses PROPERTIES PREFIX "") 16 | install(TARGETS out_ncurses DESTINATION lib/wava) 17 | 18 | # Add legal disclaimer 19 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_ncurses.txt" 20 | "NCurses license can be obtained at: https://raw.githubusercontent.com/ELLIOTTCABLE/ncurses/master/license.txt\n") 21 | else() 22 | message(WARNING "NCurses library not found; NCurses won't build") 23 | endif() 24 | endif() 25 | -------------------------------------------------------------------------------- /src/input/pipewire/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(PIPEWIRE "PIPEWIRE" ON) 3 | 4 | # libpipewire-0.3 5 | if(PIPEWIRE) 6 | pkg_check_modules(PIPEWIRE QUIET libspa-0.2 libpipewire-0.3) 7 | if(PIPEWIRE_FOUND) 8 | add_definitions(-DPIPEWIRE) 9 | add_library(in_pipewire SHARED "${WAVA_MODULE_DIR}/main.c" 10 | "${GLOBAL_FUNCTION_SOURCES}") 11 | target_link_libraries(in_pipewire wava-shared "${PIPEWIRE_LIBRARIES}") 12 | target_include_directories(in_pipewire PRIVATE "${PIPEWIRE_INCLUDE_DIRS}") 13 | target_link_directories(in_pipewire PRIVATE "${PIPEWIRE_LIBRARY_DIRS}") 14 | set_target_properties(in_pipewire PROPERTIES PREFIX "") 15 | install(TARGETS in_pipewire DESTINATION lib/wava) 16 | 17 | # Add legal disclaimer 18 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_pipewire.txt" 19 | "PipeWire license can be obtained at: https://raw.githubusercontent.com/PipeWire/pipewire/master/COPYING\n") 20 | else() 21 | message(WARNING "PipeWire library not found, PipeWire won't build") 22 | endif() 23 | endif() 24 | 25 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/stars/config.ini: -------------------------------------------------------------------------------- 1 | # Config options related to the "stars" gl module 2 | # Remove ';' for the config options to apply 3 | 4 | [stars] 5 | 6 | # Change star color in AARRGGB hex fashion 7 | color = "#fa6987" 8 | 9 | # Set a specific number of stars. If enabled, "density" will stop working. 10 | count = 8192 11 | 12 | # Control density of stars on the screen. Calculates the number of stars 13 | # relative to screen resolution and this is just a simple scalar to that 14 | # WARNING: Setting this value too high may cause graphical glitches due 15 | # to Cairo draw limits 16 | # density = 16.0 17 | 18 | # Set maximum star size (in pixels) 19 | max_size = 12 20 | 21 | # Enable/disable depth test for the stars. 22 | # This is used for cases where the depth buffer is undesired for the stars, such 23 | # as when using the shadow post shader. 24 | depth_test = true 25 | 26 | # Set maximum random star shrink. 27 | max_shrink = 0.5 28 | 29 | # Set minimum random star shrink. 30 | min_shrink = 1.1 31 | 32 | # Intensity multiplier. 33 | intensity_multiplier = 1.66 34 | 35 | # Time multiplier. 36 | time_multiplier = 1.66 37 | -------------------------------------------------------------------------------- /.github/docker/archlinux/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf build 4 | 5 | set -e 6 | 7 | # Fix build issue from Actions 8 | git config --global --add safe.directory /github/workspace 9 | 10 | # Build dir 11 | mkdir build 12 | cd build 13 | 14 | # Build AppImage version of XAVA 15 | cmake .. -DUNIX_INDEPENDENT_PATHS=ON -DCMAKE_BUILD_TYPE=Release 16 | make -j$(nproc) 17 | make install DESTDIR=AppDir 18 | 19 | # Fix AppImage not running due to the lack of FUSE 20 | export APPIMAGE_EXTRACT_AND_RUN=1 21 | 22 | # Create AppImage 23 | env LD_LIBRARY_PATH=. linuxdeploy \ 24 | --appdir AppDir \ 25 | --output appimage \ 26 | --icon-filename AppDir/usr/share/icons/hicolor/scalable/apps/xava.svg \ 27 | --desktop-file AppDir/usr/share/applications/xava.desktop \ 28 | -llibxava-shared.so 29 | 30 | # Fix the filename 31 | commit_branch="$(echo ${GITHUB_REF#refs/heads/})" 32 | commit_sha="$(git rev-parse --short HEAD)" 33 | 34 | mv XAVA-$commit_sha-x86_64.AppImage xava-x86_64.AppImage 35 | chmod +x xava-x86_64.AppImage 36 | 37 | # Extract version info 38 | cat CMakeCache.txt | grep xava_VERSION | cut -d'=' -f2 > version.txt 39 | 40 | # Leave directory 41 | cd .. 42 | 43 | -------------------------------------------------------------------------------- /.github/docker/windows/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # CPU architecture 4 | arch=$1 5 | 6 | rm -rf release 7 | rm -rf debug 8 | 9 | # Bail on error 10 | set -e 11 | 12 | build_args="-j$(nproc)" 13 | cmake_args='-DCMAKE_INSTALL_PREFIX=/usr' 14 | 15 | # toolchain prefixes because C 16 | tool_prefix="$arch-w64-mingw32" 17 | 18 | # Fix build issue from Actions 19 | git config --global --add safe.directory /github/workspace 20 | 21 | echo "Testing CMake on $arch" 22 | $tool_prefix-cmake --version 23 | 24 | # Try debug build 25 | mkdir debug 26 | cd debug 27 | echo "Trying debug for $arch" 28 | $tool_prefix-cmake "$cmake_args" -DCMAKE_BUILD_TYPE=Debug -Werror=dev .. 29 | make $build_args 30 | cd .. 31 | rm -rf debug 32 | 33 | # Release build 34 | mkdir release 35 | cd release 36 | echo "Trying release for $arch" 37 | $tool_prefix-cmake "$cmake_args" -DCMAKE_BUILD_TYPE=Release -Werror=dev .. 38 | make $build_args 39 | 40 | # Make installer and move it to the last directory 41 | echo "Buidling installer for $arch" 42 | makensis xava.nsi 43 | mv xava-win-installer.exe ../xava-installer-$arch.exe 44 | cd .. 45 | rm -rf release 46 | 47 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/stars/config.ini: -------------------------------------------------------------------------------- 1 | # Config options related to the "stars" gl module 2 | # Remove ';' for the config options to apply 3 | 4 | [stars] 5 | 6 | # Change star color in AARRGGB hex fashion 7 | ; color = "#ffffffff" 8 | 9 | # Set a specific number of stars. If enabled, "density" will stop working. 10 | ; count = 100 11 | 12 | # Control density of stars on the screen. Calculates the number of stars 13 | # relative to screen resolution and this is just a simple scalar to that 14 | # WARNING: Setting this value too high may cause graphical glitches due 15 | # to Cairo draw limits 16 | ; density = 1.0 17 | 18 | # Set maximum star size (in pixels) 19 | ; max_size = 5 20 | 21 | # Enable/disable depth test for the stars. 22 | # This is used for cases where the depth buffer is undesired for the stars, such 23 | # as when using the shadow post shader. 24 | ; depth_test = false 25 | 26 | 27 | # Set maximum random star shrink. 28 | ; max_shrink = 0.5 29 | 30 | # Set minimum random star shrink. 31 | ; min_shrink = 1.1 32 | 33 | # Intensity multiplier. 34 | ; intensity_multiplier = 1.5 35 | 36 | # Time multiplier. 37 | ; time_multiplier = 1.5 38 | -------------------------------------------------------------------------------- /src/input/pulseaudio/build.cmake: -------------------------------------------------------------------------------- 1 | # The project default 2 | option(PULSEAUDIO "PULSEAUDIO" ON) 3 | 4 | # pulseaudio 5 | if(PULSEAUDIO) 6 | pkg_check_modules(PULSEAUDIO QUIET libpulse libpulse-simple) 7 | if(PULSEAUDIO_FOUND) 8 | add_definitions(-DPULSE) 9 | add_library(in_pulseaudio SHARED "${WAVA_MODULE_DIR}/main.c" 10 | "${GLOBAL_FUNCTION_SOURCES}") 11 | target_link_libraries(in_pulseaudio wava-shared "${PULSEAUDIO_LIBRARIES}") 12 | target_include_directories(in_pulseaudio PRIVATE "${PULSEAUDIO_INCLUDE_DIRS}") 13 | target_link_directories(in_pulseaudio PRIVATE "${PULSEAUDIO_LIBRARY_DIRS}") 14 | set_target_properties(in_pulseaudio PROPERTIES PREFIX "") 15 | install(TARGETS in_pulseaudio DESTINATION lib/wava) 16 | 17 | # Add legal disclaimer 18 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_pulseaudio.txt" 19 | "PulseAudio license can be obtained at: https://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/LICENSE\n") 20 | else() 21 | message(WARNING "PulseAudio library not found, PulseAudio won't build") 22 | endif() 23 | endif() 24 | 25 | -------------------------------------------------------------------------------- /assets/windows/readme.txt: -------------------------------------------------------------------------------- 1 | WAVA @wava_VERSION@ README file 2 | --- 3 | 4 | Copyright MIT 2021 Nikola Pavlica 5 | 6 | WAVA is an audio visualizer that aims to aesthetically display music or any sound 7 | playing on the computer. 8 | 9 | Using it is simple, just launch the appropriate application shortcut for the 10 | application to open. In case it doesn't open or you want to customize anything 11 | about the visualizer, please refer to https://github.com/nikp123/wava for further 12 | information. 13 | 14 | Since you're probably running Windows as your operating system of choice, the 15 | config file can be found at %APPDATA%\wava\config.cfg or just use the 16 | "Configure WAVA" shortcut found in your Start Menu. 17 | 18 | In case it is not there, just run the visualizer once again and it will 19 | automatically generate that file for you. 20 | 21 | The file is self-documenting so that you won't have to scour the internet in 22 | order to figure out how to use the program. In any case, there's always the 23 | aforementioned project frontpage for more information. 24 | 25 | If you like the project, you're able to donate here (via PayPal): 26 | https://paypal.me/nikp123 27 | 28 | Have fun :D 29 | 30 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/egl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "output/shared/graphical.h" 8 | #include "output/shared/gl/egl.h" 9 | 10 | #include "egl.h" 11 | #include "main.h" 12 | 13 | void waylandEGLCreateWindow(struct waydata *wd) { 14 | //region = wl_compositor_create_region(wd->compositor); 15 | //wl_region_add(region, 0, 0, width, height); 16 | //wl_surface_set_opaque_region(surface, region); 17 | 18 | struct wl_egl_window *egl_window = wl_egl_window_create(wd->surface, 19 | wd->hand->conf.w, wd->hand->conf.h); 20 | 21 | wavaBailCondition(egl_window == EGL_NO_SURFACE, 22 | "Failed to create EGL window!\n"); 23 | 24 | wavaSpam("Created EGL window!"); 25 | 26 | wd->ESContext.native_window = (EGLNativeWindowType)egl_window; 27 | wd->ESContext.native_display = wd->display; 28 | } 29 | 30 | void waylandEGLWindowResize(struct waydata *wd, int w, int h) { 31 | wl_egl_window_resize((struct wl_egl_window*)wd->ESContext.native_window, 32 | w, h, 0, 0); 33 | wl_surface_commit(wd->surface); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/output/shared/cairo/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_OUTPUT_SHARED_CAIRO_H 2 | #define __WAVA_OUTPUT_SHARED_CAIRO_H 3 | 4 | #include 5 | #include "shared.h" 6 | #include "util/feature_compat.h" 7 | #include "util/module.h" 8 | 9 | typedef struct wava_cairo_handle { 10 | WAVA *wava; 11 | cairo_t *cr; // name used by a lot of docs, so I'm going with it 12 | 13 | XG_EVENT_STACK *events; 14 | 15 | wava_cairo_module *modules; 16 | WAVA_CAIRO_FEATURE feature_level; 17 | } wava_cairo_handle; 18 | 19 | wava_cairo_handle *__internal_wava_output_cairo_load_config( 20 | WAVA *wava); 21 | void __internal_wava_output_cairo_init(wava_cairo_handle *handle, 22 | cairo_t *cr); 23 | void __internal_wava_output_cairo_apply(wava_cairo_handle *handle); 24 | XG_EVENT_STACK *__internal_wava_output_cairo_event(wava_cairo_handle *handle); 25 | void __internal_wava_output_cairo_draw(wava_cairo_handle *handle); 26 | void __internal_wava_output_cairo_clear(wava_cairo_handle *handle); 27 | void __internal_wava_output_cairo_cleanup(wava_cairo_handle *handle); 28 | 29 | #endif //__WAVA_OUTPUT_SHARED_CAIRO_H 30 | 31 | -------------------------------------------------------------------------------- /src/output/shared/cairo/util/feature_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_OUTPUT_SHARED_CAIRO_FEATURE_COMPAT_H 2 | #define __WAVA_OUTPUT_SHARED_CAIRO_FEATURE_COMPAT_H 3 | // Since drawing full frames is expensive, this "feature checker" is put in 4 | // place of it 5 | 6 | #include 7 | 8 | // this is a bitmask so you'll have to OR these values together 9 | typedef enum WAVA_CAIRO_FEATURE { 10 | // reports that the cairo module can only draw full frames, trashing any 11 | // old data in the process. all other modules must support this for it to 12 | // work 13 | WAVA_CAIRO_FEATURE_FULL_DRAW = 1, 14 | // reports that the cairo module can only in certain regions and that it's 15 | // drawing operation depends on the old data and therefore is unsafe if 16 | // those regions conflict 17 | WAVA_CAIRO_FEATURE_DRAW_REGION = 2, 18 | // reports that the cairo module draws in a certain regions, but in a safe 19 | // manner meaning that it can "overwrite" previous data without depending 20 | // on the state of the fremebuffer. or in other words, "safe" 21 | WAVA_CAIRO_FEATURE_DRAW_REGION_SAFE = 4, 22 | } WAVA_CAIRO_FEATURE; 23 | 24 | bool wava_cairo_feature_compatibility_assert(WAVA_CAIRO_FEATURE a); 25 | 26 | #endif //__WAVA_OUTPUT_SHARED_CAIRO_FEATURE_COMPAT_H 27 | 28 | -------------------------------------------------------------------------------- /src/shared/ionotify.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_SHARED_IONOTIFY_H 2 | #define __WAVA_SHARED_IONOTIFY_H 3 | 4 | #include 5 | 6 | typedef void* WAVAIONOTIFY; 7 | typedef struct wava_ionotify_watch_setup* WAVAIONOTIFYWATCHSETUP; 8 | 9 | // make the compilers shuttings up 10 | typedef struct WAVA WAVA; 11 | 12 | // doubt that WAVA_IONOTIFY_DELETED ever be implemented, but I don't care 13 | typedef enum wava_ionotify_event { 14 | WAVA_IONOTIFY_NOTHING, 15 | WAVA_IONOTIFY_ERROR, 16 | WAVA_IONOTIFY_CHANGED, 17 | WAVA_IONOTIFY_DELETED, 18 | WAVA_IONOTIFY_CLOSED 19 | } WAVA_IONOTIFY_EVENT; 20 | 21 | struct wava_ionotify_watch_setup { 22 | WAVAIONOTIFY ionotify; 23 | int id; 24 | char *filename; 25 | WAVA *wava; 26 | void (*wava_ionotify_func)(WAVA_IONOTIFY_EVENT, 27 | const char *filename, 28 | int id, 29 | WAVA*); 30 | }; 31 | 32 | extern WAVAIONOTIFY wavaIONotifySetup(void); 33 | extern bool wavaIONotifyAddWatch(WAVAIONOTIFYWATCHSETUP setup); 34 | extern bool wavaIONotifyStart(const WAVAIONOTIFY ionotify); 35 | extern void wavaIONotifyKill(const WAVAIONOTIFY ionotify); 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/shared/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_OUTPUT_CAIRO_MODULE_UTIL_CONFIG 2 | #define __WAVA_OUTPUT_CAIRO_MODULE_UTIL_CONFIG 3 | 4 | #include "output/shared/cairo/util/module.h" 5 | 6 | typedef enum wava_cairo_file_type { 7 | WAVA_CAIRO_FILE_CONFIG, // for loading wava_config_source-es 8 | WAVA_CAIRO_FILE_CONFIG_CUSTOM_READ, // for loading any file found in the config dir 9 | WAVA_CAIRO_FILE_CONFIG_CUSTOM_WRITE, // the same as above 10 | WAVA_CAIRO_FILE_INSTALL_READ, // for loading any files off of the install 11 | WAVA_CAIRO_FILE_ERROR, // placeholder 12 | } wava_cairo_file_type; 13 | 14 | /** 15 | * A config/custom file helper for WAVA_CAIRO modules 16 | * 17 | * 1. You need to specify what type the file actually is 18 | * 2. A reference to the module that called it 19 | * 3. Local file name within your designated config folder for your module. 20 | * 4. If non-NULL, will write the full output file path here 21 | * 22 | * The return pointer where the resulting FILE* or wava_config_source gets put 23 | * 24 | * On fail the function returns a NULL 25 | **/ 26 | void *wava_cairo_module_file_load( 27 | wava_cairo_file_type type, 28 | wava_cairo_module_handle *module, 29 | const char *file_name, 30 | char *returned_path); 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_MAIN_H 2 | #define __WAYLAND_MAIN_H 3 | 4 | #ifdef EGL 5 | #include 6 | #include "output/shared/gl/egl.h" 7 | #endif 8 | 9 | #ifdef CAIRO 10 | #include 11 | #include "output/shared/cairo/main.h" 12 | #endif 13 | 14 | #include 15 | 16 | #include "shared.h" 17 | 18 | struct waydata { 19 | struct wl_surface *surface; 20 | struct wl_display *display; 21 | struct wl_compositor *compositor; 22 | WAVA *hand; 23 | XG_EVENT_STACK *events; 24 | struct wl_list outputs; 25 | #ifdef EGL 26 | struct _escontext ESContext; 27 | #endif 28 | #ifdef SHM 29 | struct wayland_shm { 30 | struct dimenisions { 31 | uint32_t w; 32 | uint32_t h; 33 | uint32_t stride; 34 | } dim; 35 | struct wl_shm *ref; 36 | uint32_t max_size; 37 | uint8_t *buffer; 38 | int32_t fd; 39 | bool fb_unsafe; 40 | } shm; 41 | #endif 42 | #ifdef CAIRO 43 | cairo_surface_t *cairo_surface; 44 | wava_cairo_handle *cairo_handle; 45 | #endif 46 | }; 47 | 48 | 49 | extern const struct wl_callback_listener wl_surface_frame_listener; 50 | 51 | extern char* monitorName; 52 | 53 | EXP_FUNC void wavaOutputClear(WAVA *hand); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/input/portaudio/build.cmake: -------------------------------------------------------------------------------- 1 | # The project default 2 | option(PORTAUDIO "PORTAUDIO" ON) 3 | 4 | if(PORTAUDIO) 5 | pkg_check_modules(PORTAUDIO QUIET portaudio-2.0) 6 | if(PORTAUDIO_FOUND) 7 | # Deal with fucking windows 8 | if(MSVC OR MINGW OR MSYS) 9 | set(CMAKE_EXE_LINKER_FLAGS "-static") 10 | set(PORTAUDIO_LIBRARIES "${PORTAUDIO_LIBRARIES} -lmingw32 -mwindows \ 11 | -static-libgcc -lwinmm -lsetupapi") 12 | endif() 13 | 14 | add_definitions(-DPORTAUDIO) 15 | add_library(in_portaudio SHARED "${WAVA_MODULE_DIR}/main.c" 16 | "${GLOBAL_FUNCTION_SOURCES}") 17 | target_link_libraries(in_portaudio wava-shared "${PORTAUDIO_LIBRARIES}") 18 | target_include_directories(in_portaudio PRIVATE "${PORTAUDIO_INCLUDE_DIRS}") 19 | target_link_directories(in_portaudio PRIVATE "${PORTAUDIO_LIBRARY_DIRS}") 20 | set_target_properties(in_portaudio PROPERTIES PREFIX "") 21 | install(TARGETS in_portaudio DESTINATION lib/wava) 22 | 23 | find_and_copy_dlls(in_portaudio) 24 | 25 | # Add legal disclaimer 26 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_portaudio.txt" 27 | "PortAudio license can be obtained at: http://www.portaudio.com/license.html\n") 28 | else() 29 | message(WARNING "PortAudio library not found, PortAudio won't build") 30 | endif() 31 | endif() 32 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/kinetic/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(CAIRO_MODULES "CAIRO_MODULES" ON) 3 | 4 | if(CAIRO_MODULES) 5 | pkg_check_modules(CAIRO QUIET cairo) 6 | if(CAIRO_FOUND) 7 | add_library(cairo_kinetic SHARED "${WAVA_MODULE_DIR}/main.c" 8 | "${GLOBAL_FUNCTION_SOURCES}") 9 | #"${WAVA_MODULE_DIR}/../../" 10 | 11 | target_link_directories(cairo_kinetic PRIVATE 12 | "${CAIRO_LIBRARY_DIRS}") 13 | target_include_directories(cairo_kinetic PRIVATE 14 | "${CAIRO_INCLUDE_DIRS}") 15 | target_link_libraries(cairo_kinetic wava-shared "${CAIRO_LIBRARIES}") 16 | 17 | target_compile_definitions(cairo_kinetic PUBLIC -DCAIRO) 18 | set_target_properties(cairo_kinetic PROPERTIES PREFIX "") 19 | set_target_properties(cairo_kinetic PROPERTIES IMPORT_PREFIX "") 20 | configure_file("${WAVA_MODULE_DIR}/config.ini" cairo/module/kinetic/config.ini COPYONLY) 21 | 22 | # this copies the dlls for mr. windows 23 | #find_and_copy_dlls(cairo_kinetic) 24 | 25 | set_target_properties(cairo_kinetic PROPERTIES OUTPUT_NAME "cairo/module/kinetic/module") 26 | install(TARGETS cairo_kinetic RENAME module DESTINATION share/wava/cairo/module/kinetic/) 27 | else() 28 | message(WARNING "CAIRO library not found; \"cairo_kinetic\" won't build") 29 | endif() 30 | endif() 31 | -------------------------------------------------------------------------------- /src/output/shared/graphical.h: -------------------------------------------------------------------------------- 1 | #ifndef H_GRAPHICAL 2 | #define H_GRAPHICAL 3 | 4 | #include "shared.h" 5 | 6 | // updates geometry as well as position data 7 | void calculate_win_pos(WAVA *wava, uint32_t scrW, uint32_t scrH, 8 | uint32_t winW, uint32_t winH); 9 | 10 | // just geometry data 11 | void calculate_win_geo(WAVA *wava, uint32_t winW, uint32_t winH); 12 | 13 | #define DEF_FG_COL 6 14 | #define DEF_BG_COL 0 15 | #define COLOR_NUM 8 16 | static const unsigned int colorNumbers[] = {0x000000, 0xFF0000, 0x00FF00, 0xFFFF00, 17 | 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF}; 18 | 19 | #define ARGB_A_32(x) ((x>>24)&0xff) 20 | #define ARGB_R_32(x) ((x>>16)&0xff) 21 | #define ARGB_G_32(x) ((x>>8)&0xff) 22 | #define ARGB_B_32(x) (x&0xff) 23 | 24 | #define A_ARGB_32(x) ((x&0xff)<<24) 25 | #define R_ARGB_32(x) ((x&0xff)<<16) 26 | #define G_ARGB_32(x) ((x&0xff)<<8) 27 | #define B_ARGB_32(x) (x&0xff) 28 | 29 | #define ARGB_A_64(x) ((x>>48)&0xffff) 30 | #define ARGB_R_64(x) ((x>>32)&0xffff) 31 | #define ARGB_G_64(x) ((x>>16)&0xffff) 32 | #define ARGB_B_64(x) (x&0xffff) 33 | 34 | #define A_ARGB_64(x) ((x&0xffff)<<49) 35 | #define R_ARGB_64(x) ((x&0xffff)<<32) 36 | #define G_ARGB_64(x) ((x&0xffff)<<16) 37 | #define B_ARGB_64(x) (x&0xffff) 38 | 39 | #define TRANS_FROM_MIN(x, y, z) ((typeof(x))(DIFF(x,y)*z)+MIN(x,y)) 40 | #define TRANS_FROM_MAX(x, y, z) (MAX(x,y)-(typeof(x))(DIFF(x,y)*z)) 41 | 42 | #define UNSIGNED_TRANS(x, y, z) (x>y? TRANS_FROM_MAX(x,y,z) : TRANS_FROM_MIN(x,y,z)) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/input/cubeb/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(CUBEB "CUBEB" OFF) 3 | 4 | # libcubeb-0.3 5 | if(CUBEB) 6 | set(BUILD_SHARED_LIBS ON) 7 | set(BUILD_TESTS OFF) 8 | set(BUILD_RUST_LIBS ON) 9 | set(BUILD_TOOLS OFF) 10 | set(BUNDLE_SPEEX OFF) 11 | set(LAZY_LOAD_LIBS OFF) 12 | set(USE_SANITIZERS OFF) 13 | set(USE_PULSE ON) 14 | set(USE_PULSE_RUST ON) 15 | 16 | execute_process(COMMAND git submodule update --init --recursive 17 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib/cubeb 18 | COMMAND_ERROR_IS_FATAL ANY) 19 | 20 | add_subdirectory(lib/cubeb) 21 | set_target_properties(cubeb PROPERTIES POSITION_INDEPENDENT_CODE ON) 22 | 23 | file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/lib/cubeb/cmake_install.cmake") 24 | 25 | add_definitions(-DCUBEB) 26 | add_library(in_cubeb SHARED "${WAVA_MODULE_DIR}/main.c" 27 | "${GLOBAL_FUNCTION_SOURCES}") 28 | target_link_libraries(in_cubeb wava-shared "cubeb") 29 | target_include_directories(in_cubeb PRIVATE 30 | "${CMAKE_CURRENT_BINARY_DIR}/exports" lib/cubeb/include) 31 | set_target_properties(in_cubeb PROPERTIES PREFIX "" 32 | POSITION_INDEPENDENT_CODE ON) 33 | install(TARGETS in_cubeb DESTINATION lib/wava) 34 | 35 | # Add legal disclaimer 36 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_cubeb.txt" 37 | "cubeb license can be obtained at: \ 38 | https://raw.githubusercontent.com/mozilla/cubeb/master/LICENSE\n") 39 | endif() 40 | 41 | -------------------------------------------------------------------------------- /src/shared/module/module.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_SHARED_MODULE_H 2 | #define __WAVA_SHARED_MODULE_H 3 | #include 4 | 5 | // don't leak internal structure as the user of this library 6 | // isn't supposed to mess with it 7 | typedef struct wavamodule WAVAMODULE; 8 | 9 | extern char *wava_module_error_get(WAVAMODULE *module); 10 | extern bool wava_module_valid(WAVAMODULE *module); 11 | extern void *wava_module_symbol_address_get(WAVAMODULE *module, char *symbol); 12 | extern WAVAMODULE *wava_module_input_load(char *name); 13 | extern WAVAMODULE *wava_module_output_load(char *name); 14 | extern WAVAMODULE *wava_module_filter_load(char *name); 15 | extern WAVAMODULE *wava_module_path_load(char *path); 16 | extern void wava_module_free(WAVAMODULE *module); 17 | 18 | /** 19 | * name is the user-specified module name 20 | * prefix is the application-specified module name prefix 21 | * root_prefix is the directory from where the module is 22 | * supposed to be loaded (and it must include the last 23 | * bracket) 24 | **/ 25 | extern WAVAMODULE *wava_module_custom_load(char *name, 26 | const char *prefix, const char *root_prefix); 27 | 28 | // get the path of a loaded module 29 | extern const char *wava_module_path_get(WAVAMODULE *module); 30 | 31 | // get the file extension of a module on the current system 32 | extern const char *wava_module_extension_get(void); 33 | 34 | // return module generated filename into result 35 | extern void wava_module_generate_filename(char *name, 36 | const char *prefix, char *result); 37 | 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/bars/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(CAIRO_MODULES "CAIRO_MODULES" ON) 3 | 4 | if(CAIRO_MODULES) 5 | pkg_check_modules(CAIRO QUIET cairo) 6 | if(CAIRO_FOUND) 7 | add_library(cairo_bars SHARED "${WAVA_MODULE_DIR}/main.c" 8 | "${WAVA_MODULE_DIR}/../shared/config.c" 9 | "${GLOBAL_FUNCTION_SOURCES}") 10 | 11 | target_link_directories(cairo_bars PRIVATE 12 | "${CAIRO_LIBRARY_DIRS}") 13 | target_include_directories(cairo_bars PRIVATE 14 | "${CAIRO_INCLUDE_DIRS}") 15 | target_link_libraries(cairo_bars wava-shared "${CAIRO_LIBRARIES}") 16 | 17 | target_compile_definitions(cairo_bars PUBLIC -DCAIRO) 18 | set_target_properties(cairo_bars PROPERTIES PREFIX "") 19 | set_target_properties(cairo_bars PROPERTIES IMPORT_PREFIX "") 20 | configure_file("${WAVA_MODULE_DIR}/config.ini" cairo/module/bars/config.ini COPYONLY) 21 | 22 | # this copies the dlls for mr. windows 23 | #find_and_copy_dlls(cairo_bars) 24 | 25 | set_target_properties(cairo_bars PROPERTIES OUTPUT_NAME "cairo/module/bars/module") 26 | install(FILES "${CMAKE_BINARY_DIR}/cairo/module/bars/config.ini" RENAME config.ini.example DESTINATION share/wava/cairo/module/bars/) 27 | install(TARGETS cairo_bars RENAME module DESTINATION share/wava/cairo/module/bars/) 28 | else() 29 | message(WARNING "CAIRO library not found; \"cairo_bars\" won't build") 30 | endif() 31 | endif() 32 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/stars/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(CAIRO_MODULES "CAIRO_MODULES" ON) 3 | 4 | if(CAIRO_MODULES) 5 | pkg_check_modules(CAIRO QUIET cairo) 6 | if(CAIRO_FOUND) 7 | add_library(cairo_stars SHARED "${WAVA_MODULE_DIR}/main.c" 8 | "${WAVA_MODULE_DIR}/../shared/config.c" 9 | "${GLOBAL_FUNCTION_SOURCES}") 10 | target_link_directories(cairo_stars PRIVATE 11 | "${CAIRO_LIBRARY_DIRS}") 12 | target_include_directories(cairo_stars PRIVATE 13 | "${CAIRO_INCLUDE_DIRS}") 14 | target_link_libraries(cairo_stars wava-shared "${CAIRO_LIBRARIES}") 15 | 16 | target_compile_definitions(cairo_stars PUBLIC -DCAIRO) 17 | set_target_properties(cairo_stars PROPERTIES PREFIX "") 18 | set_target_properties(cairo_stars PROPERTIES IMPORT_PREFIX "") 19 | configure_file("${WAVA_MODULE_DIR}/config.ini" cairo/module/stars/config.ini COPYONLY) 20 | 21 | # this copies the dlls for mr. windows 22 | #find_and_copy_dlls(cairo_stars) 23 | 24 | set_target_properties(cairo_stars PROPERTIES OUTPUT_NAME "cairo/module/stars/module") 25 | install(FILES "${CMAKE_BINARY_DIR}/cairo/module/stars/config.ini" RENAME config.ini.example DESTINATION share/wava/cairo/module/stars/) 26 | install(TARGETS cairo_stars RENAME module DESTINATION share/wava/cairo/module/stars/) 27 | else() 28 | message(WARNING "CAIRO library not found; \"cairo_stars\" won't build") 29 | endif() 30 | endif() 31 | -------------------------------------------------------------------------------- /example_files/gl/shaders/shadow/fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 420 core 2 | 3 | in vec2 texCoord; 4 | 5 | uniform sampler2D color_texture; 6 | uniform sampler2D depth_texture; 7 | 8 | uniform vec2 resolution; 9 | 10 | vec4 shadow_color = vec4(0.0, 0.0, 0.0, 1.0); 11 | vec2 shadow_offset, shadow_direction; 12 | 13 | uniform vec4 background_color; 14 | 15 | layout(location=0) out vec4 FragColor; 16 | 17 | // Credit: https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/5.glsl 18 | vec4 blur5(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) { 19 | vec4 color = vec4(0.0); 20 | vec2 off1 = vec2(1.3333333333333333) * direction; 21 | color += texture(image, uv) * 0.29411764705882354; 22 | color += texture(image, uv + (off1 / resolution)) * 0.35294117647058826; 23 | color += texture(image, uv - (off1 / resolution)) * 0.35294117647058826; 24 | return color; 25 | } 26 | 27 | vec4 correctForAlphaBlend(vec4 color) { 28 | return vec4(color.rgb*color.a, color.a); 29 | } 30 | 31 | vec4 append_color_properly(vec4 source, vec4 target) { 32 | target.rgb += source.rgb*source.a; 33 | target.a = max(source.a, target.a); 34 | return target; 35 | } 36 | 37 | void main() { 38 | // transfer background 39 | FragColor = texture(color_texture, texCoord); 40 | 41 | shadow_direction = vec2(-5.0, 5.0); 42 | shadow_offset = vec2(-5.0, 5.0)/resolution; 43 | 44 | // test if infinite 45 | vec4 depth = texture(depth_texture, texCoord); 46 | if(depth.r == 1.0) { 47 | float color = 1.0 - blur5(depth_texture, shadow_offset+texCoord, 48 | shadow_direction, shadow_offset).r; 49 | FragColor = mix(FragColor, shadow_color, color); 50 | } 51 | 52 | FragColor = correctForAlphaBlend(FragColor); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/oscilloscope/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(CAIRO_MODULES "CAIRO_MODULES" ON) 3 | 4 | if(CAIRO_MODULES) 5 | pkg_check_modules(CAIRO QUIET cairo) 6 | if(CAIRO_FOUND) 7 | add_library(cairo_oscilloscope SHARED "${WAVA_MODULE_DIR}/main.c" 8 | "${WAVA_MODULE_DIR}/../shared/config.c" 9 | "${GLOBAL_FUNCTION_SOURCES}") 10 | 11 | target_link_directories(cairo_oscilloscope PRIVATE 12 | "${CAIRO_LIBRARY_DIRS}") 13 | target_include_directories(cairo_oscilloscope PRIVATE 14 | "${CAIRO_INCLUDE_DIRS}") 15 | target_link_libraries(cairo_oscilloscope wava-shared "${CAIRO_LIBRARIES}") 16 | 17 | target_compile_definitions(cairo_oscilloscope PUBLIC -DCAIRO) 18 | set_target_properties(cairo_oscilloscope PROPERTIES PREFIX "") 19 | set_target_properties(cairo_oscilloscope PROPERTIES IMPORT_PREFIX "") 20 | configure_file("${WAVA_MODULE_DIR}/config.ini" cairo/module/oscilloscope/config.ini COPYONLY) 21 | 22 | # this copies the dlls for mr. windows 23 | #find_and_copy_dlls(cairo_oscilloscope) 24 | 25 | set_target_properties(cairo_oscilloscope PROPERTIES OUTPUT_NAME "cairo/module/oscilloscope/module") 26 | install(FILES "${CMAKE_BINARY_DIR}/cairo/module/oscilloscope/config.ini" RENAME config.ini.example DESTINATION share/wava/cairo/module/oscilloscope/) 27 | install(TARGETS cairo_oscilloscope RENAME module DESTINATION share/wava/cairo/module/oscilloscope/) 28 | else() 29 | message(WARNING "CAIRO library not found; \"cairo_oscilloscope\" won't build") 30 | endif() 31 | endif() 32 | -------------------------------------------------------------------------------- /src/cmake/install_and_configure.cmake: -------------------------------------------------------------------------------- 1 | # Generate README file 2 | if(MSYS OR MSVC OR MINGW) 3 | configure_file("assets/windows/readme.txt" "README.txt" NEWLINE_STYLE CRLF) 4 | endif() 5 | 6 | # Generate proper license file 7 | file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/final-LICENSE.txt") 8 | file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") 9 | file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/LICENSE" "${CMAKE_CURRENT_BINARY_DIR}/final-LICENSE.txt") 10 | 11 | file(GLOB LICENSE_FILES "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_*.txt") 12 | foreach(LICENSE_FILE ${LICENSE_FILES}) 13 | cat(${LICENSE_FILE} "${CMAKE_CURRENT_BINARY_DIR}/final-LICENSE.txt") 14 | endforeach() 15 | 16 | # Install 17 | install (TARGETS wava DESTINATION bin) 18 | install (FILES "${CMAKE_CURRENT_BINARY_DIR}/final-LICENSE.txt" DESTINATION share/licenses/wava) 19 | install (FILES example_files/config RENAME config.example DESTINATION share/wava) 20 | 21 | # Install DLLs 22 | find_and_copy_dlls(wava) 23 | 24 | include("src/cmake/copy_gl_shaders.cmake") 25 | 26 | if(UNIX AND NOT APPLE) 27 | find_program(CONVERT magick 28 | REQUIRED) 29 | find_program(LIBRSVG rsvg-convert 30 | REQUIRED) 31 | execute_process (COMMAND 32 | convert -size 128x128 -density 1200 -background none -format png32 33 | "${CMAKE_CURRENT_SOURCE_DIR}/assets/linux/wava.svg" 34 | "${CMAKE_CURRENT_BINARY_DIR}/wava.png" 35 | COMMAND_ERROR_IS_FATAL ANY) 36 | install (FILES assets/linux/wava.desktop DESTINATION share/applications) 37 | install (FILES assets/linux/wava.svg RENAME wava_visualizer.svg DESTINATION share/icons/hicolor/scalable/apps) 38 | install (FILES "${CMAKE_CURRENT_BINARY_DIR}/wava.png" RENAME wava_visualizer.png DESTINATION share/icons/hicolor/128x128/apps) 39 | endif() 40 | -------------------------------------------------------------------------------- /src/cmake/modules.cmake: -------------------------------------------------------------------------------- 1 | # Build GL modules 2 | file(GLOB gl_modules "src/output/shared/gl/modules/*/build.cmake") 3 | foreach(dir ${gl_modules}) 4 | get_filename_component(WAVA_MODULE_DIR ${dir} DIRECTORY) 5 | include(${dir}) 6 | endforeach() 7 | 8 | # Build Cairo modules 9 | file(GLOB cairo_modules "src/output/shared/cairo/modules/*/build.cmake") 10 | foreach(dir ${cairo_modules}) 11 | get_filename_component(WAVA_MODULE_DIR ${dir} DIRECTORY) 12 | include(${dir}) 13 | endforeach() 14 | 15 | # Build filter modules 16 | file(GLOB filters "src/filters/*/build.cmake" ) 17 | foreach(dir ${filters}) 18 | get_filename_component(WAVA_MODULE_DIR ${dir} DIRECTORY) 19 | include(${dir}) 20 | endforeach() 21 | 22 | # Build output modules 23 | file(GLOB outputs "src/output/*/build.cmake" ) 24 | foreach(dir ${outputs}) 25 | # Exclude the default module 26 | if("${dir}" STREQUAL "${CMAKE_SOURCE_DIR}/src/output/default/build.cmake") 27 | continue() 28 | endif() 29 | 30 | get_filename_component(WAVA_MODULE_DIR ${dir} DIRECTORY) 31 | include(${dir}) 32 | endforeach() 33 | # This is so that the default module gets build AFTER everything else 34 | get_filename_component(WAVA_MODULE_DIR "src/output/default/build.cmake" DIRECTORY) 35 | include("src/output/default/build.cmake") 36 | 37 | # Build unsupported output modules 38 | if(BUILD_LEGACY_OUTPUTS) 39 | file(GLOB legacy_outputs "src/output/unsupported/*/build.cmake" ) 40 | foreach(dir ${legacy_outputs}) 41 | get_filename_component(WAVA_MODULE_DIR ${dir} DIRECTORY) 42 | include(${dir}) 43 | endforeach() 44 | endif() 45 | 46 | # Build input modules 47 | file(GLOB inputs "src/input/*/build.cmake" ) 48 | foreach(dir ${inputs}) 49 | get_filename_component(WAVA_MODULE_DIR ${dir} DIRECTORY) 50 | include(${dir}) 51 | endforeach() 52 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/media_info/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(CAIRO_MODULES "CAIRO_MODULES" ON) 3 | 4 | if(CAIRO_MODULES) 5 | pkg_check_modules(CAIRO QUIET cairo libcurl taglib zlib dbus-1) 6 | if(CAIRO_FOUND) 7 | add_subdirectory(lib/kiss-mpris-properties) 8 | 9 | add_library(cairo_media_info SHARED "${WAVA_MODULE_DIR}/main.c" 10 | "src/output/shared/util/media/artwork.c" 11 | "src/output/shared/util/media/artwork_taglib.cpp" 12 | "src/output/shared/util/media/media_data.c" 13 | "${GLOBAL_FUNCTION_SOURCES}") 14 | #"${WAVA_MODULE_DIR}/../../" 15 | 16 | target_link_directories(cairo_media_info PRIVATE 17 | "${CAIRO_LIBRARY_DIRS}") 18 | target_include_directories(cairo_media_info PRIVATE 19 | "${CAIRO_INCLUDE_DIRS}" lib/kiss-mpris-properties/src 20 | lib/stb) 21 | target_link_libraries(cairo_media_info wava-shared kiss-mpris 22 | "${CAIRO_LIBRARIES}") 23 | 24 | target_compile_definitions(cairo_media_info PUBLIC -DCAIRO) 25 | set_target_properties(cairo_media_info PROPERTIES PREFIX "") 26 | set_target_properties(cairo_media_info PROPERTIES IMPORT_PREFIX "") 27 | configure_file("${WAVA_MODULE_DIR}/config.ini" cairo/module/media_info/config.ini COPYONLY) 28 | 29 | # this copies the dlls for mr. windows 30 | #find_and_copy_dlls(cairo_media_info) 31 | 32 | set_target_properties(cairo_media_info PROPERTIES OUTPUT_NAME "cairo/module/media_info/module") 33 | install(TARGETS cairo_media_info RENAME module DESTINATION share/wava/cairo/module/media_info/) 34 | else() 35 | message(WARNING "CAIRO, TagLib, Zlib, DBus-1 and/or CURL library not found; \"cairo_media_info\" won't build") 36 | endif() 37 | endif() 38 | -------------------------------------------------------------------------------- /src/output/shared/util/media/artwork_taglib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /** 13 | * Shamelessly stolen from: 14 | * https://rajeevandlinux.wordpress.com/2012/04/24/extract-album-art-from-mp3-files-using-taglib-in-c/ 15 | **/ 16 | 17 | // extern everything because it's a C program after all 18 | extern "C" { 19 | static const char *taglib_id_picture = "APIC"; 20 | 21 | #include "shared.h" 22 | 23 | #include "artwork.h" 24 | 25 | bool wava_util_artwork_update_by_audio_file(const char *url, 26 | struct artwork *artwork) { 27 | TagLib::MPEG::File mpeg_file(&url[strlen(URI_HEADER_MUSIC)]); 28 | TagLib::ID3v2::Tag *id3v2tag = mpeg_file.ID3v2Tag(); 29 | TagLib::ID3v2::FrameList frame; 30 | TagLib::ID3v2::AttachedPictureFrame *pic_frame; 31 | 32 | wavaReturnWarnCondition(id3v2tag == nullptr, true, 33 | "id3v2 not present in '%s'", url); 34 | 35 | // picture frame 36 | frame = id3v2tag->frameListMap()[taglib_id_picture]; 37 | wavaReturnLogCondition(frame.isEmpty() == true, true, 38 | "'%s' has no artwork information", url); 39 | 40 | for(auto it = frame.begin(); it != frame.end(); ++it) { 41 | pic_frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it); 42 | 43 | //if(pic_frame->type() == 44 | // TagLib::ID3v2::AttachedPictureFrame::FrontCover) {} 45 | 46 | // extract image (in it’s compressed form) 47 | artwork->size = pic_frame->picture().size(); 48 | artwork->file_data = static_cast 49 | (malloc(artwork->size)); 50 | 51 | memcpy(artwork->file_data, pic_frame->picture().data(), 52 | artwork->size); 53 | } 54 | return false; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/shared/module/abstractions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "shared.h" 6 | #include "shared/module/internal.h" 7 | 8 | #if defined(__WIN32__) 9 | #define DIR_BREAK '\\' 10 | #else 11 | #define DIR_BREAK '/' 12 | #endif 13 | 14 | EXP_FUNC WAVAMODULE *wava_module_output_load(char *name) { 15 | char *new_name = calloc(strlen(name)+strlen("out_") + 1, sizeof(char)); 16 | sprintf(new_name, "out_%s", name); 17 | WAVAMODULE *module = wava_module_load(new_name); 18 | free(new_name); 19 | return module; 20 | } 21 | 22 | EXP_FUNC WAVAMODULE *wava_module_input_load(char *name) { 23 | char *new_name = calloc(strlen(name)+strlen("in_") + 1, sizeof(char)); 24 | sprintf(new_name, "in_%s", name); 25 | WAVAMODULE *module = wava_module_load(new_name); 26 | free(new_name); 27 | return module; 28 | } 29 | 30 | EXP_FUNC WAVAMODULE *wava_module_filter_load(char *name) { 31 | char *new_name = calloc(strlen(name)+strlen("filter_") + 1, sizeof(char)); 32 | sprintf(new_name, "filter_%s", name); 33 | WAVAMODULE *module = wava_module_load(new_name); 34 | free(new_name); 35 | return module; 36 | } 37 | 38 | EXP_FUNC WAVAMODULE *wava_module_custom_load(char *name, const char *prefix, 39 | const char *root_prefix) { 40 | char string_size = strlen(root_prefix) + 1 + strlen(prefix) + 1 + 41 | strlen(name) + 1; 42 | char path[string_size]; 43 | 44 | // a kinda security feature 45 | for(size_t i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "shared.h" 9 | 10 | EXP_FUNC void* wavaInput(void* data) 11 | { 12 | WAVA_AUDIO *audio = (WAVA_AUDIO *)data; 13 | struct sio_par par; 14 | struct sio_hdl *hdl; 15 | int16_t buf[256]; 16 | unsigned int i, n, channels; 17 | 18 | assert(audio->channels > 0); 19 | channels = audio->channels; 20 | 21 | sio_initpar(&par); 22 | par.sig = 1; 23 | par.bits = 16; 24 | par.le = 1; 25 | par.rate = 44100; 26 | par.rchan = channels; 27 | par.appbufsz = sizeof(buf) / channels; 28 | 29 | wavaBailCondition((hdl = sio_open(audio->source, SIO_REC, 0)) == NULL, 30 | "Could not open sndio source: %s", audio->source); 31 | 32 | wavaBailCondition(!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par) || par.sig != 1 33 | || par.le != 1 || par.rate != 44100 || par.rchan != channels, 34 | "Could not set required audio parameters"); 35 | 36 | wavaBailCondition(!sio_start(hdl), "sio_start() failed"); 37 | 38 | n = 0; 39 | while (audio->terminate != 1) { 40 | wavaBailCondition(sio_read(hdl, buf, sizeof(buf)) == 0, 41 | "sio_read() failed: %s\n", strerror(errno)); 42 | 43 | for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i += 2) { 44 | if (par.rchan == 1) { 45 | // sndiod has already taken care of averaging the samples 46 | audio->audio_out_l[n] = buf[i]; 47 | } else if (par.rchan == 2) { 48 | audio->audio_out_l[n] = buf[i]; 49 | audio->audio_out_r[n] = buf[i + 1]; 50 | } 51 | n = (n + 1) % audio->inputsize; 52 | } 53 | } 54 | 55 | sio_stop(hdl); 56 | sio_close(hdl); 57 | 58 | return 0; 59 | } 60 | 61 | EXP_FUNC void wavaInputLoadConfig(WAVA *wava) { 62 | WAVA_AUDIO *audio = &wava->audio; 63 | wava_config_source config = wava->default_config.config; 64 | audio->rate = 44100; 65 | audio->source = (char*)wavaConfigGetString(config, "input", "source", SIO_DEVANY); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/shared/build.cmake: -------------------------------------------------------------------------------- 1 | project(wava-shared C) 2 | 3 | # Optional features 4 | set(ADDITIONAL_SHARED_SOURCES "") 5 | set(ADDITIONAL_SHARED_LIBRARIES "") 6 | set(ADDITIONAL_SHARED_DEFINITIONS "") 7 | set(ADDITIONAL_SHARED_INCLUDE_DIRS "") 8 | 9 | # Pull git required submodules 10 | execute_process(COMMAND git submodule update --init) 11 | 12 | # Pull submodule and install dependency 13 | add_library(iniparser STATIC 14 | lib/iniparser/src/dictionary.c 15 | lib/iniparser/src/iniparser.c) 16 | set_target_properties(iniparser PROPERTIES COMPILE_FLAGS "-fPIC") 17 | 18 | # Runtime library load 19 | if(UNIX) 20 | list(APPEND ADDITIONAL_SHARED_LIBRARIES "dl") 21 | list(APPEND ADDITIONAL_SHARED_SOURCES "src/shared/module/unix.c") 22 | list(APPEND ADDITIONAL_SHARED_SOURCES "src/shared/io/unix.c") 23 | elseif(MSYS OR MINGW OR MSVC) 24 | list(APPEND ADDITIONAL_SHARED_SOURCES "src/shared/module/windows.c") 25 | else() 26 | message(FATAL_ERROR "Your OS/Platform does NOT support modules!") 27 | endif() 28 | 29 | # Build WAVA shared library 30 | add_library(wava-shared SHARED 31 | src/shared/log.c 32 | src/shared/config/config.c 33 | src/shared/module/abstractions.c 34 | src/shared/ionotify.c 35 | src/shared/io/io.c 36 | src/shared/util/version.c 37 | ${ADDITIONAL_SHARED_SOURCES} 38 | ) 39 | set_target_properties(wava-shared PROPERTIES COMPILE_FLAGS "-fPIC") 40 | target_link_libraries(wava-shared PRIVATE ${ADDITIONAL_SHARED_LIBRARIES} iniparser pthread) 41 | target_compile_definitions(wava-shared PRIVATE ${ADDITIONAL_SHARED_DEFINITIONS}) 42 | target_include_directories(wava-shared PRIVATE "${ADDITIONAL_SHARED_INCLUDE_DIRS}" lib/iniparser/src lib/x-watcher) 43 | 44 | install (TARGETS wava-shared DESTINATION lib) 45 | 46 | find_and_copy_dlls(wava-shared) 47 | 48 | # Add legal disclaimers 49 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_iniparser.txt" 50 | "INIparser license can be obtained at: https://raw.githubusercontent.com/ndevilla/iniparser/master/LICENSE\n") 51 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_xwatcher.txt" 52 | "xWatcher license can be obtained at: https://raw.githubusercontent.com/nikp123/x-watcher/master/README.md\n") 53 | 54 | -------------------------------------------------------------------------------- /src/shared/util/array.h: -------------------------------------------------------------------------------- 1 | #ifndef ARRAY_H 2 | #define ARRAY_H 3 | 4 | #include 5 | #include 6 | 7 | struct _ArrayHeader { 8 | size_t count, capacity; 9 | }; 10 | 11 | #define ARRAY_INITIAL_SIZE 8 12 | 13 | #define _arr_header(a) ((struct _ArrayHeader*)(a) - 1) 14 | 15 | #define arr_init(a) arr_init_n((a), ARRAY_INITIAL_SIZE) 16 | 17 | #define arr_init_n(a, n) do { \ 18 | struct _ArrayHeader *header; \ 19 | header = malloc(sizeof(*header) + (sizeof(*(a)) * (n))); \ 20 | header->count = 0; \ 21 | header->capacity = (n); \ 22 | (a) = (void*)(header + 1); \ 23 | } while(0) 24 | 25 | #define arr_count(a) (_arr_header(a)->count) 26 | #define arr_capacity(a) (_arr_header(a)->capacity) 27 | 28 | #define arr_back(a) ((a)[arr_count(a) - 1]) 29 | #define arr_pop(a) ((a)[_arr_header(a)->count--]) 30 | 31 | #define arr_reserve(a, n) do { \ 32 | if(n <= arr_capacity(a)) break; \ 33 | struct _ArrayHeader *header = _arr_header(a); \ 34 | header->capacity = n; \ 35 | (a) = (void*)((struct _ArrayHeader*)realloc( \ 36 | header, sizeof(*header) + (sizeof(*(a)) * (n))) + 1); \ 37 | } while(0) 38 | 39 | #define arr_resize(a, n) do { \ 40 | arr_reserve((a), (n)); \ 41 | _arr_header(a)->count = n; \ 42 | } while(0) 43 | 44 | #define arr_resize_zero(a, n) do { \ 45 | size_t initial_count = arr_count(a); \ 46 | arr_resize((a), (n)); \ 47 | if(arr_count(a) > initial_count) \ 48 | memset( \ 49 | &(a)[initial_count], 0, \ 50 | (arr_count(a) - initial_count) * sizeof(*a)); \ 51 | } while(0) 52 | 53 | // Take a vararg list to support compound literals 54 | #define arr_add(a, ...) do { \ 55 | struct _ArrayHeader *header = _arr_header(a); \ 56 | if(header->count == header->capacity) \ 57 | arr_reserve((a), header->capacity << 1); \ 58 | (a)[_arr_header(a)->count++] = (__VA_ARGS__); \ 59 | } while(0) 60 | 61 | #define arr_free(a) do { \ 62 | free(_arr_header(a)); \ 63 | } while(0) 64 | 65 | #define arr_find(a, val, idx) do { \ 66 | *idx = -1; \ 67 | for(size_t i = 0; i < arr_count((a)); i++) { \ 68 | if((a)[i] == val) { \ 69 | *idx = i; \ 70 | break; \ 71 | } \ 72 | } \ 73 | } while(0) 74 | 75 | #endif 76 | 77 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'master' 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | include: 17 | - system: archlinux 18 | arch: x86_64 19 | icon: '🟦' 20 | - system: windows 21 | arch: i686 22 | icon: '⬛' 23 | - system: windows 24 | arch: x86_64 25 | icon: '🟦' 26 | 27 | name: 🚧${{ matrix.icon }} ${{ matrix.system }} (${{ matrix.arch }}) 28 | steps: 29 | - uses: actions/checkout@v3 30 | with: 31 | submodules: true 32 | 33 | - uses: ./.github/actions/prepare 34 | with: 35 | system: ${{ matrix.system }} 36 | arch: ${{ matrix.arch }} 37 | 38 | - uses: ./.github/actions/compile 39 | with: 40 | system: ${{ matrix.system }} 41 | arch: ${{ matrix.arch }} 42 | 43 | - uses: ./.github/actions/upload 44 | if: ${{ !env.ACT }} 45 | with: 46 | system: ${{ matrix.system }} 47 | arch: ${{ matrix.arch }} 48 | 49 | create-release: 50 | needs: build 51 | runs-on: ubuntu-latest 52 | 53 | steps: 54 | - uses: actions/checkout@v3 55 | - run: rm -rf * 56 | - uses: actions/download-artifact@v3 57 | 58 | - name: Reorganize release files 59 | run: | 60 | ls -R 61 | for i in xava-*; do 62 | mv $i temp 63 | mv temp/$i $i 64 | rmdir temp 65 | done 66 | ls -R 67 | 68 | - name: Read version file 69 | run: | 70 | cat version.txt/version.txt 71 | VER=$(cat version.txt/version.txt) 72 | echo "VERSION=$VER" >> $GITHUB_ENV 73 | 74 | - uses: "marvinpinto/action-automatic-releases@latest" 75 | with: 76 | repo_token: "${{ secrets.GH_ACCESS_TOKEN }}" 77 | automatic_release_tag: ${{ env.VERSION }} 78 | prerelease: true 79 | title: "Development Build" 80 | files: | 81 | xava-installer-i686.exe 82 | xava-installer-x86_64.exe 83 | xava-x86_64.AppImage 84 | 85 | -------------------------------------------------------------------------------- /src/output/graphical_sdl2/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(SDL2 "SDL2" ON) 3 | 4 | # SDL2 5 | if(SDL2) 6 | pkg_check_modules(SDL2 QUIET sdl2) 7 | pkg_check_modules(GLEW QUIET glew) 8 | if(SDL2_FOUND AND GLEW_FOUND) 9 | # Deal with fucking windows 10 | if(MSVC OR MINGW OR MSYS) 11 | set(CMAKE_EXE_LINKER_FLAGS "-static") 12 | set(SDL2_LIBRARIES "${SDL2_LIBRARIES} -lopengl32 -lmingw32 \ 13 | -lSDL2main -lSDL2 -mwindows -lm -ldinput8 -ldxguid -ldxerr8 \ 14 | -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 \ 15 | -lversion -luuid -static-libgcc -lsetupapi -lSetupAPI") 16 | endif() 17 | 18 | # add winapi test 19 | list(APPEND DEFAULT_OUTPUT_SOURCES "${WAVA_MODULE_DIR}/test.c") 20 | list(APPEND DEFAULT_OUTPUT_LINKDIR "${SDL2_LIBRARY_DIRS}") 21 | list(APPEND DEFAULT_OUTPUT_LINKLIB "${SDL2_LIBRARIES}") 22 | list(APPEND DEFAULT_OUTPUT_INCDIR "${SDL2_INCLUDE_DIRS}") 23 | list(APPEND DEFAULT_OUTPUT_DEF "-DSDL2") 24 | 25 | add_library(out_sdl2_opengl SHARED 26 | "${WAVA_MODULE_DIR}/main.c" 27 | "src/output/shared/graphical.c" 28 | "src/output/shared/gl/main.c" 29 | "src/output/shared/gl/glew.c" 30 | "${GLOBAL_FUNCTION_SOURCES}") 31 | target_link_libraries(out_sdl2_opengl wava-shared 32 | ${SDL2_LIBRARIES} ${GLEW_LIBRARIES}) 33 | target_include_directories(out_sdl2_opengl PRIVATE 34 | ${SDL2_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS}) 35 | target_link_directories(out_sdl2_opengl PRIVATE 36 | ${SDL2_LIBRARY_DIRS} ${GLEW_LIBRARY_DIRS}) 37 | set_target_properties(out_sdl2_opengl PROPERTIES PREFIX "") 38 | target_compile_definitions(out_sdl2_opengl PUBLIC -DSDL -DGL) 39 | install(TARGETS out_sdl2_opengl DESTINATION lib/wava) 40 | 41 | find_and_copy_dlls(out_sdl2_opengl) 42 | 43 | # Add legal disclaimer 44 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE_sdl2.txt" 45 | "SDL2 license can be obtained at: https://www.libsdl.org/license.php\n") 46 | else() 47 | message(WARNING "SDL2 or GLEW library not found") 48 | endif() 49 | endif() 50 | -------------------------------------------------------------------------------- /src/cmake/os-prerequisites.cmake: -------------------------------------------------------------------------------- 1 | # Windows-y things 2 | if(MINGW) 3 | set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES}) 4 | add_definitions(-DWAVA_DEFAULT_INPUT="wasapi") 5 | 6 | if(CMAKE_BUILD_TYPE STREQUAL "Release") 7 | message(STATUS "Since release build, console is being disabled") 8 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}") 9 | else() 10 | set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1) 11 | endif() 12 | 13 | # Do not convert the file paths to Windows-native ones as we're building in Linux 14 | file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/example_files" wava_EXAMPLE_FILES) 15 | string(REPLACE "/" "\\" wava_EXAMPLE_FILES_NSIS "${CMAKE_CURRENT_SOURCE_DIR}/example_files") 16 | #string(REPLACE "/" "\\" wava_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 17 | 18 | # Prepare NSI file for compilation 19 | configure_file("assets/windows/wava.nsi.template" "wava.nsi" NEWLINE_STYLE CRLF) 20 | 21 | set(wava_EXECUTABLE_WINDOWS_ICO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/windows/wava.ico") 22 | configure_file("assets/windows/wava.rc.template" "wava.rc" NEWLINE_STYLE CRLF) 23 | 24 | set(ADDITIONAL_OBJS ${CMAKE_CURRENT_BINARY_DIR}/wava.rc) 25 | 26 | # For Windows you use ';', but it's broken, so don't even bother 27 | # If you really care about building this on Windows, learn how to use 28 | # Docker and build the .github/actions/windows/build.sh file using 29 | # the windows-archlinux-mingw64-ownstuff image in the repo 30 | set(wava_dep_dirs_separator ":") 31 | 32 | # set global binary library search path 33 | string(JOIN "${wava_dep_dirs_separator}" wava_dep_dirs 34 | ./ ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES} ${CMAKE_FIND_ROOT_PATH}/bin 35 | /mingw64/bin /mingw32/bin /clang64/bin /clang32/bin /clangarm64/bin) 36 | 37 | add_definitions("-DWAVA_PREDEFINED_SENS_VALUE=0.005") 38 | else() 39 | # This hack is a of courtesy of: https://stackoverflow.com/a/40947954/3832385 40 | if(GNU) 41 | string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE) 42 | add_definitions("-DSOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}") 43 | set(BUILD_DEBUG_FLAGS "-rdynamic") 44 | set(CMAKE_SHARED_LINKER_FLAGS "-rdynamic") 45 | endif() 46 | endif() 47 | 48 | -------------------------------------------------------------------------------- /assets/windows/xava.rc.template: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Little macro tricks this turn number defines into non-quoted strings 4 | #define STRINGIZED_HELPER( a ) #a 5 | #define STRINGIZED( a ) STRINGIZED_HELPER( a ) 6 | 7 | #define DEMO_VER_STR STRINGIZED(@wava_VERSION_MAJOR@) "." STRINGIZED(@wava_VERSION_MINOR@) "." STRINGIZED(@wava_VERSION_PATCH@) "." STRINGIZED(@wava_VERSION_TWEAK@) "\0" 8 | #define FILEVER @wava_VERSION_MAJOR@,@wava_VERSION_MINOR@,@wava_VERSION_PATCH@,@wava_VERSION_TWEAK@ 9 | #define PRODUCTVER @wava_VERSION_MAJOR@,@wava_VERSION_MINOR@,@wava_VERSION_PATCH@,@wava_VERSION_TWEAK@ 10 | #define VS_PACKAGE_FILEVER @wava_VERSION_MAJOR@,@wava_VERSION_MINOR@,@wava_VERSION_PATCH@,@wava_VERSION_TWEAK@ 11 | #define VS_PACKAGE_PRODUCTVER @wava_VERSION_MAJOR@,@wava_VERSION_MINOR@,@wava_VERSION_PATCH@,@wava_VERSION_TWEAK@ 12 | #define STRFILEVER DEMO_VER_STR 13 | #define STRPRODUCTVER DEMO_VER_STR 14 | #define VS_PACKAGE_STRFILEVER DEMO_VER_STR 15 | #define VS_PACKAGE_STRPRODUCTVER DEMO_VER_STR 16 | #define STRCOMPANYNAME L"Nikola Pavlica\0" 17 | #define STRCOPYRIGHT L"(C) 2016-2021 Nikola Pavlica\0" 18 | #define STRFILEDESCRIPTION L"Audio Visualizer\0" 19 | #define STRPRODUCTNAME L"WAVA\0" 20 | #define VS_PACKAGE_STRPRODUCTNAME L"WAVA\0" 21 | #define ORIGINAL_FILENAME L"wava.exe\0" 22 | #define DEMO_BRANCH STRFILEVER 23 | 24 | id ICON "@wava_EXECUTABLE_WINDOWS_ICO_PATH@" 25 | 26 | VS_VERSION_INFO VERSIONINFO 27 | FILEVERSION FILEVER 28 | FILEFLAGSMASK 0x3fL 29 | FILEFLAGS 0x0L 30 | FILEOS 0x4L 31 | FILETYPE 0x1L 32 | FILESUBTYPE 0x0L 33 | BEGIN 34 | BLOCK "StringFileInfo" 35 | BEGIN 36 | BLOCK "040904B0" 37 | BEGIN 38 | VALUE "CompanyName", STRCOMPANYNAME 39 | VALUE "FileDescription", STRFILEDESCRIPTION 40 | VALUE "FileVersion", DEMO_VER_STR 41 | VALUE "LegalCopyright", STRCOPYRIGHT 42 | VALUE "LegalTrademarks", "\0" 43 | VALUE "OriginalFilename", ORIGINAL_FILENAME 44 | VALUE "ProductName", STRPRODUCTNAME 45 | VALUE "ProductVersion", DEMO_BRANCH 46 | END 47 | END 48 | BLOCK "VarFileInfo" 49 | BEGIN 50 | VALUE "Translation", 0x409, 1200 51 | END 52 | END 53 | 54 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/stars/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(GL_MODULES "GL_MODULES" ON) 3 | 4 | # Xorg 5 | if(GL_MODULES) 6 | # OpenGL/GLEW 7 | find_library(GLEW glew32) 8 | pkg_check_modules(GLEW QUIET glew) 9 | if(GLEW OR GLEW_FOUND) 10 | add_library(gl_stars SHARED "${WAVA_MODULE_DIR}/main.c" 11 | "${WAVA_MODULE_DIR}/../../util/shader.c" 12 | "${WAVA_MODULE_DIR}/../../util/misc.c" 13 | "${GLOBAL_FUNCTION_SOURCES}") 14 | target_link_directories(gl_stars PRIVATE 15 | "${GLEW_LIBRARY_DIRS}") 16 | target_include_directories(gl_stars PRIVATE 17 | "${GLEW_INCLUDE_DIRS}") 18 | 19 | if(WINDOWS OR MINGW OR MSVC OR CYGWIN) 20 | target_link_libraries(gl_stars wava-shared "-lglew32 -lopengl32") 21 | else() 22 | target_link_libraries(gl_stars wava-shared "${GLEW_LIBRARIES}") 23 | endif() 24 | target_compile_definitions(gl_stars PUBLIC -DGL) 25 | 26 | set_target_properties(gl_stars PROPERTIES PREFIX "") 27 | set_target_properties(gl_stars PROPERTIES IMPORT_PREFIX "") 28 | set_target_properties(gl_stars PROPERTIES OUTPUT_NAME "gl/module/stars/module") 29 | 30 | # this copies the dlls for mr. windows 31 | #find_and_copy_dlls(gl_stars) 32 | 33 | configure_file("${WAVA_MODULE_DIR}/vertex.glsl" gl/module/stars/vertex.glsl COPYONLY) 34 | configure_file("${WAVA_MODULE_DIR}/fragment.glsl" gl/module/stars/fragment.glsl COPYONLY) 35 | configure_file("${WAVA_MODULE_DIR}/config.ini" gl/module/stars/config.ini COPYONLY) 36 | 37 | install(TARGETS gl_stars RENAME module DESTINATION share/wava/gl/module/stars/) 38 | install(FILES "${CMAKE_BINARY_DIR}/gl/module/stars/vertex.glsl" RENAME vertex.glsl.example DESTINATION share/wava/gl/module/stars/) 39 | install(FILES "${CMAKE_BINARY_DIR}/gl/module/stars/fragment.glsl" RENAME fragment.glsl.example DESTINATION share/wava/gl/module/stars/) 40 | install(FILES "${CMAKE_BINARY_DIR}/gl/module/stars/config.ini" RENAME config.ini.example DESTINATION share/wava/gl/module/stars/) 41 | 42 | # Maybe GL license? 43 | else() 44 | message(WARNING "GLEW library not found; \"gl_stars\" won't build") 45 | endif() 46 | endif() 47 | -------------------------------------------------------------------------------- /src/cmake/copy_gl_shaders.cmake: -------------------------------------------------------------------------------- 1 | # Install vertex shaders 2 | file(GLOB filters "example_files/gl/shaders/*/vertex.glsl" ) 3 | foreach(files ${filters}) 4 | get_filename_component(path ${files} REALPATH DIRECTORY) 5 | string(REPLACE "${wava_SOURCE_DIR}/example_files/" "" target_path ${path}) 6 | string(REPLACE "vertex.glsl" "" target_path ${target_path}) 7 | configure_file("example_files/${target_path}/vertex.glsl" ${target_path}/vertex.glsl COPYONLY) 8 | install(FILES "example_files/${target_path}/vertex.glsl" RENAME vertex.glsl.example DESTINATION "share/wava/${target_path}") 9 | endforeach() 10 | 11 | # Install geometry shaders 12 | file(GLOB filters "example_files/gl/shaders/*/geometry.glsl" ) 13 | foreach(files ${filters}) 14 | get_filename_component(path ${files} REALPATH DIRECTORY) 15 | string(REPLACE "${wava_SOURCE_DIR}/example_files/" "" target_path ${path}) 16 | string(REPLACE "geometry.glsl" "" target_path ${target_path}) 17 | configure_file("example_files/${target_path}/geometry.glsl" ${target_path}/geometry.glsl COPYONLY) 18 | install(FILES "example_files/${target_path}/geometry.glsl" RENAME geometry.glsl.example DESTINATION "share/wava/${target_path}") 19 | endforeach() 20 | 21 | # Install fragment shaders 22 | file(GLOB filters "example_files/gl/shaders/*/fragment.glsl" ) 23 | foreach(files ${filters}) 24 | get_filename_component(path ${files} REALPATH DIRECTORY) 25 | string(REPLACE "${wava_SOURCE_DIR}/example_files/" "" target_path ${path}) 26 | string(REPLACE "fragment.glsl" "" target_path ${target_path}) 27 | configure_file("example_files/${target_path}/fragment.glsl" ${target_path}/fragment.glsl COPYONLY) 28 | install(FILES "example_files/${target_path}/fragment.glsl" RENAME fragment.glsl.example DESTINATION "share/wava/${target_path}") 29 | endforeach() 30 | 31 | # Install shader configs 32 | file(GLOB filters "example_files/gl/shaders/*/config.ini" ) 33 | foreach(files ${filters}) 34 | get_filename_component(path ${files} REALPATH DIRECTORY) 35 | string(REPLACE "${wava_SOURCE_DIR}/example_files/" "" target_path ${path}) 36 | string(REPLACE "config.ini" "" target_path ${target_path}) 37 | configure_file("example_files/${target_path}/config.ini" ${target_path}/config.ini COPYONLY) 38 | install(FILES "example_files/${target_path}/config.ini" RENAME config.ini.example DESTINATION "share/wava/${target_path}") 39 | endforeach() 40 | 41 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/shared/config.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "shared.h" 8 | 9 | #include "output/shared/cairo/main.h" 10 | 11 | #include "output/shared/cairo/util/feature_compat.h" 12 | #include "output/shared/cairo/util/module.h" 13 | #include "output/shared/cairo/util/region.h" 14 | 15 | #include "config.h" 16 | 17 | void *wava_cairo_module_file_load( 18 | wava_cairo_file_type type, 19 | wava_cairo_module_handle *module, 20 | const char *file_name, 21 | char *returned_path) { 22 | 23 | char file_path[MAX_PATH]; 24 | void *pointer = NULL; 25 | 26 | wava_config_source config; 27 | 28 | // "cairo/module/$module_name" 29 | strcpy(file_path, module->prefix); 30 | strcat(file_path, "/"); 31 | // add file name 32 | strcat(file_path, file_name); 33 | 34 | enum WAVA_FILE_TYPE wava_io_file_type; 35 | switch(type) { 36 | case WAVA_CAIRO_FILE_INSTALL_READ: 37 | wava_io_file_type = WAVA_FILE_TYPE_PACKAGE; 38 | break; 39 | default: 40 | wava_io_file_type = WAVA_FILE_TYPE_CONFIG; 41 | break; 42 | } 43 | 44 | // get REAL path 45 | char *actual_path; 46 | wavaReturnErrorCondition( 47 | wavaFindAndCheckFile(wava_io_file_type, 48 | file_path, &actual_path) == false, 49 | NULL, 50 | "Failed to find or open '%s'", file_path); 51 | 52 | switch(type) { 53 | case WAVA_CAIRO_FILE_CONFIG: 54 | config = wavaConfigOpen(actual_path); 55 | pointer = malloc(sizeof(wava_config_source)); 56 | wavaBailCondition(pointer == NULL, "Memory error"); 57 | ((wava_config_source*)pointer)[0] = config; 58 | break; 59 | case WAVA_CAIRO_FILE_INSTALL_READ: 60 | case WAVA_CAIRO_FILE_CONFIG_CUSTOM_READ: 61 | pointer = fopen(file_path, "rb"); 62 | break; 63 | case WAVA_CAIRO_FILE_CONFIG_CUSTOM_WRITE: 64 | pointer = fopen(file_path, "wb"); 65 | break; 66 | default: 67 | wavaReturnError(NULL, "Invalid file type"); 68 | } 69 | 70 | if(returned_path != NULL) { 71 | strcpy(returned_path, actual_path); 72 | } 73 | free(actual_path); 74 | 75 | return pointer; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | X.A.V.A. (https://github.com/nikp123/xava) license: 2 | 3 | Copyright (c) 2021 Nikola Pavlica 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | 24 | Original repository license: 25 | 26 | C.A.V.A. (https://github.com/karlstav/cava) license: 27 | 28 | Copyright (c) 2015 Karl Stavestrand 29 | 30 | Permission is hereby granted, free of charge, to any person obtaining a copy 31 | of this software and associated documentation files (the "Software"), to deal 32 | in the Software without restriction, including without limitation the rights 33 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | copies of the Software, and to permit persons to whom the Software is 35 | furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all 38 | copies or substantial portions of the Software. 39 | 40 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 46 | SOFTWARE. 47 | 48 | 49 | Third-Party licenses: 50 | 51 | -------------------------------------------------------------------------------- /src/output/shared/cairo/util/module.c: -------------------------------------------------------------------------------- 1 | #include "module.h" 2 | #include "region.h" 3 | #include "feature_compat.h" 4 | #include "shared.h" 5 | 6 | WAVA_CAIRO_FEATURE wava_cairo_module_check_compatibility(wava_cairo_module *modules) { 7 | WAVA_CAIRO_FEATURE lowest_common_denominator = 8 | WAVA_CAIRO_FEATURE_DRAW_REGION_SAFE | 9 | WAVA_CAIRO_FEATURE_DRAW_REGION | 10 | WAVA_CAIRO_FEATURE_FULL_DRAW; 11 | 12 | // check whether there are feature misalignments with modules 13 | for(size_t i = 0; i < arr_count(modules); i++) { 14 | wavaReturnErrorCondition(!wava_cairo_feature_compatibility_assert(modules[i].features), 15 | 0, "Module sanity check failed for \'%s\'", modules[i].name); 16 | lowest_common_denominator &= modules[i].features; 17 | } 18 | wavaReturnErrorCondition(lowest_common_denominator == 0, 19 | 0, "Modules do not have inter-compatible drawing methods!\n", 20 | "Please report this to the developer WHILST including your " 21 | "current configuration."); 22 | 23 | // probably will never happen but who knows ¯\_ (ツ)_/¯ 24 | wavaReturnSpamCondition(lowest_common_denominator & WAVA_CAIRO_FEATURE_DRAW_REGION_SAFE, 25 | WAVA_CAIRO_FEATURE_DRAW_REGION_SAFE, 26 | "Skipping region bounds checking as all of them are safe!"); 27 | 28 | // if regions arent supported, full draws MUST be 29 | if((lowest_common_denominator & WAVA_CAIRO_FEATURE_DRAW_REGION) == 0) { 30 | wavaReturnSpamCondition(lowest_common_denominator & WAVA_CAIRO_FEATURE_FULL_DRAW, 31 | WAVA_CAIRO_FEATURE_FULL_DRAW, 32 | "Skipping region bounds checking as all of them are drawing the frame anyway!"); 33 | 34 | wavaBail("No common drawing mode exists. Most likely a BUG!"); 35 | } 36 | 37 | bool pass = true; 38 | for(size_t i = 0; i < arr_count(modules)-1; i++) { 39 | for(size_t j = i+1; j < arr_count(modules); j++) { 40 | if(wava_cairo_region_list_check(modules[i].regions, 41 | modules[j].regions)) { 42 | pass = false; 43 | } 44 | } 45 | } 46 | 47 | if(pass == false) { 48 | wavaBailCondition( 49 | (lowest_common_denominator & WAVA_CAIRO_FEATURE_FULL_DRAW) == 0, 50 | "No common drawing mode exists since no regions match. RIP."); 51 | return WAVA_CAIRO_FEATURE_FULL_DRAW; 52 | } 53 | 54 | return WAVA_CAIRO_FEATURE_DRAW_REGION; 55 | } 56 | -------------------------------------------------------------------------------- /src/output/shared/gl/modules/bars_circle/build.cmake: -------------------------------------------------------------------------------- 1 | # Project default 2 | option(GL_MODULES "GL_MODULES" ON) 3 | 4 | # Xorg 5 | if(GL_MODULES) 6 | # OpenGL/GLEW 7 | find_library(GLEW glew32) 8 | pkg_check_modules(GLEW QUIET glew) 9 | if(GLEW OR GLEW_FOUND) 10 | add_library(gl_bars_circle SHARED "${WAVA_MODULE_DIR}/main.c" 11 | "${WAVA_MODULE_DIR}/../../util/shader.c" 12 | "${WAVA_MODULE_DIR}/../../util/misc.c" 13 | "${GLOBAL_FUNCTION_SOURCES}") 14 | target_link_directories(gl_bars_circle PRIVATE 15 | "${GLEW_LIBRARY_DIRS}") 16 | target_include_directories(gl_bars_circle PRIVATE 17 | "${GLEW_INCLUDE_DIRS}") 18 | 19 | if(WINDOWS OR MINGW OR MSVC OR CYGWIN) 20 | target_link_libraries(gl_bars_circle wava-shared "-lglew32 -lopengl32") 21 | else() 22 | target_link_libraries(gl_bars_circle wava-shared "${GLEW_LIBRARIES}") 23 | endif() 24 | target_compile_definitions(gl_bars_circle PUBLIC -DGL) 25 | 26 | set_target_properties(gl_bars_circle PROPERTIES PREFIX "") 27 | set_target_properties(gl_bars_circle PROPERTIES IMPORT_PREFIX "") 28 | set_target_properties(gl_bars_circle PROPERTIES OUTPUT_NAME "gl/module/bars_circle/module") 29 | 30 | # this copies the dlls for mr. windows 31 | #find_and_copy_dlls(gl_bars_circle) 32 | 33 | configure_file("${WAVA_MODULE_DIR}/vertex.glsl" gl/module/bars_circle/vertex.glsl COPYONLY) 34 | configure_file("${WAVA_MODULE_DIR}/fragment.glsl" gl/module/bars_circle/fragment.glsl COPYONLY) 35 | configure_file("${WAVA_MODULE_DIR}/config.ini" gl/module/bars_circle/config.ini COPYONLY) 36 | install(TARGETS gl_bars_circle RENAME module DESTINATION share/wava/gl/module/bars_circle/) 37 | install(FILES "${CMAKE_BINARY_DIR}/gl/module/bars_circle/vertex.glsl" RENAME vertex.glsl.example DESTINATION share/wava/gl/module/bars_circle/) 38 | install(FILES "${CMAKE_BINARY_DIR}/gl/module/bars_circle/fragment.glsl" RENAME fragment.glsl.example DESTINATION share/wava/gl/module/bars_circle/) 39 | install(FILES "${CMAKE_BINARY_DIR}/gl/module/bars_circle/config.ini" RENAME config.ini.example DESTINATION share/wava/gl/module/bars_circle/) 40 | 41 | # Maybe GL license? 42 | else() 43 | message(WARNING "GLEW library not found; \"gl_bars_circle\" won't build") 44 | endif() 45 | endif() 46 | -------------------------------------------------------------------------------- /src/output/shared/cairo/util/module.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_OUTPUT_SHARED_CAIRO_UTIL_MODULE_H 2 | #define __WAVA_OUTPUT_SHARED_CAIRO_UTIL_MODULE_H 3 | 4 | #include 5 | #include 6 | #include "shared.h" 7 | #include "feature_compat.h" 8 | #include "region.h" 9 | 10 | typedef struct wava_cairo_module_handle { 11 | WAVA_CAIRO_FEATURE use_feature; 12 | char *name; 13 | char *prefix; 14 | WAVA *wava; 15 | cairo_t *cr; 16 | XG_EVENT_STACK *events; 17 | } wava_cairo_module_handle; 18 | 19 | typedef struct wava_cairo_module { 20 | char *name; 21 | char *prefix; 22 | WAVA_CAIRO_FEATURE features; 23 | wava_cairo_region *regions; 24 | 25 | wava_cairo_module_handle config; 26 | 27 | struct functions { 28 | // report version 29 | wava_version (*version) (void); 30 | 31 | // load all the necessary config data and report supported drawing modes 32 | WAVA_CAIRO_FEATURE (*config_load)(wava_cairo_module_handle*); 33 | void (*init) (wava_cairo_module_handle*); 34 | void (*apply) (wava_cairo_module_handle*); 35 | 36 | // report drawn regions 37 | wava_cairo_region* (*regions) (wava_cairo_module_handle*); 38 | 39 | // event handler (events are stored in a variable in the handle) 40 | void (*event) (wava_cairo_module_handle*); 41 | 42 | // placeholder 43 | void (*clear) (wava_cairo_module_handle*); 44 | 45 | // only used with draw_region 46 | void (*draw_region)(wava_cairo_module_handle*); 47 | 48 | // no matter what condition, this ensures a safe write 49 | void (*draw_safe) (wava_cairo_module_handle*); 50 | 51 | // assume that the entire screen's being overwritten 52 | void (*draw_full) (wava_cairo_module_handle*); 53 | 54 | void (*cleanup) (wava_cairo_module_handle*); 55 | 56 | // ionotify fun 57 | void (*ionotify_callback) 58 | (WAVA_IONOTIFY_EVENT, 59 | const char* filename, 60 | int id, 61 | WAVA*); 62 | } func; 63 | 64 | // module handle for fun 65 | WAVAMODULE *handle; 66 | } wava_cairo_module; 67 | 68 | WAVA_CAIRO_FEATURE wava_cairo_module_check_compatibility(wava_cairo_module *modules); 69 | #endif // __WAVA_OUTPUT_SHARED_CAIRO_UTIL_MODULE_H 70 | 71 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(wava C CXX) 2 | cmake_minimum_required(VERSION 3.13) 3 | 4 | # Include common funnctions 5 | include(src/cmake/utilities.cmake) 6 | 7 | # Fix/handle common build errors 8 | include(src/cmake/build-fix.cmake) 9 | 10 | # Debug is default 11 | if(NOT CMAKE_BUILD_TYPE) 12 | set(CMAKE_BUILD_TYPE Debug) 13 | endif() 14 | 15 | # Allow for custom link prefixes (in order to optimize CMake builds for packagers) 16 | if(NOT WAVA_LINK_TO_INSTALL_DIR) 17 | set(WAVA_LINK_TO_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}") 18 | endif() 19 | 20 | # Define WAVA version 21 | set(wava_VERSION_MAJOR 0) 22 | set(wava_VERSION_MINOR 7) 23 | set(wava_VERSION_PATCH 1) 24 | set(wava_VERSION_TWEAK 1) 25 | set(wava_VERSION "${wava_VERSION_MAJOR}.${wava_VERSION_MINOR}.${wava_VERSION_PATCH}.${wava_VERSION_TWEAK}" CACHE STRING "WAVA version") 26 | 27 | # Definitions 28 | add_definitions(-DPACKAGE="wava" -DVERSION="${wava_VERSION}") 29 | add_definitions(-DWAVA_VERSION_MAJOR"=${wava_VERSION_MAJOR}") 30 | add_definitions(-DWAVA_VERSION_MINOR"=${wava_VERSION_MINOR}") 31 | add_definitions(-DWAVA_VERSION_PATCH"=${wava_VERSION_PATCH}") 32 | add_definitions(-DWAVA_VERSION_TWEAK"=${wava_VERSION_TWEAK}") 33 | add_definitions(-DPREFIX="${WAVA_LINK_TO_INSTALL_DIR}") 34 | 35 | # Do OS-specific stuff 36 | include(src/cmake/os-prerequisites.cmake) 37 | 38 | # Set appropriate C flags 39 | set(CMAKE_C_STANDARD 11) 40 | set(CMAKE_C_FLAGS "-Wall -Wextra ${BUILD_FLAGS}") 41 | set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG ${BUILD_DEBUG_FLAGS}") 42 | set(CMAKE_C_FLAGS_RELEASE "-O3 -fvisibility='internal'") 43 | set(CMAKE_CXX_FLAGS "-Wall -Wextra ${BUILD_FLAGS}") 44 | set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG ${BUILD_DEBUG_FLAGS}") 45 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fvisibility='internal' ") 46 | 47 | find_package(PkgConfig REQUIRED) 48 | 49 | # math lib 50 | find_library(MATH_LIB m HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 51 | if(NOT MATH_LIB) 52 | message(FATAL_ERROR "math library not found") 53 | endif() 54 | 55 | # pthread 56 | find_library(THREAD_LIB pthread HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 57 | if(NOT THREAD_LIB) 58 | message(FATAL_ERROR "pthread library not found") 59 | endif() 60 | 61 | include_directories(src) 62 | 63 | # Build shared library 64 | include("src/shared/build.cmake") 65 | 66 | # Build modules 67 | include("src/cmake/modules.cmake") 68 | 69 | # Build executable 70 | add_executable( 71 | wava 72 | ${ADDITIONAL_OBJS} 73 | src/config.c 74 | src/wava.c 75 | ) 76 | 77 | # Link executable 78 | target_link_libraries(wava wava-shared m pthread) 79 | 80 | include(src/cmake/install_and_configure.cmake) 81 | 82 | -------------------------------------------------------------------------------- /src/shared/ionotify.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "shared/ionotify.h" 4 | #include "shared.h" 5 | 6 | // cringe but bare with me k 7 | struct hax { 8 | void *original_data; 9 | void (*wava_ionotify_func)(WAVA_IONOTIFY_EVENT, 10 | const char *filename, int id, WAVA*); 11 | }; 12 | 13 | static struct hax hax[100]; 14 | static size_t hax_count; 15 | 16 | EXP_FUNC WAVAIONOTIFY wavaIONotifySetup(void) { 17 | hax_count = 0; 18 | return (WAVAIONOTIFY)xWatcher_create(); 19 | } 20 | 21 | // before calling the acutal library, this function takes care of 22 | // converting the xWatcher's event types to native ones 23 | void __internal_wavaIONotifyWorkAroundDumbDecisions(XWATCHER_FILE_EVENT event, 24 | const char *name, int id, void* data) { 25 | struct hax *h = (struct hax*)data; 26 | WAVA_IONOTIFY_EVENT new_event = 0; 27 | 28 | switch(event) { 29 | case XWATCHER_FILE_CREATED: 30 | case XWATCHER_FILE_MODIFIED: 31 | new_event = WAVA_IONOTIFY_CHANGED; 32 | break; 33 | case XWATCHER_FILE_REMOVED: 34 | new_event = WAVA_IONOTIFY_DELETED; 35 | break; 36 | case XWATCHER_FILE_OPENED: // this gets triggered by basically everything 37 | case XWATCHER_FILE_ATTRIBUTES_CHANGED: // usually not important 38 | case XWATCHER_FILE_NONE: 39 | case XWATCHER_FILE_RENAMED: // ignoring because most likely breaks visualizer 40 | case XWATCHER_FILE_UNSPECIFIED: 41 | new_event = WAVA_IONOTIFY_NOTHING; 42 | break; 43 | default: 44 | new_event = WAVA_IONOTIFY_ERROR; 45 | } 46 | 47 | h->wava_ionotify_func(new_event, name, id, h->original_data); 48 | } 49 | 50 | EXP_FUNC bool wavaIONotifyAddWatch(WAVAIONOTIFYWATCHSETUP setup) { 51 | xWatcher_reference reference; 52 | 53 | // workaround in progress 54 | hax[hax_count].original_data = setup->wava; 55 | hax[hax_count].wava_ionotify_func = setup->wava_ionotify_func; 56 | 57 | reference.callback_func = __internal_wavaIONotifyWorkAroundDumbDecisions; 58 | reference.context = setup->id; 59 | reference.path = setup->filename; 60 | reference.additional_data = &hax[hax_count]; 61 | 62 | // hax counter 63 | hax_count++; 64 | 65 | wavaBailCondition(hax_count > 100, "Scream at @nikp123 to fix this!"); 66 | 67 | return xWatcher_appendFile(setup->ionotify, &reference); 68 | } 69 | 70 | EXP_FUNC bool wavaIONotifyStart(const WAVAIONOTIFY ionotify) { 71 | return xWatcher_start(ionotify); 72 | } 73 | 74 | EXP_FUNC void wavaIONotifyKill(const WAVAIONOTIFY ionotify) { 75 | xWatcher_destroy(ionotify); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/shared/io/io.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // define directory breaks cuz windows sucks 5 | #ifdef __WIN32__ 6 | #define DIRBRK '\\' 7 | #else 8 | #define DIRBRK '/' 9 | #endif 10 | 11 | #ifdef __linux__ 12 | // I've gotten this from a stranger on the internet 13 | #include 14 | #define MAX_PATH PATH_MAX 15 | #endif 16 | 17 | #ifdef __WIN32__ 18 | #include 19 | #endif 20 | 21 | #ifdef __APPLE__ 22 | #include 23 | #define MAX_PATH PATH_MAX 24 | #endif 25 | 26 | #if defined(__unix__)||defined(__APPLE__) 27 | #define mkdir(dir) mkdir(dir, 0770) 28 | #else 29 | #define mkdir(dir) mkdir(dir) 30 | #endif 31 | 32 | // WAVA file handlers 33 | typedef enum WAVA_FILE_TYPE { 34 | WAVA_FILE_TYPE_CONFIG, // where configuration files are stored 35 | WAVA_FILE_TYPE_OPTIONAL_CONFIG, // where optional configuration files are stored 36 | WAVA_FILE_TYPE_CACHE, // where cached files are stored (shader cache) 37 | WAVA_FILE_TYPE_PACKAGE, // where files that are part of the packages are stored (assets or binaries) 38 | WAVA_FILE_TYPE_NONE, // this is an error 39 | WAVA_FILE_TYPE_CUSTOM_READ, // custom file that can only be readable (must include full path) 40 | WAVA_FILE_TYPE_CUSTOM_WRITE // custom file that can be both readable and writable (must include full path) 41 | } XF_TYPE; 42 | 43 | // simulated data type 44 | typedef struct data { 45 | size_t size; 46 | void* data; 47 | } RawData; 48 | 49 | // WAVA event stuff 50 | typedef enum WAVA_GRAHPICAL_EVENT { 51 | WAVA_REDRAW, WAVA_IGNORE, WAVA_RESIZE, WAVA_RELOAD, 52 | WAVA_QUIT 53 | } XG_EVENT; 54 | 55 | typedef struct WAVA_GRAHPICAL_EVENT_STACK { 56 | int pendingEvents; 57 | XG_EVENT *events; 58 | } XG_EVENT_STACK; 59 | 60 | // simulated event stack 61 | extern void pushWAVAEventStack (XG_EVENT_STACK *stack, XG_EVENT event); 62 | extern XG_EVENT popWAVAEventStack (XG_EVENT_STACK *stack); 63 | extern XG_EVENT_STACK *newWAVAEventStack (); 64 | extern void destroyWAVAEventStack (XG_EVENT_STACK *stack); 65 | extern bool pendingWAVAEventStack (XG_EVENT_STACK *stack); 66 | extern bool isEventPendingWAVA (XG_EVENT_STACK *stack, XG_EVENT event); 67 | 68 | // OS abstractions 69 | extern int wavaMkdir(const char *dir); 70 | extern bool wavaFindAndCheckFile(XF_TYPE type, const char *filename, char **actualPath); 71 | extern unsigned long wavaSleep(unsigned long oldTime, int framerate); 72 | extern unsigned long wavaGetTime(void); 73 | 74 | // file/memory abstractions 75 | extern RawData *wavaReadFile(const char *file); 76 | extern void wavaCloseFile(RawData *file); 77 | extern void *wavaDuplicateMemory(void *memory, size_t size); 78 | 79 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/registry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "wl_output.h" 7 | #include "registry.h" 8 | #include "zwlr.h" 9 | #include "main.h" 10 | #include "xdg.h" 11 | 12 | struct wl_registry *wavaWLRegistry; 13 | 14 | static void wava_wl_registry_global_listener(void *data, struct wl_registry *wl_registry, 15 | uint32_t name, const char *interface, uint32_t version) { 16 | struct waydata *wd = data; 17 | 18 | UNUSED(version); 19 | 20 | #ifdef SHM 21 | if (strcmp(interface, wl_shm_interface.name) == 0) { 22 | wd->shm.ref = wl_registry_bind( 23 | wl_registry, name, &wl_shm_interface, 1); 24 | } else 25 | #endif 26 | if (strcmp(interface, wl_compositor_interface.name) == 0) { 27 | wd->compositor = wl_registry_bind( 28 | wl_registry, name, &wl_compositor_interface, 4); 29 | } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { 30 | wavaXDGWMBase = wl_registry_bind( 31 | wl_registry, name, &xdg_wm_base_interface, 1); 32 | xdg_wm_base_add_listener(wavaXDGWMBase, 33 | &xdg_wm_base_listener, NULL); 34 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { 35 | wavaWLRLayerShell = wl_registry_bind(wavaWLRegistry, name, 36 | &zwlr_layer_shell_v1_interface, 1); 37 | } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { 38 | wavaXDGOutputManager = wl_registry_bind(wavaWLRegistry, name, 39 | &zxdg_output_manager_v1_interface, 2); 40 | } else if (strcmp(interface, wl_output_interface.name) == 0) { 41 | if(!wavaXDGOutputManager) 42 | return; 43 | 44 | struct wlOutput *output = malloc(sizeof(struct wlOutput)); 45 | output->output = wl_registry_bind(wavaWLRegistry, name, 46 | &wl_output_interface, 3); 47 | output->id = name; 48 | 49 | wl_output_add_listener(output->output, &output_listener, output); 50 | wl_list_insert(&wd->outputs, &output->link); 51 | 52 | output->xdg_output = zxdg_output_manager_v1_get_xdg_output( 53 | wavaXDGOutputManager, output->output); 54 | zxdg_output_v1_add_listener(output->xdg_output, 55 | &xdg_output_listener, output); 56 | } 57 | } 58 | 59 | static void wava_wl_registry_global_remove(void *data, struct wl_registry *wl_registry, 60 | uint32_t name) { 61 | UNUSED(wl_registry); 62 | UNUSED(name); 63 | 64 | struct waydata *wd = data; 65 | 66 | // This sometimes happens when displays get reconfigured 67 | pushWAVAEventStack(wd->events, WAVA_RELOAD); 68 | 69 | wavaLog("wl_registry died"); 70 | } 71 | 72 | const struct wl_registry_listener wava_wl_registry_listener = { 73 | .global = wava_wl_registry_global_listener, 74 | .global_remove = wava_wl_registry_global_remove, 75 | }; 76 | 77 | -------------------------------------------------------------------------------- /src/input/shmem/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "shared.h" 14 | 15 | typedef unsigned int u32_t; 16 | typedef short s16_t; 17 | 18 | 19 | // #define BUFSIZE 1024 20 | #define BUFSIZE 4096 21 | 22 | #define VIS_BUF_SIZE 16384 23 | #define VB_OFFSET 8192+4096 24 | 25 | typedef struct { 26 | pthread_rwlock_t rwlock; 27 | u32_t buf_size; 28 | u32_t buf_index; 29 | unsigned char running; 30 | u32_t rate; 31 | time_t updated; 32 | s16_t buffer[VIS_BUF_SIZE]; 33 | } vis_t; 34 | 35 | 36 | //input: SHMEM 37 | EXP_FUNC void* wavaInput(void* data) 38 | { 39 | WAVA_AUDIO *audio = (WAVA_AUDIO *)data; 40 | vis_t *mmap_area; 41 | int fd; /* file descriptor to mmaped area */ 42 | int mmap_count = sizeof( vis_t); 43 | /* 44 | struct timespec req = { .tv_sec = 0, .tv_nsec = 10000000 }; 45 | int16_t buf[BUFSIZE / 2]; 46 | int bytes = 0; 47 | int t = 0; 48 | */ 49 | int n = 0; 50 | int i; 51 | 52 | wavaSpam("SHMEM source: %s", audio->source); 53 | 54 | fd = shm_open(audio->source, O_RDWR, 0666); 55 | 56 | wavaBailCondition(fd<0, "Could not open source '%s': %s", audio->source, strerror(errno)); 57 | 58 | mmap_area = mmap(NULL, sizeof( vis_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 59 | wavaBailCondition((intptr_t)mmap_area==-1, "mmap failed - check if squeezelite is running with visualization enabled"); 60 | 61 | wavaSpam("bufs: %u / run: %u / rate: %u\n",mmap_area->buf_size, mmap_area->running, mmap_area->rate); 62 | audio->rate = mmap_area->rate; 63 | 64 | while (1) { 65 | // for (i = 0; i < BUFSIZE; i += 2) { // BUFSIZE / 2 66 | for (i = VB_OFFSET; i < BUFSIZE+VB_OFFSET; i += 2) { 67 | if (audio->channels == 1) { 68 | audio->audio_out_l[n] = (mmap_area->buffer[i] + mmap_area->buffer[i + 1]) / 2; 69 | } else if (audio->channels == 2) { 70 | audio->audio_out_l[n] = mmap_area->buffer[i]; 71 | audio->audio_out_r[n] = mmap_area->buffer[i + 1]; 72 | } 73 | n++; 74 | if (n == 2048 - 1) n = 0; 75 | } 76 | if (audio->terminate == 1) { 77 | break; 78 | } 79 | } 80 | 81 | // cleanup 82 | wavaErrorCondition(fd<1, "Wrong file descriptor %d", fd); 83 | wavaErrorCondition(close(fd)!=0, "Could not close file descriptor %d: %s", fd, strerror(errno)); 84 | 85 | wavaErrorCondition(munmap(mmap_area, mmap_count)!=0, "Could not munmap() area %p+%d. %s", 86 | mmap_area, mmap_count, strerror(errno)); 87 | return 0; 88 | } 89 | 90 | EXP_FUNC void wavaInputLoadConfig(WAVA *wava) { 91 | WAVA_AUDIO *audio = &wava->audio; 92 | wava_config_source config = wava->default_config.config; 93 | audio->rate = 44100; 94 | audio->source = (char*)wavaConfigGetString(config, "input", "source", "/squeezelite-00:00:00:00:00:00"); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /assets/windows/xava.nsi.template: -------------------------------------------------------------------------------- 1 | !include "MUI2.nsh" 2 | 3 | # Set project name 4 | Name "X.A.V.A." 5 | 6 | !define PRODUCT_VERSION "@wava_VERSION@" 7 | !define VERSION "@wava_VERSION@" 8 | 9 | VIProductVersion "@wava_VERSION@" 10 | VIFileVersion "@wava_VERSION@" 11 | VIAddVersionKey "FileVersion" "@wava_VERSION@" 12 | VIAddVersionKey "LegalCopyright" "(C) Nikola Pavlica" 13 | VIAddVersionKey "FileDescription" "Graphical audio visualizer" 14 | 15 | # installer filename 16 | OutFile "wava-win-installer.exe" 17 | 18 | # installation directory 19 | InstallDir $PROGRAMFILES64\wava 20 | 21 | # Get admin priviledges 22 | RequestExecutionLevel admin 23 | 24 | # start default section 25 | Section 26 | # set the installation directory as the destination for the following actions 27 | SetOutPath $INSTDIR 28 | 29 | # include these files 30 | File wava.exe 31 | File *.dll 32 | File /nonfatal /r gl 33 | File /nonfatal /r cairo 34 | File @wava_EXAMPLE_FILES_NSIS@\config 35 | File final-LICENSE.txt 36 | File README.txt 37 | 38 | SetOutPath $APPDATA\wava\ 39 | 40 | Rename "$INSTDIR\config" "$INSTDIR\config.cfg" 41 | Rename "$INSTDIR\final-LICENSE.txt" "$INSTDIR\LICENSE.txt" 42 | 43 | # create the uninstaller 44 | WriteUninstaller "$INSTDIR\uninstall.exe" 45 | 46 | # create a shortcut named "new shortcut" in the start menu programs directory 47 | # point the new shortcut at the program uninstaller 48 | CreateDirectory "$SMPROGRAMS\WAVA" 49 | CreateShortCut "$SMPROGRAMS\WAVA\WAVA.lnk" "$INSTDIR\wava.exe" "" "$INSTDIR\wava.ico" 50 | CreateShortCut "$SMPROGRAMS\WAVA\Configure WAVA.lnk" "notepad.exe" "%APPDATA%\wava\config.cfg" 51 | CreateShortCut "$SMPROGRAMS\WAVA\Uninstall WAVA.lnk" "$INSTDIR\uninstall.exe" 52 | SectionEnd 53 | 54 | # uninstaller section start 55 | Section "uninstall" 56 | # first, remove the link from the start menu 57 | RMDir /r "$SMPROGRAMS\WAVA" 58 | 59 | # second, delete the program 60 | RMDir /r "$INSTDIR" 61 | # uninstaller section end 62 | SectionEnd 63 | 64 | 65 | !ifndef EM_SETCUEBANNER 66 | !define EM_SETCUEBANNER 0x1501 ; NT5 w/Themes & Vista+ 67 | !endif 68 | 69 | !define MUI_FINISHPAGE_NOAUTOCLOSE 70 | !define MUI_INSTFILESPAGE_NOAUTOCLOSE 71 | 72 | !InsertMacro MUI_PAGE_LICENSE final-LICENSE.txt 73 | 74 | !insertmacro MUI_PAGE_DIRECTORY 75 | 76 | !insertmacro MUI_PAGE_INSTFILES 77 | 78 | # Markdown files dont work for some reason, so we have to do it like this 79 | Function OpenREADME 80 | Exec 'notepad.exe "$INSTDIR\README.txt"' 81 | FunctionEnd 82 | 83 | ; Finish page 84 | !define MUI_FINISHPAGE_RUN "$INSTDIR\wava.exe" 85 | !define MUI_FINISHPAGE_RUN_NOTCHECKED 86 | !define MUI_FINISHPAGE_SHOWREADME 87 | !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED 88 | !define MUI_FINISHPAGE_SHOWREADME_FUNCTION 'OpenREADME' 89 | !define MUI_FINISHPAGE_LINK 'Check out the project page' 90 | !define MUI_FINISHPAGE_LINK_LOCATION https://www.github.com/nikp123/wava 91 | !insertmacro MUI_PAGE_FINISH 92 | !insertmacro MUI_LANGUAGE English 93 | 94 | -------------------------------------------------------------------------------- /src/input/fifo/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "shared.h" 8 | 9 | int rc; 10 | 11 | int open_fifo(const char *path) { 12 | int fd = open(path, O_RDONLY); 13 | int flags = fcntl(fd, F_GETFL, 0); 14 | fcntl(fd, F_SETFL, flags | O_NONBLOCK); 15 | return fd; 16 | } 17 | 18 | // input: FIFO 19 | EXP_FUNC void* wavaInput(void* data) 20 | { 21 | WAVA_AUDIO *audio = (WAVA_AUDIO *)data; 22 | int fd; 23 | uint32_t n = 0; 24 | //signed char buf[1024]; 25 | //int tempr, templ, lo, q; 26 | int t = 0; 27 | //int size = 1024; 28 | ssize_t bytes = 0; 29 | int16_t buf[audio->inputsize]; 30 | struct timespec req = { .tv_sec = 0, .tv_nsec = 10000000 }; 31 | 32 | fd = open_fifo(audio->source); 33 | 34 | // first read to remove any latency that may happen 35 | nanosleep (&req, NULL); 36 | while(!bytes) { 37 | bytes = read(fd, buf, sizeof(buf)); 38 | } 39 | 40 | while (1) { 41 | bytes = read(fd, buf, sizeof(buf)); 42 | 43 | if (bytes < 1) { //if no bytes read sleep 10ms and zero shared buffer 44 | nanosleep (&req, NULL); 45 | t++; 46 | if (t > 10) { 47 | for (uint32_t i = 0; i < audio->inputsize; i++) 48 | audio->audio_out_l[i] = 0; 49 | 50 | // prevents filling a invalid buffer whilst in mono mode 51 | if (audio->channels == 2) { 52 | for (uint32_t i = 0; i < audio->inputsize; i++) 53 | audio->audio_out_r[i] = 0; 54 | } 55 | close(fd); 56 | fd = open_fifo(audio->source); 57 | t = 0; 58 | } 59 | } else { //if bytes read go ahead 60 | t = 0; 61 | 62 | // assuming samples are 16bit (as per example) 63 | // also reading more than the retrieved buffer is considered memory corruption 64 | for (uint32_t i = 0; i < bytes/2; i += 2) { 65 | if (audio->channels == 1) audio->audio_out_l[n] = (float)(buf[i] + buf[i + 1]) / (float)2.0; 66 | 67 | //stereo storing channels in buffer 68 | if (audio->channels == 2) { 69 | audio->audio_out_l[n] = buf[i]; 70 | audio->audio_out_r[n] = buf[i + 1]; 71 | } 72 | 73 | n++; 74 | if (n == audio->inputsize-1) n = 0; 75 | } 76 | } 77 | 78 | if (audio->terminate == 1) { 79 | close(fd); 80 | break; 81 | } 82 | } 83 | return 0; 84 | } 85 | 86 | EXP_FUNC void wavaInputLoadConfig(WAVA *wava) { 87 | WAVA_AUDIO *audio = &wava->audio; 88 | wava_config_source config = wava->default_config.config; 89 | wavaWarnCondition(audio->rate != 44100, 90 | "Changing the audio rate won't do much as that depends on your MPD " 91 | "settings. Go check those instead!"); 92 | audio->source = (char*)wavaConfigGetString(config, "input", "source", "/tmp/mpd.fifo"); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/shared/util/version.c: -------------------------------------------------------------------------------- 1 | #include "shared.h" 2 | 3 | EXP_FUNC wava_version wava_version_host_get(void) { 4 | wava_version v; 5 | v.major = WAVA_VERSION_MAJOR; 6 | v.minor = WAVA_VERSION_MINOR; 7 | v.tweak = WAVA_VERSION_TWEAK; 8 | v.patch = WAVA_VERSION_PATCH; 9 | return v; 10 | } 11 | 12 | EXP_FUNC bool wava_version_less(wava_version host, wava_version target) 13 | { 14 | if(target.major > host.major) { 15 | return false; 16 | } else if (target.major < host.major) { 17 | return true; 18 | } 19 | 20 | if(target.minor > host.minor) { 21 | return false; 22 | } else if (target.minor < host.minor) { 23 | return true; 24 | } 25 | 26 | if(target.tweak > host.tweak) { 27 | return false; 28 | } else if (target.tweak < host.tweak) { 29 | return true; 30 | } 31 | 32 | if(target.patch > host.patch) { 33 | return false; 34 | } else if (target.patch < host.patch) { 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | EXP_FUNC bool wava_version_greater(wava_version host, wava_version target) 42 | { 43 | if(target.major > host.major) { 44 | return true; 45 | } else if (target.major < host.major) { 46 | return false; 47 | } 48 | 49 | if(target.minor > host.minor) { 50 | return true; 51 | } else if (target.minor < host.minor) { 52 | return false; 53 | } 54 | 55 | if(target.tweak > host.tweak) { 56 | return true; 57 | } else if (target.tweak < host.tweak) { 58 | return false; 59 | } 60 | 61 | if(target.patch > host.patch) { 62 | return true; 63 | } else if (target.patch < host.patch) { 64 | return false; 65 | } 66 | 67 | return false; 68 | } 69 | 70 | EXP_FUNC bool wava_version_equal(wava_version host, wava_version target) 71 | { 72 | if(target.major == host.major && target.minor == host.minor && 73 | target.tweak == host.tweak && target.patch == host.patch) { 74 | return true; 75 | } 76 | return false; 77 | } 78 | 79 | EXP_FUNC bool wava_version_breaking_check(wava_version target) 80 | { 81 | // list of all versions that broke something in terms of internal variables 82 | wava_version breaking_versions[] = { 83 | {0, 7, 1, 1}, 84 | }; 85 | 86 | for(size_t i = 0; i < sizeof(breaking_versions)/sizeof(wava_version); i++) { 87 | if(wava_version_less(breaking_versions[i], target)) { 88 | return true; 89 | } 90 | } 91 | 92 | return false; 93 | } 94 | 95 | EXP_FUNC WAVA_VERSION_COMPATIBILITY wava_version_verify(wava_version target) 96 | { 97 | wava_version host = wava_version_host_get(); 98 | 99 | if(wava_version_equal(host, target)) { 100 | return WAVA_VERSIONS_COMPATIBLE; 101 | } 102 | 103 | if(wava_version_breaking_check(target)) { 104 | wavaError("The version of the module is NOT compatible with the current build"); 105 | return WAVA_VERSIONS_INCOMPATIBLE; 106 | } 107 | 108 | if(wava_version_greater(host, target)) { 109 | wavaError("Please update WAVA to run this."); 110 | return WAVA_VERSIONS_INCOMPATIBLE; 111 | } 112 | 113 | wavaWarn("Versions may not be compatbile"); 114 | return WAVA_VERSIONS_UNKNOWN; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/shared/config/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_SHARED_CONFIG_H 2 | #define __WAVA_SHARED_CONFIG_H 3 | 4 | #include "shared/util/types.h" 5 | 6 | // config entry macro (cursed) 7 | #define WAVA_CONFIG_OPTION(T, name) \ 8 | T name; bool name##_is_set_from_file 9 | 10 | // config line macro 11 | #define WAVA_CONFIG_GET_STRING(config, section, key, default_value, return_value) \ 12 | __internal_wavaConfigGetString(config, section, key, default_value, &return_value, &return_value##_is_set_from_file) 13 | #define WAVA_CONFIG_GET_BOOL(config, section, key, default_value, return_value) \ 14 | __internal_wavaConfigGetBool(config, section, key, default_value, &return_value, &return_value##_is_set_from_file) 15 | #define WAVA_CONFIG_GET_I32(config, section, key, default_value, return_value) \ 16 | __internal_wavaConfigGetI32(config, section, key, default_value, &return_value, &return_value##_is_set_from_file) 17 | #define WAVA_CONFIG_GET_U32(config, section, key, default_value, return_value) \ 18 | __internal_wavaConfigGetU32(config, section, key, default_value, &return_value, &return_value##_is_set_from_file) 19 | #define WAVA_CONFIG_GET_F64(config, section, key, default_value, return_value) \ 20 | __internal_wavaConfigGetF64(config, section, key, default_value, &return_value, &return_value##_is_set_from_file) 21 | 22 | typedef struct wava_config* wava_config_source; 23 | 24 | extern void __internal_wavaConfigGetString( 25 | wava_config_source config, 26 | const char* section, 27 | const char* key, 28 | const char* default_value, 29 | char **value, 30 | bool *value_is_set); 31 | 32 | extern void __internal_wavaConfigGetBool( 33 | wava_config_source config, 34 | const char* section, 35 | const char* key, 36 | bool default_value, 37 | bool *value, 38 | bool *value_is_set); 39 | 40 | extern void __internal_wavaConfigGetI32( 41 | wava_config_source config, 42 | const char* section, 43 | const char* key, 44 | i32 default_value, 45 | i32 *value, 46 | bool *value_is_set); 47 | 48 | extern void __internal_wavaConfigGetU32( 49 | wava_config_source config, 50 | const char* section, 51 | const char* key, 52 | u32 default_value, 53 | u32 *value, 54 | bool *value_is_set); 55 | 56 | extern void __internal_wavaConfigGetF64( 57 | wava_config_source config, 58 | const char* section, 59 | const char* key, 60 | f64 default_value, 61 | f64 *value, 62 | bool *value_is_set); 63 | 64 | 65 | extern bool wavaConfigGetBool (wava_config_source config, const char *section, const char *key, bool default_value); 66 | extern i32 wavaConfigGetI32 (wava_config_source config, const char *section, const char *key, i32 default_value); 67 | extern f64 wavaConfigGetF64 (wava_config_source config, const char *section, const char *key, f64 default_value); 68 | extern char* wavaConfigGetString(wava_config_source config, const char *section, const char *key, const char* default_value); 69 | 70 | extern wava_config_source wavaConfigOpen (const char *filename); 71 | extern void wavaConfigClose(wava_config_source config); 72 | 73 | extern int wavaConfigGetKeyNumber(wava_config_source config, const char *section); 74 | extern char** wavaConfigGetKeys (wava_config_source config, const char *section); 75 | #endif 76 | 77 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/xdg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "output/shared/graphical.h" 6 | 7 | #include "gen/xdg-shell-client-protocol.h" 8 | 9 | #include "xdg.h" 10 | #include "main.h" 11 | #ifdef EGL 12 | #include "egl.h" 13 | #endif 14 | #ifdef SHM 15 | #include "shm.h" 16 | #endif 17 | #ifdef CAIRO 18 | #include "cairo.h" 19 | #endif 20 | 21 | static struct xdg_surface *wavaXDGSurface; 22 | static struct xdg_toplevel *wavaXDGToplevel; 23 | 24 | struct xdg_wm_base *wavaXDGWMBase; 25 | 26 | static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, 27 | uint32_t serial) { 28 | UNUSED(data); 29 | xdg_wm_base_pong(xdg_wm_base, serial); 30 | } 31 | 32 | const struct xdg_wm_base_listener xdg_wm_base_listener = { 33 | .ping = xdg_wm_base_ping, 34 | }; 35 | 36 | static void xdg_toplevel_handle_configure(void *data, 37 | struct xdg_toplevel *xdg_toplevel, int32_t w, int32_t h, 38 | struct wl_array *states) { 39 | UNUSED(xdg_toplevel); 40 | UNUSED(states); 41 | 42 | struct waydata *wd = data; 43 | WAVA *wava = wd->hand; 44 | WAVA_CONFIG *conf = &wava->conf; 45 | 46 | if(w == 0 && h == 0) return; 47 | 48 | if(conf->w != (uint32_t)w && conf->h != (uint32_t)h) { 49 | // fixme when i get proper monitor support on XDG 50 | calculate_win_geo(wava, w, h); 51 | 52 | #ifdef EGL 53 | waylandEGLWindowResize(wd, w, h); 54 | #endif 55 | 56 | #ifdef SHM 57 | reallocSHM(wd); 58 | #endif 59 | 60 | #ifdef CAIRO 61 | wava_output_wayland_cairo_resize(wd); 62 | #endif 63 | 64 | pushWAVAEventStack(wd->events, WAVA_REDRAW); 65 | pushWAVAEventStack(wd->events, WAVA_RESIZE); 66 | } 67 | 68 | #ifdef SHM 69 | update_frame(wd); 70 | #endif 71 | } 72 | 73 | static void xdg_toplevel_handle_close(void *data, 74 | struct xdg_toplevel *xdg_toplevel) { 75 | struct waydata *wd = data; 76 | 77 | UNUSED(xdg_toplevel); 78 | 79 | pushWAVAEventStack(wd->events, WAVA_QUIT); 80 | } 81 | 82 | struct xdg_toplevel_listener xdg_toplevel_listener = { 83 | .configure = xdg_toplevel_handle_configure, 84 | .close = xdg_toplevel_handle_close, 85 | }; 86 | 87 | static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, 88 | uint32_t serial) { 89 | UNUSED(data); 90 | 91 | // confirm that you exist to the compositor 92 | xdg_surface_ack_configure(xdg_surface, serial); 93 | } 94 | 95 | const struct xdg_surface_listener xdg_surface_listener = { 96 | .configure = xdg_surface_configure, 97 | }; 98 | 99 | void xdg_init(struct waydata *wd) { 100 | // create window, or "surface" in waland terms 101 | wavaXDGSurface = xdg_wm_base_get_xdg_surface(wavaXDGWMBase, wd->surface); 102 | 103 | // for those unaware, the compositor baby sits everything that you 104 | // make, thus it needs a function through which the compositor 105 | // will manage your application 106 | xdg_surface_add_listener(wavaXDGSurface, &xdg_surface_listener, wd); 107 | 108 | wavaXDGToplevel = xdg_surface_get_toplevel(wavaXDGSurface); 109 | xdg_toplevel_set_title(wavaXDGToplevel, "WAVA"); 110 | xdg_toplevel_add_listener(wavaXDGToplevel, &xdg_toplevel_listener, wd); 111 | } 112 | 113 | void xdg_cleanup() { 114 | xdg_toplevel_destroy(wavaXDGToplevel); 115 | xdg_surface_destroy(wavaXDGSurface); 116 | } 117 | -------------------------------------------------------------------------------- /src/output/graphical_win/build.cmake: -------------------------------------------------------------------------------- 1 | # The project default 2 | option(WINAPI "WINAPI" ON) 3 | 4 | if(NOT (MSYS OR MINGW OR MSVC)) 5 | set(WINAPI OFF) 6 | endif() 7 | 8 | # winapi 9 | if(WINAPI) 10 | find_library(GDI_LIB gdi32 HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 11 | if(GDI_LIB) 12 | find_library(GLU_LIB glu32 HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 13 | if(GLU_LIB) 14 | find_library(DWM_LIB dwmapi HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 15 | if(DWM_LIB) 16 | find_library(WGL_LIB opengl32 HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) 17 | 18 | # This is the only way it works under Windows+CMake for some reason 19 | find_library(GLEW glew32) 20 | 21 | # add winapi test 22 | list(APPEND DEFAULT_OUTPUT_SOURCES "${WAVA_MODULE_DIR}/test.c") 23 | #list(APPEND DEFAULT_OUTPUT_LINKDIR "${WIN_LIBRARY_DIRS}") 24 | #list(APPEND DEFAULT_OUTPUT_LINKLIB "${WIN_LIBRARIES}") 25 | #list(APPEND DEFAULT_OUTPUT_INCDIR "${WIN_INCLUDE_DIRS}") 26 | list(APPEND DEFAULT_OUTPUT_DEF "-DWINDOWS") 27 | 28 | if(WGL_LIB AND GLEW) 29 | add_library(out_win_opengl SHARED "${WAVA_MODULE_DIR}/main.c" 30 | "src/output/shared/graphical.c" 31 | "src/output/shared/gl/glew.c" 32 | "src/output/shared/gl/main.c" 33 | "${GLOBAL_FUNCTION_SOURCES}") 34 | target_link_libraries(out_win_opengl wava-shared 35 | "-lglew32 -lgdi32 -lwinmm -lopengl32 -ldwmapi") 36 | target_compile_definitions(out_win_opengl PUBLIC -DWIN -DGL) 37 | set_target_properties(out_win_opengl PROPERTIES PREFIX "") 38 | 39 | find_and_copy_dlls(out_win_opengl) 40 | else() 41 | message(WARNING "OpenGL or GLEW library not found; 'out_win' app won't build") 42 | endif() 43 | 44 | pkg_check_modules(CAIRO QUIET cairo) 45 | if(CAIRO_FOUND) 46 | add_library(out_win_cairo SHARED "${WAVA_MODULE_DIR}/main.c" 47 | "src/output/shared/graphical.c" 48 | "src/output/shared/cairo/main.c" 49 | "src/output/shared/cairo/util/module.c" 50 | "src/output/shared/cairo/util/feature_compat.c" 51 | "src/output/shared/cairo/util/region.c" 52 | "${GLOBAL_FUNCTION_SOURCES}") 53 | target_link_libraries(out_win_cairo wava-shared "-lgdi32" 54 | "-lwinmm -ldwmapi" ${CAIRO_LIBRARIES}) 55 | target_link_directories(out_win_cairo PRIVATE 56 | ${CAIRO_LIBRARY_DIRS}) 57 | target_include_directories(out_win_cairo PRIVATE 58 | "${CAIRO_INCLUDE_DIRS}") 59 | target_compile_definitions(out_win_cairo PUBLIC -DWIN -DCAIRO) 60 | set_target_properties(out_win_cairo PROPERTIES PREFIX "") 61 | 62 | find_and_copy_dlls(out_win_cairo) 63 | else() 64 | message(WARNING "Cairo library not found, \"win_cairo\" won't build") 65 | endif() 66 | else() 67 | message(WARNING "DWMAPI library not found, WinAPI app won't build") 68 | endif() 69 | else() 70 | message(WARNING "GLU library not found, WinAPI app won't build") 71 | endif() 72 | else() 73 | message(WARNING "GDI library not found, WinAPI app won't build") 74 | endif() 75 | endif() 76 | -------------------------------------------------------------------------------- /src/output/shared/gl/egl.c: -------------------------------------------------------------------------------- 1 | 2 | #include "egl.h" 3 | 4 | #include "shared.h" 5 | #include "output/shared/graphical.h" 6 | 7 | 8 | void EGLConfigLoad(WAVA *wava) { 9 | SGLConfigLoad(wava); 10 | } 11 | 12 | EGLBoolean EGLCreateContext(WAVA *wava, struct _escontext *ESContext) { 13 | WAVA_CONFIG *conf = &wava->conf; 14 | EGLint numConfigs; 15 | EGLint majorVersion; 16 | EGLint minorVersion; 17 | EGLContext context; 18 | EGLSurface surface; 19 | EGLConfig config; 20 | EGLint fbAttribs[] = 21 | { 22 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 23 | EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, 24 | EGL_DEPTH_SIZE, 8, 25 | EGL_RED_SIZE, 8, 26 | EGL_GREEN_SIZE, 8, 27 | EGL_BLUE_SIZE, 8, 28 | EGL_ALPHA_SIZE, conf->flag.transparency ? 8 : 0, 29 | EGL_NONE 30 | }; 31 | EGLint contextAttribs[] = { EGL_CONTEXT_MAJOR_VERSION, 2, 32 | EGL_CONTEXT_MINOR_VERSION, 1, 33 | EGL_CONTEXT_OPENGL_PROFILE_MASK, 34 | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 35 | EGL_NONE }; 36 | 37 | eglBindAPI(EGL_OPENGL_API); 38 | 39 | EGLDisplay display = eglGetDisplay(ESContext->native_display); 40 | if ( display == EGL_NO_DISPLAY ) 41 | { 42 | wavaError("No EGL display"); 43 | return EGL_FALSE; 44 | } 45 | 46 | // Initialize EGL 47 | if ( !eglInitialize(display, &majorVersion, &minorVersion) ) 48 | { 49 | wavaError("eglInitialize failed"); 50 | return EGL_FALSE; 51 | } 52 | 53 | wavaSpam("Initialized EGL API version: %d.%d", majorVersion, minorVersion); 54 | 55 | // Get configs 56 | if ( (eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) 57 | { 58 | wavaError("EGL was unable to find display configs"); 59 | return EGL_FALSE; 60 | } 61 | 62 | // Choose config 63 | if ( (eglChooseConfig(display, fbAttribs, &config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) 64 | { 65 | wavaError("EGL was unable to choose a config"); 66 | return EGL_FALSE; 67 | } 68 | 69 | // Create a surface 70 | surface = eglCreateWindowSurface(display, config, ESContext->native_window, NULL); 71 | if ( surface == EGL_NO_SURFACE ) 72 | { 73 | wavaError("EGL was unable to create a surface"); 74 | return EGL_FALSE; 75 | } 76 | 77 | // Create a GL context 78 | context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs ); 79 | if ( context == EGL_NO_CONTEXT ) 80 | { 81 | wavaError("EGL was unable to create a context"); 82 | return EGL_FALSE; 83 | } 84 | 85 | // Make the context current 86 | if ( !eglMakeCurrent(display, surface, surface, context) ) 87 | { 88 | wavaError("EGL was not able to switch to to the current window"); 89 | return EGL_FALSE; 90 | } 91 | 92 | ESContext->display = display; 93 | ESContext->surface = surface; 94 | ESContext->context = context; 95 | return EGL_TRUE; 96 | } 97 | 98 | void EGLInit(WAVA *wava) { 99 | glewInit(); 100 | SGLInit(wava); 101 | } 102 | 103 | void EGLApply(WAVA *wava) { 104 | SGLApply(wava); 105 | } 106 | 107 | XG_EVENT_STACK *EGLEvent(WAVA *wava) { 108 | return SGLEvent(wava); 109 | } 110 | 111 | void EGLClear(WAVA *wava) { 112 | SGLClear(wava); 113 | } 114 | 115 | void EGLDraw(WAVA *wava) { 116 | SGLDraw(wava); 117 | } 118 | 119 | void EGLCleanup(WAVA *wava, struct _escontext *ESContext) { 120 | SGLCleanup(wava); 121 | eglDestroyContext(ESContext->display, ESContext->context); 122 | eglDestroySurface(ESContext->display, ESContext->surface); 123 | eglTerminate(ESContext->display); 124 | } 125 | 126 | -------------------------------------------------------------------------------- /src/output/shared/gl/main.h: -------------------------------------------------------------------------------- 1 | #include "shared.h" 2 | 3 | #ifndef __WAVA_OUTPUT_GL_MAIN_H 4 | #define __WAVA_OUTPUT_GL_MAIN_H 5 | 6 | // for static checker sake 7 | #if !defined(GL) && !defined(EGL) 8 | #define GL 9 | #warning "This WILL break your build. Fix it!" 10 | #endif 11 | 12 | #if defined(EGL) 13 | #include 14 | #include 15 | #endif 16 | 17 | #ifndef GL_ALREADY_DEFINED 18 | #include 19 | #endif 20 | 21 | typedef struct WAVAGLModuleOptions { 22 | // actual options used by the module 23 | GLdouble resolution_scale; 24 | WAVA *wava; 25 | void (*ionotify_callback) 26 | (WAVA_IONOTIFY_EVENT, 27 | const char* filename, 28 | int id, 29 | WAVA*); 30 | 31 | char *prefix; 32 | XG_EVENT_STACK *events; 33 | } WAVAGLModuleOptions; 34 | 35 | // working around my badly designed includes 36 | typedef struct WAVAGLModule WAVAGLModule; 37 | 38 | // shader stuff 39 | typedef struct wava_gl_module_program { 40 | struct shader { 41 | char *path, *text; 42 | GLuint handle; 43 | } frag, vert, geo; 44 | GLuint program; 45 | wava_config_source config; 46 | } wava_gl_module_program; 47 | 48 | // post render stuff 49 | typedef enum gl_module_post_render_features { 50 | GL_MODULE_POST_INTENSITY = 1, 51 | GL_MODULE_POST_COLORS = 2, 52 | GL_MODULE_POST_TIME = 4, 53 | } gl_module_post_render_features; 54 | 55 | struct WAVAGLModule { 56 | char *name; 57 | char *prefix; 58 | WAVAMODULE *handle; 59 | 60 | struct functions { 61 | wava_version (*version)(void); 62 | void (*config_load)(WAVAGLModule*,WAVA*); 63 | void (*init)(WAVAGLModuleOptions*); 64 | void (*apply)(WAVAGLModuleOptions*); 65 | void (*event)(WAVAGLModuleOptions*); 66 | /** 67 | * events are returned through the options->events thingy 68 | **/ 69 | void (*clear)(WAVAGLModuleOptions*); 70 | void (*draw)(WAVAGLModuleOptions*); 71 | void (*cleanup)(WAVAGLModuleOptions*); 72 | void (*ionotify_callback) 73 | (WAVA_IONOTIFY_EVENT, 74 | const char* filename, 75 | int id, 76 | WAVA*); 77 | } func; 78 | 79 | WAVAGLModuleOptions options; 80 | }; 81 | 82 | typedef struct WAVAGLHostOptions { 83 | WAVAGLModule *module; 84 | WAVA_CONFIG_OPTION(f64, resolution_scale); 85 | XG_EVENT_STACK *events; 86 | WAVA *wava; 87 | 88 | struct FBO { 89 | GLuint framebuffer; 90 | GLuint final_texture; 91 | GLuint depth_texture; 92 | } FBO; 93 | 94 | // post shader variables 95 | struct gl_vars { 96 | // geometry info 97 | GLuint POS; 98 | GLuint TEXCOORD; 99 | GLuint RESOLUTION; 100 | GLuint DOTS; 101 | 102 | // textures 103 | GLuint TEXTURE; 104 | GLuint DEPTH; 105 | 106 | // system info 107 | GLuint TIME; 108 | GLuint INTENSITY; 109 | 110 | // color information 111 | GLuint FGCOL; 112 | GLuint BGCOL; 113 | } gl_vars; 114 | 115 | wava_gl_module_program post; 116 | gl_module_post_render_features features; 117 | bool post_enabled; 118 | } WAVAGLHostOptions; 119 | 120 | void SGLConfigLoad(WAVA *wava); 121 | void SGLInit(WAVA *wava); 122 | void SGLApply(WAVA *wava); 123 | XG_EVENT_STACK *SGLEvent(WAVA *wava); 124 | void SGLClear(WAVA *wava); 125 | void SGLDraw(WAVA *wava); 126 | void SGLCleanup(WAVA *wava); 127 | 128 | #endif 129 | 130 | -------------------------------------------------------------------------------- /src/output/shared/cairo/modules/kinetic/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "output/shared/cairo/util/module.h" 4 | #include "output/shared/graphical.h" 5 | #include "shared.h" 6 | 7 | // report version 8 | EXP_FUNC wava_version wava_cairo_module_version(void) { 9 | return wava_version_host_get(); 10 | } 11 | 12 | // load all the necessary config data and report supported drawing modes 13 | EXP_FUNC WAVA_CAIRO_FEATURE wava_cairo_module_config_load(wava_cairo_module_handle* handle) { 14 | UNUSED(handle); 15 | return WAVA_CAIRO_FEATURE_FULL_DRAW; 16 | } 17 | 18 | EXP_FUNC void wava_cairo_module_init(wava_cairo_module_handle* handle) { 19 | UNUSED(handle); 20 | } 21 | 22 | EXP_FUNC void wava_cairo_module_apply(wava_cairo_module_handle* handle) { 23 | UNUSED(handle); 24 | } 25 | 26 | // report drawn regions 27 | EXP_FUNC wava_cairo_region* wava_cairo_module_regions(wava_cairo_module_handle* handle) { 28 | UNUSED(handle); 29 | return NULL; 30 | } 31 | 32 | // event handler 33 | EXP_FUNC void wava_cairo_module_event (wava_cairo_module_handle* handle) { 34 | WAVA *wava = handle->wava; 35 | 36 | // check if the visualizer bounds were changed 37 | if((wava->inner.w != wava->bar_space.w) || 38 | (wava->inner.h != wava->bar_space.h)) { 39 | wava->bar_space.w = wava->inner.w; 40 | wava->bar_space.h = wava->inner.h; 41 | pushWAVAEventStack(handle->events, WAVA_RESIZE); 42 | } 43 | } 44 | 45 | // placeholder, as it literally does nothing atm 46 | EXP_FUNC void wava_cairo_module_clear (wava_cairo_module_handle* handle) { 47 | UNUSED(handle); 48 | } 49 | 50 | EXP_FUNC void wava_cairo_module_draw_region(wava_cairo_module_handle* handle) { 51 | UNUSED(handle); 52 | } 53 | 54 | // no matter what condition, this ensures a safe write 55 | EXP_FUNC void wava_cairo_module_draw_safe (wava_cairo_module_handle* handle) { 56 | UNUSED(handle); 57 | } 58 | 59 | // assume that the entire screen's being overwritten 60 | EXP_FUNC void wava_cairo_module_draw_full (wava_cairo_module_handle* handle) { 61 | WAVA *wava = handle->wava; 62 | WAVA_CONFIG *conf = &wava->conf; 63 | 64 | cairo_set_source_rgba(handle->cr, 65 | ARGB_R_32(conf->col)/255.0, 66 | ARGB_G_32(conf->col)/255.0, 67 | ARGB_B_32(conf->col)/255.0, 68 | conf->foreground_opacity); 69 | 70 | float intensity = 0.0; 71 | 72 | for(register uint32_t i=0; ibars; i++) { 73 | // the not so, speed part 74 | // intensity has a low-freq bias as they are more "physical" 75 | float bar_percentage = (float)(wava->f[i]-1)/(float)conf->h; 76 | if(bar_percentage > 0.0) { 77 | intensity+=powf(bar_percentage, 78 | (float)2.0*(float)i/(float)wava->bars); 79 | } 80 | } 81 | 82 | // since im not bothering to do the math, this'll do 83 | // - used to balance out intensity across various number of bars 84 | intensity /= wava->bars; 85 | 86 | cairo_set_source_rgba(handle->cr, 87 | ARGB_R_32(conf->bgcol)/255.0, 88 | ARGB_G_32(conf->bgcol)/255.0, 89 | ARGB_B_32(conf->bgcol)/255.0, 90 | conf->background_opacity*(1.0-intensity)); 91 | cairo_set_operator(handle->cr, CAIRO_OPERATOR_SOURCE); 92 | cairo_paint(handle->cr); 93 | } 94 | 95 | EXP_FUNC void wava_cairo_module_cleanup (wava_cairo_module_handle* handle) { 96 | UNUSED(handle); 97 | } 98 | 99 | // ionotify fun 100 | EXP_FUNC void wava_cairo_module_ionotify_callback 101 | (WAVA_IONOTIFY_EVENT event, 102 | const char* filename, 103 | int id, 104 | WAVA* wava) { 105 | UNUSED(event); 106 | UNUSED(filename); 107 | UNUSED(id); 108 | UNUSED(wava); 109 | } 110 | -------------------------------------------------------------------------------- /src/shared/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAVA_SHARED_LOG_H 2 | #define __WAVA_SHARED_LOG_H 3 | 4 | // static analyser, please shut the fuck up 5 | #ifdef SOURCE_PATH_SIZE 6 | #define __FILENAME__ (__FILE__ + SOURCE_PATH_SIZE) 7 | #else 8 | #define __FILENAME__ __FILE__ 9 | #endif 10 | 11 | extern void __internal_wavaSpam (const char *func, const char *file, int line, const char *fmt, ...); 12 | extern void __internal_wavaLog (const char *func, const char *file, int line, const char *fmt, ...); 13 | extern void __internal_wavaWarn (const char *func, const char *file, int line, const char *fmt, ...); 14 | extern void __internal_wavaError(const char *func, const char *file, int line, const char *fmt, ...); 15 | extern void __internal_wavaDie (void); 16 | 17 | #ifdef DEBUG 18 | #define wavaSpam(fmt, ...) __internal_wavaSpam (__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); 19 | #define wavaLog(fmt, ...) __internal_wavaLog (__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); 20 | #else 21 | #define wavaSpam(fmt, ...) /** nothing lol **/ 22 | #define wavaLog(fmt, ...) /** nothing lol **/ 23 | #endif 24 | 25 | #define wavaWarn(fmt, ...) __internal_wavaWarn (__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); 26 | #define wavaError(fmt, ...) __internal_wavaError(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); 27 | #define wavaBail(fmt, ...) { \ 28 | __internal_wavaError(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 29 | __internal_wavaDie(); \ 30 | } 31 | 32 | #define wavaReturnSpam(return_val, fmt, ...) { \ 33 | __internal_wavaSpam(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 34 | return return_val; \ 35 | } 36 | #define wavaReturnLog(return_val, fmt, ...) { \ 37 | __internal_wavaLog(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 38 | return return_val; \ 39 | } 40 | #define wavaReturnWarn(return_val, fmt, ...) { \ 41 | __internal_wavaWarn(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 42 | return return_val; \ 43 | } 44 | #define wavaReturnError(return_val, fmt, ...) { \ 45 | __internal_wavaError(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 46 | return return_val; \ 47 | } 48 | 49 | 50 | #define wavaReturnSpamCondition(condition, return_val, fmt, ...) { \ 51 | if(condition) { \ 52 | __internal_wavaSpam(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 53 | return return_val; \ 54 | } \ 55 | } 56 | #define wavaReturnLogCondition(condition, return_val, fmt, ...) { \ 57 | if(condition) { \ 58 | __internal_wavaLog(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 59 | return return_val; \ 60 | } \ 61 | } 62 | #define wavaReturnWarnCondition(condition, return_val, fmt, ...) { \ 63 | if(condition) { \ 64 | __internal_wavaWarn(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 65 | return return_val; \ 66 | } \ 67 | } 68 | #define wavaReturnErrorCondition(condition, return_val, fmt, ...) { \ 69 | if(condition) { \ 70 | __internal_wavaError(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 71 | return return_val; \ 72 | } \ 73 | } 74 | 75 | #define wavaSpamCondition(condition, fmt, ...) \ 76 | if((condition)) { __internal_wavaSpam(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); } 77 | #define wavaLogCondition(condition, fmt, ...) \ 78 | if((condition)) { __internal_wavaLog(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); } 79 | #define wavaWarnCondition(condition, fmt, ...) \ 80 | if((condition)) { __internal_wavaWarn(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); } 81 | #define wavaErrorCondition(condition, fmt, ...) \ 82 | if((condition)) { __internal_wavaError(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); } 83 | #define wavaBailCondition(condition, fmt, ...) { \ 84 | if((condition)) { \ 85 | __internal_wavaError(__func__, __FILENAME__, __LINE__, fmt, ## __VA_ARGS__); \ 86 | __internal_wavaDie(); \ 87 | } \ 88 | } 89 | 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/shm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef SHM 7 | #define SHM 8 | #endif 9 | 10 | #include "shm.h" 11 | #include "main.h" 12 | 13 | const struct wl_callback_listener wl_surface_frame_listener = { 14 | .done = wl_surface_frame_done, 15 | }; 16 | 17 | void wl_surface_frame_done(void *data, struct wl_callback *cb, 18 | uint32_t time) { 19 | UNUSED(time); 20 | 21 | struct waydata *wd = data; 22 | UNUSED(wd); 23 | 24 | wl_callback_destroy(cb); 25 | 26 | wl_surface_damage_buffer(wd->surface, 0, 0, INT32_MAX, INT32_MAX); 27 | 28 | #ifdef SHM 29 | update_frame(wd); 30 | 31 | // when using non-EGL wayland, the framerate is controlled by the wl_callbacks 32 | cb = wl_surface_frame(wd->surface); 33 | wl_callback_add_listener(cb, &wl_surface_frame_listener, wd); 34 | 35 | #endif 36 | wl_surface_commit(wd->surface); 37 | } 38 | 39 | uint32_t wayland_color_blend(uint32_t color, uint8_t alpha) { 40 | uint8_t red = ((color >> 16 & 0xff) | (color >> 8 & 0xff00)) * alpha / 0xff; 41 | uint8_t green = ((color >> 8 & 0xff) | (color >> 0 & 0xff00)) * alpha / 0xff; 42 | uint8_t blue = ((color >> 0 & 0xff) | (color << 8 & 0xff00)) * alpha / 0xff; 43 | return alpha<<24|red<<16|green<<8|blue; 44 | } 45 | 46 | void wl_buffer_release(void *data, struct wl_buffer *wl_buffer) { 47 | UNUSED(data); 48 | 49 | /* Sent by the compositor when it's no longer using this buffer */ 50 | wl_buffer_destroy(wl_buffer); 51 | } 52 | const struct wl_buffer_listener wl_buffer_listener = { 53 | .release = wl_buffer_release, 54 | }; 55 | 56 | struct wl_buffer *wl_create_framebuffer(struct waydata *wd) { 57 | WAVA *wava = wd->hand; 58 | 59 | int width = wava->outer.w, height = wava->outer.h; 60 | int stride = width*sizeof(uint32_t); 61 | int size = stride * height; 62 | 63 | struct wl_shm_pool *pool = wl_shm_create_pool(wd->shm.ref, wd->shm.fd, size); 64 | struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 65 | 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); 66 | wl_shm_pool_destroy(pool); 67 | 68 | wd->shm.dim.w = width; 69 | wd->shm.dim.h = height; 70 | wd->shm.dim.stride = stride; 71 | 72 | wl_buffer_add_listener(buffer, &wl_buffer_listener, wd); 73 | 74 | return buffer; 75 | } 76 | 77 | void update_frame(struct waydata *wd) { 78 | //WAVA_CONFIG *p = &wd->s->conf; 79 | 80 | // Update frame and inform wayland 81 | struct wl_buffer *buffer = wl_create_framebuffer(wd); 82 | wl_surface_attach(wd->surface, buffer, 0, 0); 83 | //wl_surface_damage_buffer(wavaWLSurface, 0, 0, INT32_MAX, INT32_MAX); 84 | wl_surface_commit(wd->surface); 85 | } 86 | 87 | void reallocSHM(struct waydata *wd) { 88 | WAVA *hand = wd->hand; 89 | 90 | munmap(wd->shm.buffer, wd->shm.max_size); 91 | 92 | uint32_t size = hand->outer.w * 93 | hand->outer.h * 94 | sizeof(uint32_t); 95 | if(size > wd->shm.max_size) { 96 | wd->shm.max_size = size; 97 | wavaErrorCondition(ftruncate(wd->shm.fd, size) == -1, 98 | "%s", strerror(errno)); 99 | } 100 | 101 | wd->shm.dim.w = hand->outer.w; 102 | wd->shm.dim.h = hand->outer.h; 103 | wd->shm.dim.stride = hand->outer.w*sizeof(uint32_t); 104 | 105 | wd->shm.buffer = mmap(NULL, 106 | wd->shm.max_size, 107 | PROT_READ | PROT_WRITE, 108 | MAP_SHARED, 109 | wd->shm.fd, 110 | 0); 111 | 112 | wavaBailCondition(wd->shm.buffer == MAP_FAILED, 113 | "%s", strerror(errno)); 114 | 115 | wl_surface_commit(wd->surface); 116 | } 117 | 118 | void closeSHM(struct waydata *wd) { 119 | close(wd->shm.fd); 120 | munmap(wd->shm.buffer, wd->shm.dim.stride*wd->shm.dim.h); 121 | 122 | wd->shm.fd = -1; 123 | wd->shm.buffer = NULL; 124 | } 125 | 126 | -------------------------------------------------------------------------------- /src/input/cubeb/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "shared.h" 10 | 11 | struct cubeb_data { 12 | WAVA_AUDIO *audio; 13 | double accumulator; 14 | 15 | // C-based cringe 16 | struct audio_str { 17 | char rate[32]; 18 | char channels[32]; 19 | } audio_str; 20 | 21 | long progress; 22 | bool autoconnect; 23 | } cubeb_data; 24 | 25 | char *cubeb_strerr(int error) { 26 | switch(error) { 27 | case CUBEB_OK: return "No error"; 28 | case CUBEB_ERROR: return "Unclassifed error"; 29 | case CUBEB_ERROR_INVALID_FORMAT: return "Invalid format"; 30 | case CUBEB_ERROR_INVALID_PARAMETER: return "Invalid parameter"; 31 | case CUBEB_ERROR_NOT_SUPPORTED: return "Not supported"; 32 | case CUBEB_ERROR_DEVICE_UNAVAILABLE: return "Device not available"; 33 | } 34 | return "Unknown error, probably a bug!"; 35 | } 36 | 37 | long data_cb(cubeb_stream *stm, void *data, 38 | const void * input_buffer, void * output_buffer, long nframes) { 39 | struct cubeb_data *cubeb = data; 40 | WAVA_AUDIO *audio = cubeb->audio; 41 | 42 | int16_t *in = input_buffer; 43 | 44 | for (int i = 0; i < nframes; ++i) { 45 | audio->audio_out_l[cubeb->progress] = in[i]; 46 | if(cubeb->progress < audio->inputsize) 47 | cubeb->progress++; 48 | else cubeb->progress = 0; 49 | } 50 | return nframes; 51 | } 52 | 53 | void state_cb(cubeb_stream * stm, void *data, cubeb_state state) { 54 | //wavaSpam("state=%d\n", state); 55 | } 56 | 57 | EXP_FUNC void* wavaInput(void *audiodata) { 58 | cubeb_data.audio = audiodata; 59 | cubeb_data.progress = 0; 60 | 61 | cubeb_set_log_callback(CUBEB_LOG_VERBOSE, NULL); 62 | 63 | cubeb * app_ctx; 64 | cubeb_init(&app_ctx, "WAVA", NULL); 65 | 66 | int rv; 67 | uint32_t rate; 68 | uint32_t latency_frames; 69 | uint64_t ts; 70 | 71 | rv = cubeb_get_preferred_sample_rate(app_ctx, &rate); 72 | wavaBailCondition(rv != CUBEB_OK, "Could not get preferred sample-rate: %s", cubeb_strerr(rv)); 73 | 74 | cubeb_stream_params input_params; 75 | input_params.format = CUBEB_SAMPLE_S16LE; 76 | input_params.rate = rate; 77 | input_params.channels = 1; 78 | input_params.layout = CUBEB_LAYOUT_UNDEFINED; 79 | input_params.prefs = CUBEB_STREAM_PREF_LOOPBACK; 80 | 81 | rv = cubeb_get_min_latency(app_ctx, &input_params, &latency_frames); 82 | wavaBailCondition(rv != CUBEB_OK, "Could not get minimum latency: %s", cubeb_strerr(rv)); 83 | 84 | cubeb_stream * stm; 85 | rv = cubeb_stream_init(app_ctx, &stm, "Audio capture process", 86 | NULL, &input_params, 87 | NULL, NULL, 88 | latency_frames, 89 | data_cb, state_cb, 90 | &cubeb_data); 91 | wavaBailCondition(rv != CUBEB_OK, "Could not open the stream: %s", cubeb_strerr(rv)); 92 | 93 | rv = cubeb_stream_start(stm); 94 | wavaBailCondition(rv != CUBEB_OK, "Could not start the stream: %s", cubeb_strerr(rv)); 95 | 96 | while(1) { 97 | //cubeb_stream_get_position(stm, &ts); 98 | //wavaSpam("time=%llu\n", ts); 99 | 100 | // the ideal CHAD loop, thanks mozilla 101 | wavaSleep(5, 0); 102 | if(cubeb_data.audio->terminate == 1) break; 103 | } 104 | 105 | rv = cubeb_stream_stop(stm); 106 | wavaBailCondition(rv != CUBEB_OK, "Could not stop the stream: %s", cubeb_strerr(rv)); 107 | 108 | cubeb_stream_destroy(stm); 109 | cubeb_destroy(app_ctx); 110 | 111 | return 0; 112 | } 113 | 114 | EXP_FUNC void wavaInputLoadConfig(WAVA *wava) { 115 | WAVA_AUDIO *audio = &wava->audio; 116 | wava_config_source config = wava->default_config.config; 117 | 118 | // default to ignore or change to keep 'em searching 119 | audio->source = (char*)wavaConfigGetString(config, "input", "source", "default"); 120 | } 121 | 122 | -------------------------------------------------------------------------------- /src/output/shared/util/media/artwork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define STB_IMAGE_IMPLEMENTATION 6 | #include 7 | 8 | #include "shared.h" 9 | 10 | #include "artwork.h" 11 | 12 | typedef enum uri_type { 13 | URI_TYPE_DOWNLOAD, 14 | URI_TYPE_FILE, 15 | URI_TYPE_AUDIO_FILE 16 | } uri_type; 17 | 18 | size_t wava_util_download_artwork(void *ptr, size_t size, size_t nmemb, 19 | struct artwork *artwork) { 20 | if(artwork->file_data == NULL) { 21 | artwork->file_data = malloc(size*nmemb); 22 | artwork->size = size*nmemb; 23 | memcpy(artwork->file_data, ptr, nmemb*size); 24 | } else { 25 | void *new = realloc(artwork->file_data, artwork->size+nmemb*size); 26 | artwork->file_data = new; 27 | memcpy(&artwork->file_data[artwork->size], ptr, nmemb*size); 28 | artwork->size += size*nmemb; 29 | } 30 | 31 | return nmemb*size; 32 | } 33 | 34 | void wava_util_artwork_destroy(struct artwork *artwork) { 35 | // reset artwork if already allocated 36 | if(artwork->ready) { 37 | // needs to be set early because stupid computers 38 | artwork->ready = false; 39 | free(artwork->file_data); 40 | free(artwork->image_data); 41 | } 42 | artwork->ready = false; 43 | artwork->size = 0; 44 | artwork->image_data = NULL; 45 | artwork->file_data = NULL; 46 | } 47 | 48 | bool wava_util_artwork_update_by_download(const char *url, 49 | struct artwork *artwork, CURL *curl) { 50 | CURLcode res; 51 | 52 | curl_easy_setopt(curl, CURLOPT_URL, url); 53 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, artwork); 54 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, 55 | wava_util_download_artwork); 56 | 57 | res = curl_easy_perform(curl); 58 | 59 | if(res != CURLE_OK) { 60 | wavaLog("Failed to download '%s'", url); 61 | return true; 62 | } 63 | 64 | return false; 65 | } 66 | 67 | bool wava_util_artwork_update_by_file(const char *url, struct artwork *artwork) { 68 | const char *filename = &url[strlen(URI_HEADER_FILE)]; 69 | FILE *fp = fopen(filename, "rb"); 70 | 71 | wavaReturnWarnCondition(fp == NULL, true, "Failed to open '%s'", filename); 72 | 73 | fseek(fp, 0, SEEK_END); 74 | size_t size = ftell(fp); 75 | fseek(fp, 0, SEEK_SET); 76 | 77 | artwork->file_data = malloc(size); 78 | fread(artwork->file_data, size, 1, fp); 79 | artwork->size = size; 80 | 81 | fclose(fp); 82 | 83 | return false; 84 | } 85 | 86 | void wava_util_artwork_update(const char *url, 87 | struct artwork *artwork, CURL *curl) { 88 | wava_util_artwork_destroy(artwork); 89 | 90 | uri_type type = URI_TYPE_DOWNLOAD; 91 | 92 | if(strncmp(url, URI_HEADER_FILE, strlen(URI_HEADER_FILE)) == 0) 93 | type = URI_TYPE_FILE; 94 | 95 | if(strncmp(url, URI_HEADER_MUSIC, strlen(URI_HEADER_MUSIC)) == 0) 96 | type = URI_TYPE_AUDIO_FILE; 97 | 98 | bool fail; 99 | switch(type) { 100 | case URI_TYPE_FILE: 101 | fail = wava_util_artwork_update_by_file(url, artwork); 102 | break; 103 | case URI_TYPE_DOWNLOAD: 104 | fail = wava_util_artwork_update_by_download(url, artwork, curl); 105 | break; 106 | case URI_TYPE_AUDIO_FILE: 107 | fail = wava_util_artwork_update_by_audio_file(url, artwork); 108 | break; 109 | } 110 | if(fail) 111 | return; 112 | 113 | if(artwork->size == 0) { 114 | wavaLog("Failed to load '%s'", url); 115 | return; 116 | } 117 | 118 | int w, h, c; 119 | artwork->image_data = stbi_load_from_memory( 120 | artwork->file_data, artwork->size, &w, &h, &c, 4); 121 | 122 | // update size and color info 123 | artwork->w = w; 124 | artwork->h = h; 125 | artwork->c = c; 126 | 127 | // correct color order 128 | for(unsigned char *ptr = artwork->image_data; 129 | ptr < artwork->image_data+w*h*4; ptr+=4) { 130 | ptr[0] ^= ptr[2]; 131 | ptr[2] ^= ptr[0]; 132 | ptr[0] ^= ptr[2]; 133 | } 134 | 135 | artwork->ready = true; 136 | } 137 | 138 | -------------------------------------------------------------------------------- /src/output/graphical_wayland/wl_output.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "gen/xdg-output-unstable-v1-client-protocol.h" 5 | #include "wl_output.h" 6 | #include "main.h" 7 | 8 | struct zxdg_output_manager_v1 *wavaXDGOutputManager; 9 | 10 | static void output_geometry(void *data, struct wl_output *output, int32_t x, 11 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, 12 | const char *make, const char *model, int32_t transform) { 13 | UNUSED(data); 14 | UNUSED(output); 15 | UNUSED(x); 16 | UNUSED(y); 17 | UNUSED(width_mm); 18 | UNUSED(height_mm); 19 | UNUSED(subpixel); 20 | UNUSED(make); 21 | UNUSED(model); 22 | UNUSED(transform); 23 | 24 | // Who cares 25 | } 26 | 27 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, 28 | int32_t width, int32_t height, int32_t refresh) { 29 | UNUSED(data); 30 | UNUSED(output); 31 | UNUSED(flags); 32 | UNUSED(width); 33 | UNUSED(height); 34 | UNUSED(refresh); 35 | // Who cares 36 | } 37 | 38 | static void output_done(void *data, struct wl_output *output) { 39 | UNUSED(data); 40 | UNUSED(output); 41 | // Who cares 42 | } 43 | 44 | static void output_scale(void *data, struct wl_output *wl_output, 45 | int32_t scale) { 46 | UNUSED(wl_output); 47 | 48 | struct wlOutput *output = data; 49 | output->scale = scale; 50 | } 51 | 52 | const struct wl_output_listener output_listener = { 53 | .geometry = output_geometry, 54 | .mode = output_mode, 55 | .done = output_done, 56 | .scale = output_scale, 57 | }; 58 | 59 | void wl_output_cleanup(struct waydata *wd) { 60 | struct wlOutput *output, *tmp; 61 | 62 | wl_list_for_each_safe(output, tmp, &wd->outputs, link) { 63 | wavaSpam("Destroying output %s", output->name); 64 | wl_list_remove(&output->link); 65 | free(output->name); 66 | free(output); 67 | } 68 | } 69 | 70 | void wl_output_init(struct waydata *wd) { 71 | wl_list_init(&wd->outputs); 72 | } 73 | 74 | struct wlOutput *wl_output_get_desired(struct waydata *wd) { 75 | struct wlOutput *output, *tmp, *lastGood; 76 | 77 | lastGood = NULL; // supress warnings by GCC 78 | 79 | wl_list_for_each_safe(output, tmp, &wd->outputs, link) { 80 | if(!strcmp(output->name, monitorName)) { 81 | return output; 82 | } else lastGood = output; 83 | } 84 | 85 | // in case none are available, just send the last display 86 | return lastGood; 87 | } 88 | 89 | 90 | // XDG_OUTPUT_HANDLE 91 | 92 | static void xdg_output_handle_logical_position(void *data, 93 | struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) { 94 | UNUSED(data); 95 | UNUSED(xdg_output); 96 | UNUSED(x); 97 | UNUSED(y); 98 | // Who cares 99 | } 100 | 101 | static void xdg_output_handle_logical_size(void *data, 102 | struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) { 103 | UNUSED(xdg_output); 104 | 105 | struct wlOutput *output = data; 106 | output->width = width; 107 | output->height = height; 108 | } 109 | 110 | static void xdg_output_handle_name(void *data, 111 | struct zxdg_output_v1 *xdg_output, const char *name) { 112 | UNUSED(xdg_output); 113 | 114 | struct wlOutput *output = data; 115 | wavaSpam("Output %s loaded with id %d", name, output->id); 116 | output->name = strdup(name); 117 | } 118 | 119 | static void xdg_output_handle_done(void *data, 120 | struct zxdg_output_v1 *xdg_output) { 121 | // Who cares 122 | UNUSED(data); 123 | UNUSED(xdg_output); 124 | } 125 | 126 | static void xdg_output_handle_description(void *data, 127 | struct zxdg_output_v1 *xdg_output, const char *description) { 128 | // Who cares 129 | UNUSED(data); 130 | UNUSED(xdg_output); 131 | UNUSED(description); 132 | } 133 | 134 | struct zxdg_output_v1_listener xdg_output_listener = { 135 | .logical_position = xdg_output_handle_logical_position, 136 | .logical_size = xdg_output_handle_logical_size, 137 | .name = xdg_output_handle_name, 138 | .description = xdg_output_handle_description, 139 | .done = xdg_output_handle_done, 140 | }; 141 | 142 | -------------------------------------------------------------------------------- /src/output/shared/util/media/media_data.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "shared.h" 7 | 8 | #include "media_data.h" 9 | 10 | #define TRACK_ID_LENGTH 1024 11 | 12 | struct media_data_thread { 13 | CURL *curl; 14 | char last_track_id[TRACK_ID_LENGTH]; 15 | long int last_timestamp; 16 | pthread_t thread; 17 | bool alive; 18 | struct media_data data; 19 | }; 20 | 21 | void media_data_update 22 | (struct media_data_thread *data) { 23 | kiss_mpris_options options; 24 | mpris_properties properties; 25 | 26 | options.player_count = 0; 27 | options.status = MPRIS_PLAYER_ANY_PLAYING; 28 | properties = get_mpris_player_status(&options); 29 | 30 | data->last_timestamp = wavaGetTime(); 31 | 32 | bool should_update = false; 33 | 34 | // check track ID for mismatches 35 | if(strncmp(properties.metadata.track_id, data->last_track_id, TRACK_ID_LENGTH)) 36 | should_update = true; 37 | 38 | // check album name for mismatches 39 | if(strncmp(properties.metadata.album, data->data.album, MUSIC_DATA_STRING_LENGTH)) 40 | should_update = true; 41 | 42 | // check song artist for mismatches 43 | if(strncmp(properties.metadata.artist, data->data.artist, MUSIC_DATA_STRING_LENGTH)) 44 | should_update = true; 45 | 46 | // check song title for mismatches 47 | if(strncmp(properties.metadata.title, data->data.title, MUSIC_DATA_STRING_LENGTH)) 48 | should_update = true; 49 | 50 | // check song genre for mismatches 51 | if(strncmp(properties.metadata.genre, data->data.genre, MUSIC_DATA_STRING_LENGTH)) 52 | should_update = true; 53 | 54 | if(should_update) { 55 | // this complicated mess turns empty art_url's with a file attached to said file 56 | if(strlen(properties.metadata.art_url) == 0 && 57 | strncmp(properties.metadata.url, URI_HEADER_FILE, 58 | strlen(URI_HEADER_FILE)) == 0) { 59 | strncpy(properties.metadata.art_url, 60 | URI_HEADER_MUSIC, MUSIC_DATA_STRING_LENGTH); 61 | strncat(properties.metadata.art_url, 62 | &properties.metadata.url[strlen(URI_HEADER_FILE)], 63 | MUSIC_DATA_STRING_LENGTH-1); 64 | } 65 | 66 | wava_util_artwork_update(properties.metadata.art_url, 67 | &data->data.cover, data->curl); 68 | 69 | strncpy(data->last_track_id, properties.metadata.track_id, TRACK_ID_LENGTH); 70 | 71 | strncpy(data->data.album, properties.metadata.album, MUSIC_DATA_STRING_LENGTH); 72 | strncpy(data->data.artist, properties.metadata.artist, MUSIC_DATA_STRING_LENGTH); 73 | strncpy(data->data.title, properties.metadata.title, MUSIC_DATA_STRING_LENGTH); 74 | strncpy(data->data.genre, properties.metadata.genre, MUSIC_DATA_STRING_LENGTH); 75 | 76 | data->data.version++; 77 | } 78 | } 79 | 80 | void* media_data_thread_runner(void* ptr) { 81 | struct media_data_thread *data = ptr; 82 | data->curl = curl_easy_init(); 83 | 84 | while(data->alive) { 85 | media_data_update(data); 86 | 87 | // sleep for 1 second but interruptable every 50ms 88 | for(int i = 0; i < 10 && data->alive; i++) { 89 | wavaSleep(100, 0); 90 | } 91 | } 92 | 93 | wava_util_artwork_destroy(&data->data.cover); 94 | curl_easy_cleanup(data->curl); 95 | return NULL; 96 | } 97 | 98 | struct media_data * 99 | wava_util_media_data_thread_data(struct media_data_thread *thread) { 100 | return &thread->data; 101 | } 102 | 103 | struct media_data_thread * 104 | wava_util_media_data_thread_create(void) { 105 | struct media_data_thread *value; 106 | MALLOC_SELF(value, 1); 107 | 108 | value->data.cover.ready = false; 109 | value->data.version = 0; 110 | 111 | value->alive = true; 112 | pthread_create(&value->thread, NULL, media_data_thread_runner, value); 113 | 114 | return value; 115 | } 116 | 117 | void wava_util_media_data_thread_destroy(struct media_data_thread *data) { 118 | data->alive = false; 119 | pthread_join(data->thread, NULL); 120 | free(data); 121 | } 122 | 123 | -------------------------------------------------------------------------------- /src/output/default/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "shared.h" 8 | 9 | #ifdef WAYLAND 10 | bool am_i_wayland(void); 11 | #endif 12 | 13 | #ifdef X11 14 | bool am_i_x11(void); 15 | #endif 16 | 17 | #ifdef WINDOWS 18 | bool am_i_win32(void); 19 | #endif 20 | 21 | #ifdef SDL2 22 | bool am_i_sdl2(void); 23 | #endif 24 | 25 | typedef struct system { 26 | bool (*test_func)(void); 27 | 28 | // if these strings are empty, that means that the system is not supported 29 | char *cairo; 30 | char *opengl; 31 | } sys; 32 | 33 | sys systems[] = { 34 | #ifdef WAYLAND 35 | { .test_func = am_i_wayland, .cairo = "wayland_cairo", .opengl = "wayland_opengl" }, 36 | #endif 37 | #ifdef WINDOWS 38 | { .test_func = am_i_win32, .cairo = "win_cairo", .opengl = "win_opengl" }, 39 | #endif 40 | #ifdef X11 41 | { .test_func = am_i_x11, .cairo = "x11_cairo", .opengl = "x11_opengl" }, 42 | #endif 43 | #ifdef SDL2 44 | { .test_func = am_i_sdl2, .cairo = NULL, .opengl = "sdl2_opengl" }, 45 | #endif 46 | }; 47 | 48 | struct functions { 49 | void (*cleanup) (WAVA *wava); 50 | int (*init) (WAVA *wava); 51 | void (*clear) (WAVA *wava); 52 | int (*apply) (WAVA *wava); 53 | XG_EVENT (*handle_input)(WAVA *wava); 54 | void (*draw) (WAVA *wava); 55 | void (*load_config) (WAVA *wava); 56 | } functions; 57 | 58 | WAVAMODULE *module; 59 | 60 | EXP_FUNC void wavaOutputLoadConfig(WAVA *wava) { 61 | int supported_systems = sizeof(systems)/sizeof(sys); 62 | 63 | char *system = NULL; 64 | int i = 0; 65 | 66 | wava_output_module_default_find_any_remaining: 67 | for(; i < supported_systems; i++) { 68 | if(systems[i].test_func()) { 69 | #ifdef CAIRO 70 | system = systems[i].cairo; 71 | if(system != NULL) 72 | break; 73 | #endif 74 | #ifdef OPENGL 75 | system = systems[i].opengl; 76 | if(system != NULL) 77 | break; 78 | #endif 79 | } 80 | } 81 | 82 | wavaBailCondition(system == NULL, 83 | "No supported output methods found for '%s'", 84 | #if defined(CAIRO) 85 | "cairo" 86 | #elif defined(OPENGL) 87 | "opengl" 88 | #else 89 | #error "Build broke, pls fix!" 90 | "wtf" 91 | #endif 92 | ); 93 | 94 | module = wava_module_output_load(system); 95 | if(!wava_module_valid(module)) { 96 | // execution halts here if the condition fails btw 97 | wavaBailCondition(i == supported_systems-1, 98 | "wava module failed to load (definitely bug): %s", 99 | wava_module_error_get(module)); 100 | 101 | wavaLog("wava module failed to load (probably bug): %s", 102 | wava_module_error_get(module)); 103 | goto wava_output_module_default_find_any_remaining; 104 | } 105 | 106 | 107 | functions.cleanup = wava_module_symbol_address_get(module, "wavaOutputCleanup"); 108 | functions.init = wava_module_symbol_address_get(module, "wavaInitOutput"); 109 | functions.clear = wava_module_symbol_address_get(module, "wavaOutputClear"); 110 | functions.apply = wava_module_symbol_address_get(module, "wavaOutputApply"); 111 | functions.handle_input = wava_module_symbol_address_get(module, "wavaOutputHandleInput"); 112 | functions.draw = wava_module_symbol_address_get(module, "wavaOutputDraw"); 113 | functions.load_config = wava_module_symbol_address_get(module, "wavaOutputLoadConfig"); 114 | 115 | functions.load_config(wava); 116 | } 117 | 118 | EXP_FUNC void wavaOutputCleanup(WAVA *wava) { 119 | functions.cleanup(wava); 120 | 121 | wava_module_free(module); 122 | } 123 | 124 | EXP_FUNC int wavaInitOutput(WAVA *wava) { 125 | return functions.init(wava); 126 | } 127 | 128 | EXP_FUNC void wavaOutputClear(WAVA *wava) { 129 | functions.clear(wava); 130 | } 131 | 132 | EXP_FUNC int wavaOutputApply(WAVA *wava) { 133 | return functions.apply(wava); 134 | } 135 | 136 | EXP_FUNC XG_EVENT wavaOutputHandleInput(WAVA *wava) { 137 | return functions.handle_input(wava); 138 | } 139 | 140 | EXP_FUNC void wavaOutputDraw(WAVA *wava) { 141 | functions.draw(wava); 142 | } 143 | 144 | -------------------------------------------------------------------------------- /src/shared/module/unix.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "shared.h" 8 | #include "shared/io/unix.h" 9 | 10 | typedef struct wavamodule { 11 | char *name; 12 | void **moduleHandle; 13 | char *path; 14 | } WAVAMODULE; 15 | 16 | char *LIBRARY_EXTENSION = ".so"; 17 | 18 | EXP_FUNC void wava_module_free(WAVAMODULE *module) { 19 | dlclose(module->moduleHandle); 20 | module->moduleHandle = 0; 21 | free(module->name); 22 | free(module->path); 23 | free(module); 24 | } 25 | 26 | EXP_FUNC WAVAMODULE *wava_module_load(char *name) { 27 | #ifdef UNIX_INDEPENDENT_PATHS 28 | char *prefix = find_prefix(); 29 | #else 30 | char *prefix = PREFIX; 31 | #endif 32 | 33 | // make this static size :) 34 | char new_name[MAX_PATH]; 35 | 36 | // Security check 37 | for(size_t i=0; imoduleHandle = dlopen(new_name, RTLD_NOW); 60 | module->name = strdup(name); 61 | 62 | // don't ask, this is unexplainable C garbage at work again 63 | module->path = strdup(new_name); 64 | 65 | wavaLog("Module loaded '%s' loaded at %p", 66 | module->name, module->moduleHandle); 67 | 68 | #ifdef UNIX_INDEPENDENT_PATHS 69 | //free(prefix); 70 | #endif 71 | 72 | return module; 73 | } 74 | 75 | // because of stupidity this is not a entire path instead, 76 | // it's supposed to take in the path without the extension 77 | // 78 | // the extension gets added here, just as a FYI 79 | EXP_FUNC WAVAMODULE *wava_module_path_load(char *path) { 80 | size_t offset; 81 | for(offset = strlen(path); offset > 0; offset--) { 82 | if(path[offset-1] == '/') 83 | break; 84 | } 85 | 86 | char *new_name = &path[offset]; 87 | char full_path[strlen(path)+strlen(LIBRARY_EXTENSION)+1]; 88 | strcpy(full_path, path); 89 | strcat(full_path, LIBRARY_EXTENSION); 90 | 91 | WAVAMODULE *module = (WAVAMODULE*) malloc(sizeof(WAVAMODULE)); 92 | module->moduleHandle = dlopen(full_path, RTLD_NOW); 93 | module->name = strdup(new_name); 94 | module->path = strdup(full_path); 95 | 96 | wavaLog("Module loaded '%s' loaded at %p", 97 | module->name, module->moduleHandle); 98 | 99 | return module; 100 | } 101 | 102 | EXP_FUNC char *wava_module_error_get(WAVAMODULE *module) { 103 | UNUSED(module); 104 | return dlerror(); 105 | } 106 | 107 | EXP_FUNC void *wava_module_symbol_address_get(WAVAMODULE *module, char *symbol) { 108 | void *address = dlsym(module->moduleHandle, symbol); 109 | 110 | // the program would crash with an NULL pointer error anyway 111 | wavaBailCondition(!address, "Failed to find symbol '%s' in module '%s'", 112 | symbol, module->name); 113 | 114 | wavaLog("Symbol '%s' of '%s' found at: %p", 115 | symbol, module->name, address); 116 | 117 | return address; 118 | } 119 | 120 | EXP_FUNC bool wava_module_valid(WAVAMODULE *module) { 121 | if(module->moduleHandle) 122 | return 1; 123 | else 124 | return 0; 125 | } 126 | 127 | EXP_FUNC const char *wava_module_path_get(WAVAMODULE *module) { 128 | // prevent NULL-pointer exception 129 | if(module == NULL) 130 | return NULL; 131 | 132 | return module->path; 133 | } 134 | 135 | EXP_FUNC const char *wava_module_extension_get(void) { 136 | return LIBRARY_EXTENSION; 137 | } 138 | 139 | EXP_FUNC void wava_module_generate_filename(char *name, 140 | const char *prefix, char *result) { 141 | sprintf(result, "%s_%s%s", prefix, name, LIBRARY_EXTENSION); 142 | return; 143 | } 144 | -------------------------------------------------------------------------------- /src/shared/io/unix.c: -------------------------------------------------------------------------------- 1 | #ifdef __unix__ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifndef SSIZE_MAX 15 | #define SSIZE_MAX ((ssize_t)(SIZE_MAX>>1)) 16 | #endif 17 | 18 | /* 19 | * Shamelessly stolen from: https://github.com/datenwolf/binreloc/blob/master/binreloc.c 20 | * 21 | * Original maintainer: Wolfgang 'datenwolf' Draxinger 22 | * Licensed with WTFPL 23 | */ 24 | 25 | static char *find_exe(void) 26 | { 27 | char *path, *path2, *line, *result; 28 | size_t buf_size; 29 | ssize_t size; 30 | struct stat stat_buf; 31 | FILE *f; 32 | 33 | /* Read from /proc/self/exe (symlink) */ 34 | if (sizeof (path) > SSIZE_MAX) 35 | buf_size = SSIZE_MAX - 1; 36 | else 37 | buf_size = PATH_MAX - 1; 38 | path = (char *) malloc (buf_size); 39 | if (path == NULL) { 40 | return NULL; 41 | } 42 | path2 = (char *) malloc (buf_size); 43 | if (path2 == NULL) { 44 | free (path); 45 | return NULL; 46 | } 47 | 48 | strncpy (path2, "/proc/self/exe", buf_size - 1); 49 | 50 | while (1) { 51 | int i; 52 | 53 | size = readlink (path2, path, buf_size - 1); 54 | if (size == -1) { 55 | /* Error. */ 56 | free (path2); 57 | break; 58 | } 59 | 60 | /* readlink() success. */ 61 | path[size] = '\0'; 62 | 63 | /* Check whether the symlink's target is also a symlink. 64 | * We want to get the final target. */ 65 | i = stat (path, &stat_buf); 66 | if (i == -1) { 67 | /* Error. */ 68 | free (path2); 69 | break; 70 | } 71 | 72 | /* stat() success. */ 73 | if (!S_ISLNK (stat_buf.st_mode)) { 74 | /* path is not a symlink. Done. */ 75 | free (path2); 76 | return path; 77 | } 78 | 79 | /* path is a symlink. Continue loop and resolve this. */ 80 | strncpy (path, path2, buf_size - 1); 81 | } 82 | 83 | 84 | /* readlink() or stat() failed; this can happen when the program is 85 | * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ 86 | 87 | buf_size = PATH_MAX + 128; 88 | line = (char *) realloc (path, buf_size); 89 | if (line == NULL) { 90 | /* Cannot allocate memory. */ 91 | free (path); 92 | return NULL; 93 | } 94 | 95 | f = fopen ("/proc/self/maps", "r"); 96 | if (f == NULL) { 97 | free (line); 98 | return NULL; 99 | } 100 | 101 | /* The first entry should be the executable name. */ 102 | result = fgets (line, (int) buf_size, f); 103 | if (result == NULL) { 104 | fclose (f); 105 | free (line); 106 | return NULL; 107 | } 108 | 109 | /* Get rid of newline character. */ 110 | buf_size = strlen (line); 111 | if (buf_size <= 0) { 112 | /* Huh? An empty string? */ 113 | fclose (f); 114 | free (line); 115 | return NULL; 116 | } 117 | if (line[buf_size - 1] == 10) 118 | line[buf_size - 1] = 0; 119 | 120 | /* Extract the filename; it is always an absolute path. */ 121 | path = strchr (line, '/'); 122 | 123 | /* Sanity check. */ 124 | if (strstr (line, " r-xp ") == NULL || path == NULL) { 125 | fclose (f); 126 | free (line); 127 | return NULL; 128 | } 129 | 130 | path = strdup (path); 131 | free (line); 132 | fclose (f); 133 | return path; 134 | } 135 | 136 | /* Emulates glibc's strndup() */ 137 | static char * 138 | br_strndup (const char *str, size_t size) 139 | { 140 | char *result = (char *) NULL; 141 | size_t len; 142 | 143 | if (str == (const char *) NULL) 144 | return (char *) NULL; 145 | 146 | len = strlen (str); 147 | if (len == 0) 148 | return strdup (""); 149 | if (size > len) 150 | size = len; 151 | 152 | result = (char *) malloc (len + 1); 153 | memcpy (result, str, size); 154 | result[size] = '\0'; 155 | return result; 156 | } 157 | 158 | char * 159 | br_dirname (const char *path) 160 | { 161 | char *end, *result; 162 | 163 | if (path == (const char *) NULL) 164 | return (char *) NULL; 165 | 166 | end = strrchr (path, '/'); 167 | if (end == (const char *) NULL) 168 | return strdup ("."); 169 | 170 | while (end > path && *end == '/') 171 | end--; 172 | result = br_strndup (path, end - path + 1); 173 | if (result[0] == 0) { 174 | free (result); 175 | return strdup ("/"); 176 | } else 177 | return result; 178 | } 179 | 180 | char * 181 | find_prefix(void) { 182 | char *exe = find_exe(); 183 | char *dir1 = br_dirname(exe); 184 | char *dir2 = br_dirname(dir1); 185 | free(exe); 186 | free(dir1); 187 | 188 | return dir2; 189 | } 190 | 191 | #endif 192 | 193 | -------------------------------------------------------------------------------- /src/shared/log.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "shared.h" 7 | 8 | #ifdef __linux__ 9 | #include 10 | #endif 11 | 12 | // internal stuff below 13 | 14 | enum WAVA_MESSAGE_TYPE { 15 | WAVA_LOG_ERROR, WAVA_LOG_WARN, WAVA_LOG_NORM, WAVA_LOG_SPAM 16 | }; 17 | 18 | static void __internal_wavaMsgHnd(enum WAVA_MESSAGE_TYPE mes, const char *fmt, 19 | const char *func, const char *file, int line, va_list list) { 20 | 21 | // please don't let this be a memory bug 22 | char newFmt[512]; 23 | 24 | FILE *output = stdout; 25 | 26 | bool stack_trace = false; 27 | bool debug_details = false; 28 | bool ignore_spam = true; 29 | char *indicator = "[BUG!FIXTHISRIGHTTHEFUCKNOW]"; // ideally never shown 30 | 31 | if(getenv("WAVA_DEBUG")) 32 | debug_details = true; 33 | 34 | if(getenv("WAVA_TRACE")) 35 | stack_trace = true; 36 | 37 | if(getenv("WAVA_SPAMMY")) 38 | ignore_spam = false; 39 | 40 | if(getenv("WAVA_SCREAM")) { 41 | debug_details = true; 42 | stack_trace = true; 43 | ignore_spam = false; 44 | } 45 | 46 | bool should_trace = false; 47 | 48 | // process message headers 49 | switch(mes) { 50 | case WAVA_LOG_ERROR: 51 | output = stderr; 52 | should_trace = true; 53 | indicator = "[ERROR]"; 54 | break; 55 | case WAVA_LOG_WARN: 56 | should_trace = true; 57 | indicator = "[WARN]"; 58 | break; 59 | case WAVA_LOG_NORM: 60 | if(ignore_spam) return; 61 | indicator = "[INFO]"; 62 | break; 63 | case WAVA_LOG_SPAM: 64 | if(ignore_spam) return; 65 | indicator = "[SPAM]"; 66 | break; 67 | } 68 | 69 | if(debug_details) 70 | snprintf(newFmt, 511, "%s %s at %s:%d - %s\n", indicator, func, file, line, fmt); 71 | else 72 | snprintf(newFmt, 511, "%s\n", fmt); 73 | 74 | vfprintf(output, newFmt, list); 75 | 76 | // add stack traces for better debugging 77 | if(stack_trace && should_trace) { 78 | #ifdef __linux__ 79 | void *stack_pointers[12]; 80 | int stack_lenght = 12; 81 | char **stack_names; 82 | 83 | stack_lenght = backtrace(stack_pointers, stack_lenght); 84 | 85 | stack_names = backtrace_symbols(stack_pointers, stack_lenght); 86 | 87 | // skip the first two functions as they are part of the logging system itself 88 | for(int i=2; i 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "shared.h" 9 | 10 | typedef struct wavamodule { 11 | char *name; 12 | char *path; 13 | HMODULE moduleHandle; 14 | DWORD error; 15 | } WAVAMODULE; 16 | 17 | char *LIBRARY_EXTENSION = ".dll"; 18 | 19 | EXP_FUNC char *wava_module_error_get(WAVAMODULE *module) { 20 | char *message; 21 | FormatMessage( 22 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 23 | FORMAT_MESSAGE_FROM_SYSTEM | 24 | FORMAT_MESSAGE_IGNORE_INSERTS, 25 | NULL, 26 | module->error, 27 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 28 | (LPTSTR) &message, 29 | 0, NULL); 30 | return message; 31 | } 32 | 33 | EXP_FUNC bool wava_module_valid(WAVAMODULE *module) { 34 | if(module->moduleHandle) 35 | return 1; 36 | else 37 | return 0; 38 | } 39 | 40 | EXP_FUNC void *wava_module_symbol_address_get(WAVAMODULE *module, char *symbol) { 41 | void *addr = GetProcAddress(module->moduleHandle, symbol); 42 | 43 | if(addr == NULL) { 44 | int error = GetLastError(); 45 | char *message; 46 | FormatMessage( 47 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 48 | FORMAT_MESSAGE_FROM_SYSTEM | 49 | FORMAT_MESSAGE_IGNORE_INSERTS, 50 | NULL, 51 | error, 52 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 53 | (LPTSTR) &message, 54 | 0, NULL ); 55 | 56 | wavaBail("Finding symbol '%s' in '%s' failed! Code %x\n" 57 | "Message: %s", symbol, module->name, error, message); 58 | } 59 | 60 | return addr; 61 | } 62 | 63 | EXP_FUNC WAVAMODULE *wava_module_load(char *name) { 64 | // hacker prevention system 9000 65 | for(u32 i=0; iname = strdup(name); 75 | module->moduleHandle = LoadLibrary(new_name); 76 | module->error = GetLastError(); 77 | 78 | if(module->moduleHandle) // if loading is done, we are successful 79 | return module; 80 | 81 | // Windows uses widechars internally 82 | WCHAR wpath[MAX_PATH]; 83 | char *path = malloc(MAX_PATH); 84 | 85 | // Get path of where the executable is installed 86 | HMODULE hModule = GetModuleHandleW(NULL); 87 | GetModuleFileNameW(hModule, wpath, MAX_PATH); 88 | wcstombs(path, wpath, MAX_PATH); 89 | 90 | // remove program filename from the path 91 | for(int i=strlen(path)-1; i>0; i--) { 92 | if(path[i-1] == '\\') { 93 | path[i] = '\0'; 94 | break; 95 | } 96 | } 97 | 98 | // append new filename to path 99 | strcat(path, new_name); 100 | 101 | // try again 102 | module->moduleHandle = LoadLibrary(path); 103 | module->error = GetLastError(); 104 | module->path = path; 105 | 106 | return module; // if it failed WAVA would know (no error checks needed) 107 | } 108 | 109 | // because of stupidity this is not a entire path instead, 110 | // it's supposed to take in the path without the extension 111 | // 112 | // the extension gets added here, just as a FYI 113 | EXP_FUNC WAVAMODULE *wava_module_path_load(char *path) { 114 | size_t offset; 115 | for(offset = strlen(path); offset > 0; offset--) { 116 | if(path[offset-1] == '\\') 117 | break; 118 | } 119 | 120 | char *new_name = &path[offset]; 121 | char full_path[strlen(path)+strlen(LIBRARY_EXTENSION)+1]; 122 | strcpy(full_path, path); 123 | strcat(full_path, LIBRARY_EXTENSION); 124 | 125 | WAVAMODULE *module = (WAVAMODULE*) malloc(sizeof(WAVAMODULE)); 126 | module->moduleHandle = LoadLibrary(full_path); 127 | module->error = GetLastError(); 128 | module->name = strdup(new_name); 129 | module->path = strdup(full_path); 130 | 131 | wavaLog("Module loaded '%s' loaded at %p", 132 | module->name, module->moduleHandle); 133 | 134 | return module; 135 | } 136 | 137 | EXP_FUNC void wava_module_free(WAVAMODULE *module) { 138 | FreeLibrary(module->moduleHandle); 139 | free(module->name); 140 | free(module->path); 141 | free(module); 142 | } 143 | 144 | EXP_FUNC const char *wava_module_path_get(WAVAMODULE *module) { 145 | // prevent NULL-pointer exception 146 | if(module == NULL) 147 | return NULL; 148 | 149 | return module->path; 150 | } 151 | 152 | EXP_FUNC const char *wava_module_extension_get(void) { 153 | return LIBRARY_EXTENSION; 154 | } 155 | 156 | EXP_FUNC void wava_module_generate_filename(char *name, 157 | const char *prefix, char *result) { 158 | sprintf(result, "%s_%s%s", prefix, name, LIBRARY_EXTENSION); 159 | return; 160 | } 161 | --------------------------------------------------------------------------------