Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 96f97d81df | |||
| 365fee352e | |||
| 1b3d6464de | |||
| bdaf53e259 | |||
| 37a492d00d | |||
| 06d175c4fd | |||
| 7b9f5ca032 | |||
| 6abf050bcc | |||
| 28b87d316a | |||
| adc520bc8b | |||
| d4565fa507 | |||
| 25b7134a43 | |||
| 7da4f27e13 | |||
| 26c90ec928 | |||
| e982c9214d | |||
| d640017136 | |||
| 3aaefc3174 |
@@ -0,0 +1,74 @@
|
||||
name: Clang Build CI
|
||||
|
||||
concurrency:
|
||||
group: build-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/build.yml'
|
||||
- 'src/*.c'
|
||||
- 'src/*.h'
|
||||
- 'configure.ac'
|
||||
- 'Makefile.am'
|
||||
|
||||
env:
|
||||
GCC_ARGS: src/*.c src/*.h -lglfw -lGL -lm -lasound -Wno-format-truncation -Iinclude hashmap.c/hashmap.c log.c/src/log.c -DGLFW_INCLUDE_NONE -DGLFW_NATIVE_INCLUDE_NONE
|
||||
GCC_ARGS_VIDEO: -DGLFW_EXPOSE_NATIVE_EGL -DVIDEO_IN
|
||||
PACKAGES: "libglfw3-dev libgl-dev libasound2-dev"
|
||||
PACKAGES_VIDEO: "libv4l-dev"
|
||||
TARGET: forge
|
||||
TEST_ARGS: "--help"
|
||||
|
||||
jobs:
|
||||
build-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: apt update && apt install -y $PACKAGES $PACKAGES_VIDEO
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: aclocal
|
||||
run: aclocal
|
||||
- name: autoconf
|
||||
run: autoconf
|
||||
- name: automake
|
||||
run: automake --add-missing
|
||||
- name: configure
|
||||
run: ./configure
|
||||
- name: make
|
||||
run: make
|
||||
- name: make distcheck
|
||||
run: make distcheck
|
||||
|
||||
run-no-video:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: apt update && apt install -y $PACKAGES
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: gcc
|
||||
run: mkdir -p build && gcc $GCC_ARGS -o build/$TARGET
|
||||
- name: run program
|
||||
run: ./build/$TARGET $TEST_ARGS
|
||||
|
||||
run-video:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: apt update && apt install -y $PACKAGES $PACKAGES_VIDEO
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: gcc
|
||||
run: mkdir -p build && gcc $GCC_ARGS $GCC_ARGS_VIDEO -o build/$TARGET
|
||||
- name: run program
|
||||
run: ./build/$TARGET $TEST_ARGS
|
||||
@@ -1,52 +0,0 @@
|
||||
name: C-lang CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
pull_request:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: install libs
|
||||
run: sudo apt install -y libglfw3-dev libgl-dev libv4l-dev libasound2-dev libbsd-dev
|
||||
- name: gcc
|
||||
run: mkdir -p build && gcc -v -Wall -Wextra -Werror -Wno-format-truncation src/*.c src/*.h -lglfw -lGL -lm -lasound -lbsd -Iinclude hashmap.c/hashmap.c log.c/src/log.c -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE -DVIDEO_IN
|
||||
|
||||
build-no-video:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: install libs
|
||||
run: sudo apt install -y libglfw3-dev libgl-dev libasound2-dev libbsd-dev
|
||||
- name: gcc
|
||||
run: mkdir -p build && gcc -v -Werror src/*.c src/*.h -lglfw -lGL -lm -lasound -lbsd -Iinclude hashmap.c/hashmap.c log.c/src/log.c -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE
|
||||
|
||||
build-release:
|
||||
needs: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: install libs
|
||||
run: sudo apt install -y libglfw3-dev libgl-dev libv4l-dev libasound2-dev libbsd-dev
|
||||
- name: aclocal
|
||||
run: aclocal
|
||||
- name: autoconf
|
||||
run: autoconf
|
||||
- name: automake
|
||||
run: automake --add-missing
|
||||
- name: configure
|
||||
run: ./configure
|
||||
- name: make
|
||||
run: make
|
||||
- name: make distcheck
|
||||
run: make distcheck
|
||||
@@ -0,0 +1,44 @@
|
||||
name: Clang Lint CI
|
||||
|
||||
concurrency:
|
||||
group: lint-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/lint.yml'
|
||||
- 'src/*.c'
|
||||
- 'src/*.h'
|
||||
|
||||
env:
|
||||
GCC_ARGS: src/*.c src/*.h -lglfw -lGL -lm -lasound -Iinclude hashmap.c/hashmap.c log.c/src/log.c -DGLFW_INCLUDE_NONE -DGLFW_NATIVE_INCLUDE_NONE
|
||||
GCC_ARGS_VIDEO: -DGLFW_EXPOSE_NATIVE_EGL -DVIDEO_IN
|
||||
PACKAGES: "libglfw3-dev libgl-dev libasound2-dev"
|
||||
PACKAGES_VIDEO: "libv4l-dev"
|
||||
|
||||
jobs:
|
||||
lint-no-video:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: apt update && apt install -y $PACKAGES
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: gcc
|
||||
run: gcc -Wall -Wextra -Werror -Wno-format-truncation -Wno-unused-parameter $GCC_ARGS
|
||||
|
||||
lint-video:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: apt update && apt install -y $PACKAGES $PACKAGES_VIDEO
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: gcc
|
||||
run: gcc -Wall -Wextra -Werror -Wno-format-truncation $GCC_ARGS $GCC_ARGS_VIDEO
|
||||
+3
-1
@@ -26,4 +26,6 @@ confdeps.*
|
||||
conftest.*
|
||||
*.txt
|
||||
error.glsl
|
||||
draft/
|
||||
draft/
|
||||
*.gch
|
||||
*.out
|
||||
|
||||
+6
-7
@@ -8,7 +8,7 @@ build build project into build/forge
|
||||
run run project with test args
|
||||
demo run project with demo mode
|
||||
valgrind valgrind analysis
|
||||
clean-release remove autoconf/automake files
|
||||
full-clean remove build files and untracked files
|
||||
test-release try to build release
|
||||
release-% make full release of version %
|
||||
release-arch make arch-linux release package
|
||||
@@ -20,7 +20,7 @@ release-arch make arch-linux release package
|
||||
# make full build
|
||||
make -f Makefile.dev release-1.0.0
|
||||
# push release
|
||||
git push origin master --tags
|
||||
git push origin main --tags
|
||||
# create release from tag on github
|
||||
# attach .tar.gz to the github release
|
||||
make -f Makefile.dev release-arch
|
||||
@@ -126,15 +126,14 @@ make -f Makefile.dev release-arch
|
||||
- [x] Monitor improvements
|
||||
- [ ] Ignore some values in auto random
|
||||
- [x] build without video in
|
||||
- [ ] Auto discover video devices
|
||||
- [ ] Update README monitor/keymap
|
||||
- [ ] Auto reconnect midi input
|
||||
- [ ] Auto reconnect video device
|
||||
- [ ] Key codes as inputs
|
||||
- [x] Auto reconnect midi input
|
||||
- [x] Auto reconnect video device
|
||||
- [x] Key codes as inputs
|
||||
- [ ] Mouse position and scroll as inputs
|
||||
- [ ] Joystick as input
|
||||
- [ ] Record show as text files
|
||||
- [ ] Play from record text file
|
||||
- [ ] Fixes
|
||||
- [ ] Try to write NanoKontrol config
|
||||
- [x] Investigate video device fps loss (bad unregister ?)
|
||||
- [x] Investigate video device fps loss (bad unregister ?)
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects -Wall
|
||||
bin_PROGRAMS = forge
|
||||
forge_SOURCES = src/args.c src/arr.c src/config_file.c src/file.c src/forge.c src/main.c src/midi.c src/project.c src/rand.c src/shaders.c src/shared.c src/state.c src/string.c src/tempo.c src/timer.c src/video.c src/window.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/hashmap.c/hashmap.c $(top_srcdir)/log.c/src/log.c
|
||||
forge_SOURCES = src/args.c src/arr.c src/config_file.c src/file.c src/forge.c src/main.c src/midi.c src/project.c src/rand.c src/shaders.c src/state.c src/string.c src/tempo.c src/timer.c src/video.c src/window.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/hashmap.c/hashmap.c $(top_srcdir)/log.c/src/log.c
|
||||
forge_CFLAGS = -Ofast -march=native -flto -funroll-loops -fprefetch-loop-arrays -fno-exceptions -fopenmp -I$(top_srcdir)/include -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE -DLOG_USE_COLOR -DVIDEO_IN -DDATADIR=\"$(datadir)/$(PACKAGE)\"
|
||||
forge_LDADD = -lm -lGL -lglfw -lasound -lbsd
|
||||
include_HEADERS = src/args.h src/arr.h src/config.h src/config_file.h src/constants.h src/file.h src/forge.h src/main.h src/midi.h src/project.h src/rand.h src/shaders.h src/shared.h src/state.h src/string.h src/tempo.h src/timer.h src/types.h src/video.h src/window.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/include/linmath.h $(top_srcdir)/include/hashmap.h $(top_srcdir)/include/log.h
|
||||
forge_LDADD = -lm -lGL -lglfw -lasound
|
||||
include_HEADERS = src/args.h src/arr.h src/config.h src/config_file.h src/constants.h src/file.h src/forge.h src/main.h src/midi.h src/project.h src/rand.h src/shaders.h src/state.h src/string.h src/tempo.h src/timer.h src/types.h src/video.h src/window.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/include/linmath.h $(top_srcdir)/include/hashmap.h $(top_srcdir)/include/log.h
|
||||
|
||||
EXTRA_DIST = default/forge_project.cfg default/frag1.glsl default/frag10.glsl default/frag2.glsl default/frag3.glsl default/frag4.glsl default/frag5.glsl default/frag6.glsl default/frag7.glsl default/frag8.glsl default/frag9.glsl default/inc_cp437.glsl default/inc_debug.glsl default/inc_functions.glsl default/inc_fx.glsl default/inc_magic.glsl default/inc_rand.glsl default/inc_res.glsl default/inc_sentences.glsl default/inc_src.glsl default/inc_template.glsl default/inc_time.glsl default/inc_yuyv.glsl
|
||||
confdir = $(prefix)/share/$(PACKAGE)
|
||||
conf_DATA = default/forge_project.cfg default/frag1.glsl default/frag10.glsl default/frag2.glsl default/frag3.glsl default/frag4.glsl default/frag5.glsl default/frag6.glsl default/frag7.glsl default/frag8.glsl default/frag9.glsl default/inc_cp437.glsl default/inc_debug.glsl default/inc_functions.glsl default/inc_fx.glsl default/inc_magic.glsl default/inc_rand.glsl default/inc_res.glsl default/inc_sentences.glsl default/inc_src.glsl default/inc_template.glsl default/inc_time.glsl default/inc_yuyv.glsl
|
||||
conf_DATA = default/forge_project.cfg default/frag1.glsl default/frag10.glsl default/frag2.glsl default/frag3.glsl default/frag4.glsl default/frag5.glsl default/frag6.glsl default/frag7.glsl default/frag8.glsl default/frag9.glsl default/inc_cp437.glsl default/inc_debug.glsl default/inc_functions.glsl default/inc_fx.glsl default/inc_magic.glsl default/inc_rand.glsl default/inc_res.glsl default/inc_sentences.glsl default/inc_src.glsl default/inc_template.glsl default/inc_time.glsl default/inc_yuyv.glsl
|
||||
|
||||
+29
-32
@@ -1,6 +1,6 @@
|
||||
TARGET ?= forge
|
||||
INSTALL_DIR ?= $(HOME)/.local/bin
|
||||
TEST_ARGS ?= --video-in=/dev/video0 --video-in=/dev/video1 --video-in=/dev/video2 --video-in=/dev/video3 --video-in=/dev/video4 --video-in=/dev/video5 --video-in=/dev/video6 --video-in=/dev/video7 --video-in=/dev/video8 --video-in=/dev/video9
|
||||
RUN_ARGS ?= --help
|
||||
SHELL := /bin/bash
|
||||
|
||||
.PHONY: build
|
||||
@@ -14,7 +14,7 @@ build:
|
||||
-Iinclude \
|
||||
hashmap.c/hashmap.c \
|
||||
log.c/src/log.c \
|
||||
-lm -lGL -lglfw -lasound -lbsd \
|
||||
-lm -lGL -lglfw -lasound \
|
||||
-Wall -Wextra \
|
||||
-Wno-format-truncation \
|
||||
-DGLFW_INCLUDE_NONE \
|
||||
@@ -25,17 +25,31 @@ build:
|
||||
-o build/$(TARGET) \
|
||||
-g -Og
|
||||
|
||||
.PHONY: build-no-video
|
||||
build-no-video:
|
||||
@mkdir -p build
|
||||
gcc \
|
||||
src/*.h src/*.c \
|
||||
-Iinclude \
|
||||
hashmap.c/hashmap.c \
|
||||
log.c/src/log.c \
|
||||
-lm -lGL -lglfw -lasound \
|
||||
-Wall -Wextra \
|
||||
-Wno-format-truncation \
|
||||
-Wno-unused-parameter \
|
||||
-DGLFW_INCLUDE_NONE \
|
||||
-DGLFW_NATIVE_INCLUDE_NONE \
|
||||
-DLOG_USE_COLOR \
|
||||
-o build/$(TARGET) \
|
||||
-g -Og
|
||||
|
||||
.PHONY: format
|
||||
format:
|
||||
clang-format -i src/*
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
./build/$(TARGET) $(TEST_ARGS) --monitor-only --internal-size=480 --video-size=240 --hot-reload
|
||||
|
||||
.PHONY: demo
|
||||
demo: build
|
||||
./build/$(TARGET) $(TEST_ARGS) --demo
|
||||
./build/$(TARGET) $(RUN_ARGS)
|
||||
|
||||
.PHONY: sample
|
||||
sample: build
|
||||
@@ -46,29 +60,12 @@ valgrind: build
|
||||
valgrind \
|
||||
--show-realloc-size-zero=no \
|
||||
--undef-value-errors=no \
|
||||
./build/$(TARGET) $(TEST_ARGS)
|
||||
./build/$(TARGET) $(RUN_ARGS)
|
||||
|
||||
.PHONY: clean-release
|
||||
clean-release:
|
||||
@rm -rf \
|
||||
autom4te.cache \
|
||||
aclocal.m4 \
|
||||
compile \
|
||||
config.* \
|
||||
configure \
|
||||
configure~ \
|
||||
depcomp \
|
||||
**/.deps \
|
||||
**/**/.deps \
|
||||
$(TARGET) \
|
||||
$(TARGET)-*.tar.gz \
|
||||
$(TARGET)-*.pkg.tar.zst \
|
||||
install-sh \
|
||||
Makefile \
|
||||
Makefile.in \
|
||||
missing \
|
||||
src/.* \
|
||||
src/*.o
|
||||
.PHONY: full-clean
|
||||
full-clean:
|
||||
git clean -f -x
|
||||
rm -rf **/**/.deps
|
||||
|
||||
.PHONY: test-release
|
||||
test-release: clean clean-release
|
||||
@@ -82,7 +79,7 @@ test-release: clean clean-release
|
||||
|
||||
.PHONY: release-%
|
||||
release-%: clean clean-release
|
||||
git pull origin master
|
||||
git pull origin main
|
||||
sed -i -E "s/[0-9]+\\.[0-9]+\\.[0-9]+/$*/g" configure.ac
|
||||
aclocal
|
||||
autoconf
|
||||
@@ -95,8 +92,8 @@ release-%: clean clean-release
|
||||
sha256sum build/forge-steel-$*.tar.gz | cut -d' ' -f1 | xargs -I{} sed -i -E "s/sha256sums=\\('.*'\\)/sha256sums=\\('{}'\\)/g" PKGBUILD
|
||||
git add configure.ac PKGBUILD
|
||||
git commit -am "forge (steel) v$*"
|
||||
git tag v$* -m "forge (steel) v$*"
|
||||
@echo "Push release: git push origin master --tags"
|
||||
git tag v$* -m "FORGE steel-$*"
|
||||
@echo "Push release: git push origin main --tags"
|
||||
@echo "Rollback release: git reset HEAD~1 --hard && git tag -d v$*"
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
pkgname=forge-steel
|
||||
pkgver=1.0.1
|
||||
pkgver=1.1.0
|
||||
pkgrel=1
|
||||
pkgdesc="Fusion Of Real Time Generative Effects"
|
||||
arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv7h' 'armv6h' 'aarch64' 'riscv64')
|
||||
depends=('glfw>=1:3', 'v4l-utils>=1.32', 'alsa-lib>=1.2', 'libglvnd>=1.7')
|
||||
url="https://github.com/klemek/forge-steel"
|
||||
source=("${pkgname}-steel-${pkgver}.tar.gz::https://github.com/klemek/forge-steel/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
|
||||
sha256sums=('b2345c1a87f6b5b13dcce6a237a3f9a9ddb7fa9c3e982f5e164e7d7fef5725f3')
|
||||
url="https://git.klemek.fr/klemek/forge-steel"
|
||||
source=("${pkgname}-steel-${pkgver}.tar.gz::https://git.klemek.fr/klemek/forge-steel/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
|
||||
sha256sums=('794fb0f170cff19872acfba8a556e2a08c55a78e497ac0b330eca6db65343529')
|
||||
srcdir=build
|
||||
backup=("usr/share/${pkgname}")
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://github.com/klemek/forge-steel/releases) [](https://github.com/klemek/forge-steel/releases) [](https://github.com/klemek/forge-steel/commits/master/) [](https://github.com/klemek/forge-steel/actions/workflows/ci.yml) [](https://sonarcloud.io/summary/new_code?id=klemek_forge-steel) 
|
||||
[](https://git.klemek.fr/klemek/forge-steel/actions?workflow=lint.yml) [](https://git.klemek.fr/klemek/forge-steel/actions?workflow=build.yml) 
|
||||
|
||||
<!-- omit from toc -->
|
||||
# F.O.R.G.E. (Steel)
|
||||
@@ -116,11 +116,10 @@ Here's a quick rundown of the process:
|
||||
| libGL | libgl-dev | extra/libglvnd |
|
||||
| libasound | libasound2-dev | extra/alsa-lib |
|
||||
| libv4l2 | libv4l-dev | extra/v4l-utils |
|
||||
| libbsd | libbsd-dev | extra/libbsd |
|
||||
|
||||
### From release
|
||||
|
||||
See [Releases](https://github.com/klemek/forge-steel/releases)
|
||||
See [Releases](https://git.klemek.fr/klemek/forge-steel/releases)
|
||||
|
||||
```shell
|
||||
tar xvzf forge-steel-x.y.z.tar.gz
|
||||
@@ -133,7 +132,7 @@ make install
|
||||
### From repository (PKGBUILD)
|
||||
|
||||
```shell
|
||||
git clone --recursive https://github.com/klemek/forge-steel
|
||||
git clone --recursive https://git.klemek.fr/klemek/forge-steel
|
||||
cd forge
|
||||
makepkg -si
|
||||
```
|
||||
@@ -142,7 +141,7 @@ makepkg -si
|
||||
### From repository (dev version)
|
||||
|
||||
```shell
|
||||
git clone --recursive https://github.com/klemek/forge-steel
|
||||
git clone --recursive https://git.klemek.fr/klemek/forge-steel
|
||||
cd forge
|
||||
aclocal
|
||||
autoconf
|
||||
@@ -175,9 +174,9 @@ These are configurable in the [`forge_project.cfg`](#forge_projectcfg).
|
||||
### CLI arguments
|
||||
|
||||
```txt
|
||||
forge steel-dev
|
||||
forge steel-VERSION
|
||||
|
||||
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-vi=FILE] [-vs=SIZE] [-vr / -nvr] [-is=SIZE] [-ls / -nls] [-ss / -nss] [-tm] [-tf]
|
||||
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-vi=FILE] [-vs=SIZE] [-vb=COUNT] [-vr / -nvr] [-is=SIZE] [-ls / -nls] [-ss / -nss] [-mr / -nmr] [-tm] [-tf]
|
||||
|
||||
Fusion Of Real-time Generative Effects.
|
||||
|
||||
@@ -197,6 +196,7 @@ options:
|
||||
-nar, --no-auto-random do not randomize state (default)
|
||||
-arc, --auto-random-cycle auto random cycle length (default: 4)
|
||||
-vi, --video-in path to video capture device (multiple allowed)
|
||||
-vb, --video-buffers number of video buffers to use (default: 2)
|
||||
-vs, --video-size video capture desired height (default: internal texture height)
|
||||
-vr, --video-reconnect auto-reconnect video (default)
|
||||
-nvr, --no-video-reconnect do not auto-reconnect video
|
||||
@@ -205,6 +205,8 @@ options:
|
||||
-nls, --no-load-state do not load saved state
|
||||
-ss, --save-state save state (default)
|
||||
-nss, --no-save-state do not save state
|
||||
-mr, --midi-reconnect auto-reconnect midi (default)
|
||||
-nmr, --no-midi-reconnect do not auto-reconnect midi
|
||||
-tm, --trace-midi print midi code and values
|
||||
-tf, --trace-fps print fps status of subsystems
|
||||
```
|
||||
@@ -281,16 +283,28 @@ We will not dig down all the variables here but feel free to read either:
|
||||
* [sample/forge_project.cfg](./sample/forge_project.cfg) (beginner oriented)
|
||||
* [default/forge_project.cfg](./default/forge_project.cfg) (more complete)
|
||||
|
||||
#### Midi groups
|
||||
#### Input codes
|
||||
|
||||
FORGE allows you to send the midi data in the form of groups.
|
||||
Each input code can be either a midi event or a key code.
|
||||
|
||||
* 0 - 999 -> midi event
|
||||
* Keyboard modifiers are encoded like this:
|
||||
* 1000 -> keyboard event
|
||||
* 10000 -> shift
|
||||
* 100000 -> control
|
||||
* 1000000 -> alt
|
||||
* (This means 111082 is control+alt+R)
|
||||
|
||||
#### Input groups
|
||||
|
||||
FORGE allows you to send the midi/keyboard data in the form of groups.
|
||||
|
||||
Each group has the following properties:
|
||||
|
||||
* A number of layers with `MIDI_X_ACTIVE_COUNT` (default: `1`)
|
||||
* Each midi code controlling how to change the active layer with `MIDI_X_ACTIVE_Y`
|
||||
* A number of codes with `MIDI_X_COUNT`
|
||||
* Each midi code controlling the active layer with `MIDI_X_Y` (as a `vec3`: `_X` / `_Y` / `_Z`)
|
||||
* A number of layers with `GROUP_X_ACTIVE_COUNT` (default: `1`)
|
||||
* Each midi/keyboard code controlling how to change the active layer with `GROUP_X_ACTIVE_Y`
|
||||
* A number of codes with `GROUP_X_COUNT`
|
||||
* Each midi/keyboard code controlling the active layer with `GROUP_X_Y` (as a `vec3`: `_X` / `_Y` / `_Z`)
|
||||
|
||||
#### States
|
||||
|
||||
@@ -298,9 +312,9 @@ FORGE allows to define a "state" to a fragment shader.
|
||||
|
||||
This combines several parameters:
|
||||
|
||||
* `SELECT_PAGE_COUNT` (default: `1`) + `SELECT_PAGE_X`: define midi codes for pages of item.
|
||||
* `SELECT_ITEM_COUNT` + `SELECT_ITEM_X`: define midi codes for items per page.
|
||||
* `SELECT_FRAG_X`: define midi codes to "select" a fragment shader.
|
||||
* `SELECT_PAGE_COUNT` (default: `1`) + `SELECT_PAGE_X`: define midi/keyboard codes for pages of item.
|
||||
* `SELECT_ITEM_COUNT` + `SELECT_ITEM_X`: define midi/keyboard codes for items per page.
|
||||
* `SELECT_FRAG_X`: define midi/keyboard codes to "select" a fragment shader.
|
||||
|
||||
The selected fragment shader will have its state updated with either:
|
||||
|
||||
@@ -341,8 +355,8 @@ uniform float iTime; // the current time
|
||||
uniform sampler2D iTex0; // texture 1 (0-based)
|
||||
uniform sampler2D iTex9; // texture 10
|
||||
uniform int iSeed1;
|
||||
uniform vec3 iMidi2_3[7]; // midi group 2, layer 3, size 7
|
||||
uniform vec3 iMidi3_1[2];
|
||||
uniform vec3 iGroup2_3[7]; // midi group 2, layer 3, size 7
|
||||
uniform vec3 iGroup3_1[2];
|
||||
```
|
||||
|
||||
#### Working with `#include`
|
||||
@@ -458,11 +472,11 @@ FORGE (steel) describe the linux version.
|
||||
|
||||
Verify you have the correct [requirements](#requirements) installed.
|
||||
|
||||
Then if you continue to have problems, you can [open an issue](https://github.com/klemek/forge-steel/issues).
|
||||
Then if you continue to have problems, you can [open an issue](https://git.klemek.fr/klemek/forge-steel/issues).
|
||||
|
||||
### I didn't understand everything about your tutorial
|
||||
|
||||
Please [open an issue](https://github.com/klemek/forge-steel/issues) describing what your having trouble with,
|
||||
Please [open an issue](https://git.klemek.fr/klemek/forge-steel/issues) describing what your having trouble with,
|
||||
I'll try to answer and update the README.
|
||||
|
||||
### My nanoKontrol2 is acting strange
|
||||
@@ -473,7 +487,7 @@ Use the [KORG KONTROL Editor](https://www.korg.com/us/support/download/software/
|
||||
|
||||
### How do I report a bug?
|
||||
|
||||
You're free to open a new issue in the [Issues page](https://github.com/klemek/forge-steel/issues).
|
||||
You're free to open a new issue in the [Issues page](https://git.klemek.fr/klemek/forge-steel/issues).
|
||||
|
||||
Don't forget to add all information available to your bug (version, operating system, etc.).
|
||||
|
||||
|
||||
+3
-1
@@ -2,4 +2,6 @@
|
||||
-DGLFW_INCLUDE_NONE
|
||||
-DGLFW_EXPOSE_NATIVE_EGL
|
||||
-DGLFW_NATIVE_INCLUDE_NONE
|
||||
-DVIDEO_IN
|
||||
-DVIDEO_IN
|
||||
-DEGL_DEBUG
|
||||
-DGL_DEBUG
|
||||
|
||||
+3
-4
@@ -1,4 +1,4 @@
|
||||
AC_INIT([forge], [steel-1.0.1], [klemek.dev@proton.me])
|
||||
AC_INIT([forge], [steel-1.1.0], [klemek.dev@proton.me])
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_PROG_CC
|
||||
|
||||
@@ -22,8 +22,7 @@ AC_CHECK_HEADERS([math.h])
|
||||
AC_CHECK_HEADERS([string.h])
|
||||
AC_CHECK_HEADERS([time.h])
|
||||
AC_CHECK_HEADERS([unistd.h])
|
||||
|
||||
AC_CHECK_HEADERS([bsd/string.h])
|
||||
AC_CHECK_HEADERS([pthread.h])
|
||||
|
||||
AC_CHECK_HEADERS([linux/videodev2.h])
|
||||
|
||||
@@ -33,4 +32,4 @@ AC_CHECK_HEADERS([GLFW/glfw3.h])
|
||||
AC_CHECK_HEADERS([GLFW/glfw3native.h])
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
AC_OUTPUT
|
||||
|
||||
+111
-113
@@ -6,7 +6,7 @@
|
||||
# (shaders, video devices, textures, midi inputs, etc.)
|
||||
# Every number based constant will be "one-based" (1,2,3,etc.)
|
||||
# To read more, go to
|
||||
# https://github.com/klemek/forge-steel
|
||||
# https://git.klemek.fr/klemek/forge-steel
|
||||
|
||||
|
||||
# ================
|
||||
@@ -24,7 +24,7 @@
|
||||
UNIFORM_TIME=iTime
|
||||
# Current tempo
|
||||
UNIFORM_TEMPO=iTempo
|
||||
# Current total beats
|
||||
# Current total beats
|
||||
UNIFORM_BEATS=iBeats
|
||||
|
||||
# --- uniform int ---
|
||||
@@ -51,8 +51,6 @@ UNIFORM_STATE_PREFIX=iState
|
||||
UNIFORM_ACTIVE_PREFIX=iActive
|
||||
# Input X format raw integer value
|
||||
UNIFORM_IN_FORMAT_PREFIX=iInputFormat
|
||||
# Input X should use swap texture or not (0/1)
|
||||
UNIFORM_IN_SWAP_PREFIX=iInputSwap
|
||||
|
||||
# --- uniform vec2 ---
|
||||
|
||||
@@ -66,8 +64,8 @@ UNIFORM_IN_RESOLUTION_PREFIX=iInputResolution
|
||||
# --- uniform vec3 ---
|
||||
|
||||
# Midi group X layer Y (beware of group size)
|
||||
# Injected as "iMidiX_Y[Z]"
|
||||
UNIFORM_MIDI_PREFIX=iMidi
|
||||
# Injected as "iGroupX_Y[Z]"
|
||||
UNIFORM_GROUP_PREFIX=iGroup
|
||||
|
||||
# --- uniform sampler2D ---
|
||||
|
||||
@@ -106,9 +104,6 @@ IN_COUNT=2
|
||||
# To which texture will be bound video device X
|
||||
IN_1_OUT=1
|
||||
IN_2_OUT=2
|
||||
# To which texture will be bound swap buffers (for double-buffering)
|
||||
IN_1_SWAP_OUT=3
|
||||
IN_2_SWAP_OUT=4
|
||||
|
||||
# === FRAGMENT SHADERS
|
||||
# Fragment shaders will be read from the CLI directory as "fragX.glsl"
|
||||
@@ -120,13 +115,13 @@ FRAG_FILE_PREFIX=frag
|
||||
FRAG_COUNT=10
|
||||
|
||||
# To which texture will the shader fragX.glsl will render to
|
||||
FRAG_1_OUT=5
|
||||
FRAG_2_OUT=6
|
||||
FRAG_3_OUT=7
|
||||
FRAG_4_OUT=8
|
||||
FRAG_5_OUT=9
|
||||
FRAG_6_OUT=10
|
||||
FRAG_7_OUT=11
|
||||
FRAG_1_OUT=3
|
||||
FRAG_2_OUT=4
|
||||
FRAG_3_OUT=5
|
||||
FRAG_4_OUT=6
|
||||
FRAG_5_OUT=7
|
||||
FRAG_6_OUT=8
|
||||
FRAG_7_OUT=9
|
||||
FRAG_8_OUT=0
|
||||
# Which fragment shader renders to output window
|
||||
FRAG_OUTPUT=9
|
||||
@@ -134,10 +129,17 @@ FRAG_OUTPUT=9
|
||||
FRAG_MONITOR=10
|
||||
|
||||
|
||||
# ========
|
||||
# MIDI I/O
|
||||
# ========
|
||||
|
||||
# ==========
|
||||
# I/O Inputs
|
||||
# ==========
|
||||
# Each code either maps to a midi event or a key code
|
||||
# 0 - 999 -> midi event
|
||||
# Keyboard modifiers are encoded like this:
|
||||
# 1000 -> keyboard event
|
||||
# 10000 -> shift
|
||||
# 100000 -> control
|
||||
# 1000000 -> alt
|
||||
# This means 111082 is control+alt+R
|
||||
|
||||
# The recognized ALSA name of the midi device
|
||||
MIDI_HW=hw:CARD=nanoKONTROL2
|
||||
@@ -193,8 +195,8 @@ SELECT_ITEM_3=42
|
||||
SELECT_ITEM_4=41
|
||||
SELECT_ITEM_5=45
|
||||
|
||||
# === MIDI INPUT STATES
|
||||
# Midi inputs will control FORGE's state as follows
|
||||
# === GROUP INPUT STATES
|
||||
# Inputs will control FORGE's state as follows
|
||||
# X groups of Y layers sized Z
|
||||
# You can manipulate only 1 layer at a time
|
||||
# Every layer of every groups will be send as uniforms
|
||||
@@ -202,72 +204,72 @@ SELECT_ITEM_5=45
|
||||
# with the same codes for nice display
|
||||
|
||||
# Total number of groups
|
||||
MIDI_COUNT=3
|
||||
GROUP_COUNT=3
|
||||
|
||||
# Total number of layers of group 1
|
||||
MIDI_1_ACTIVE_COUNT=2
|
||||
GROUP_1_ACTIVE_COUNT=2
|
||||
# Midi codes to change layer of group 1
|
||||
MIDI_1_ACTIVE_1=32
|
||||
MIDI_1_ACTIVE_2=64
|
||||
GROUP_1_ACTIVE_1=32
|
||||
GROUP_1_ACTIVE_2=64
|
||||
|
||||
# Size of group 1
|
||||
MIDI_1_COUNT=6
|
||||
GROUP_1_COUNT=6
|
||||
# Every code of active layer manipulation of group 1
|
||||
MIDI_1_1_X=33
|
||||
MIDI_1_1_Y=49
|
||||
MIDI_1_1_Z=65
|
||||
MIDI_1_2_X=1
|
||||
MIDI_1_2_Y=17
|
||||
MIDI_1_2_Z=
|
||||
MIDI_1_3_X=34
|
||||
MIDI_1_3_Y=50
|
||||
MIDI_1_3_Z=66
|
||||
MIDI_1_4_X=2
|
||||
MIDI_1_4_Y=18
|
||||
MIDI_1_4_Z=
|
||||
MIDI_1_5_X=35
|
||||
MIDI_1_5_Y=51
|
||||
MIDI_1_5_Z=67
|
||||
MIDI_1_6_X=3
|
||||
MIDI_1_6_Y=19
|
||||
MIDI_1_6_Z=
|
||||
GROUP_1_1_X=33
|
||||
GROUP_1_1_Y=49
|
||||
GROUP_1_1_Z=65
|
||||
GROUP_1_2_X=1
|
||||
GROUP_1_2_Y=17
|
||||
GROUP_1_2_Z=
|
||||
GROUP_1_3_X=34
|
||||
GROUP_1_3_Y=50
|
||||
GROUP_1_3_Z=66
|
||||
GROUP_1_4_X=2
|
||||
GROUP_1_4_Y=18
|
||||
GROUP_1_4_Z=
|
||||
GROUP_1_5_X=35
|
||||
GROUP_1_5_Y=51
|
||||
GROUP_1_5_Z=67
|
||||
GROUP_1_6_X=3
|
||||
GROUP_1_6_Y=19
|
||||
GROUP_1_6_Z=
|
||||
|
||||
# Same for group 2
|
||||
MIDI_2_ACTIVE_COUNT=3
|
||||
MIDI_2_ACTIVE_1=36
|
||||
MIDI_2_ACTIVE_2=68
|
||||
MIDI_2_ACTIVE_3=52
|
||||
MIDI_2_COUNT=7
|
||||
MIDI_2_1_X=37
|
||||
MIDI_2_1_Y=53
|
||||
MIDI_2_1_Z=69
|
||||
MIDI_2_2_X=5
|
||||
MIDI_2_2_Y=21
|
||||
MIDI_2_2_Z=
|
||||
MIDI_2_3_X=38
|
||||
MIDI_2_3_Y=54
|
||||
MIDI_2_3_Z=70
|
||||
MIDI_2_4_X=6
|
||||
MIDI_2_4_Y=22
|
||||
MIDI_2_4_Z=
|
||||
MIDI_2_5_X=39
|
||||
MIDI_2_5_Y=55
|
||||
MIDI_2_5_Z=71
|
||||
MIDI_2_6_X=7
|
||||
MIDI_2_6_Y=23
|
||||
MIDI_2_6_Z=
|
||||
MIDI_2_7_X=4
|
||||
MIDI_2_7_Y=20
|
||||
MIDI_2_7_Z=59
|
||||
GROUP_2_ACTIVE_COUNT=3
|
||||
GROUP_2_ACTIVE_1=36
|
||||
GROUP_2_ACTIVE_2=68
|
||||
GROUP_2_ACTIVE_3=52
|
||||
GROUP_2_COUNT=7
|
||||
GROUP_2_1_X=37
|
||||
GROUP_2_1_Y=53
|
||||
GROUP_2_1_Z=69
|
||||
GROUP_2_2_X=5
|
||||
GROUP_2_2_Y=21
|
||||
GROUP_2_2_Z=
|
||||
GROUP_2_3_X=38
|
||||
GROUP_2_3_Y=54
|
||||
GROUP_2_3_Z=70
|
||||
GROUP_2_4_X=6
|
||||
GROUP_2_4_Y=22
|
||||
GROUP_2_4_Z=
|
||||
GROUP_2_5_X=39
|
||||
GROUP_2_5_Y=55
|
||||
GROUP_2_5_Z=71
|
||||
GROUP_2_6_X=7
|
||||
GROUP_2_6_Y=23
|
||||
GROUP_2_6_Z=
|
||||
GROUP_2_7_X=4
|
||||
GROUP_2_7_Y=20
|
||||
GROUP_2_7_Z=59
|
||||
|
||||
# Same for group 3
|
||||
MIDI_3_COUNT=2
|
||||
MIDI_3_1_X=48
|
||||
MIDI_3_1_Y=58
|
||||
MIDI_3_1_Z=
|
||||
MIDI_3_2_X=0
|
||||
MIDI_3_2_Y=16
|
||||
MIDI_3_2_Z=
|
||||
GROUP_3_COUNT=2
|
||||
GROUP_3_1_X=48
|
||||
GROUP_3_1_Y=58
|
||||
GROUP_3_1_Z=
|
||||
GROUP_3_2_X=0
|
||||
GROUP_3_2_Y=16
|
||||
GROUP_3_2_Z=
|
||||
|
||||
# =====
|
||||
# OTHER
|
||||
@@ -279,55 +281,51 @@ SAVE_FILE_PREFIX=forge_default_save
|
||||
|
||||
# === HOTKEYS
|
||||
# You can change the default keycodes used on runtime
|
||||
# Modifiers are encoded like this:
|
||||
# 1000 -> shift
|
||||
# 10000 -> control
|
||||
# 100000 -> alt
|
||||
# This means 110082 is control+alt+R
|
||||
|
||||
|
||||
# R on (qwerty)
|
||||
HOTKEY_RANDOMIZE=82
|
||||
KEY_RANDOMIZE=1082
|
||||
# SHIFT+R (qwerty)
|
||||
HOTKEY_RESET=1082
|
||||
KEY_RESET=11082
|
||||
# D (qwerty)
|
||||
HOTKEY_DEMO=68
|
||||
KEY_DEMO=1068
|
||||
# A (qwerty)
|
||||
HOTKEY_AUTORAND=65
|
||||
KEY_AUTORAND=1065
|
||||
# Left arrow
|
||||
HOTKEY_AUTORAND_DOWN=263
|
||||
KEY_AUTORAND_DOWN=1263
|
||||
# Right arrow
|
||||
HOTKEY_AUTORAND_UP=262
|
||||
KEY_AUTORAND_UP=1262
|
||||
# Down arrow
|
||||
HOTKEY_TEMPO_DOWN=264
|
||||
KEY_TEMPO_DOWN=1264
|
||||
# Up arrow
|
||||
HOTKEY_TEMPO_UP=265
|
||||
KEY_TEMPO_UP=1265
|
||||
|
||||
# Number of load states keys
|
||||
HOTKEY_LOAD_COUNT=10
|
||||
KEY_LOAD_COUNT=10
|
||||
|
||||
# 1 to 9 then 0 keys
|
||||
HOTKEY_LOAD_1=49
|
||||
HOTKEY_LOAD_2=50
|
||||
HOTKEY_LOAD_3=51
|
||||
HOTKEY_LOAD_4=52
|
||||
HOTKEY_LOAD_5=53
|
||||
HOTKEY_LOAD_6=54
|
||||
HOTKEY_LOAD_7=55
|
||||
HOTKEY_LOAD_8=56
|
||||
HOTKEY_LOAD_9=57
|
||||
HOTKEY_LOAD_10=48
|
||||
KEY_LOAD_1=1049
|
||||
KEY_LOAD_2=1050
|
||||
KEY_LOAD_3=1051
|
||||
KEY_LOAD_4=1052
|
||||
KEY_LOAD_5=1053
|
||||
KEY_LOAD_6=1054
|
||||
KEY_LOAD_7=1055
|
||||
KEY_LOAD_8=1056
|
||||
KEY_LOAD_9=1057
|
||||
KEY_LOAD_10=1048
|
||||
|
||||
# Number of save states keys
|
||||
HOTKEY_SAVE_COUNT=10
|
||||
KEY_SAVE_COUNT=10
|
||||
|
||||
# 1 to 9 then 0 keys with shift
|
||||
HOTKEY_SAVE_1=1049
|
||||
HOTKEY_SAVE_2=1050
|
||||
HOTKEY_SAVE_3=1051
|
||||
HOTKEY_SAVE_4=1052
|
||||
HOTKEY_SAVE_5=1053
|
||||
HOTKEY_SAVE_6=1054
|
||||
HOTKEY_SAVE_7=1055
|
||||
HOTKEY_SAVE_8=1056
|
||||
HOTKEY_SAVE_9=1057
|
||||
HOTKEY_SAVE_10=1048
|
||||
KEY_SAVE_1=11049
|
||||
KEY_SAVE_2=11050
|
||||
KEY_SAVE_3=11051
|
||||
KEY_SAVE_4=11052
|
||||
KEY_SAVE_5=11053
|
||||
KEY_SAVE_6=11054
|
||||
KEY_SAVE_7=11055
|
||||
KEY_SAVE_8=11056
|
||||
KEY_SAVE_9=11057
|
||||
KEY_SAVE_10=11048
|
||||
|
||||
+3
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
// VIDEO 1
|
||||
// -----------
|
||||
// IN: 1+3 (RAW IN A)
|
||||
// OUT: 5 (IN A)
|
||||
// IN: 1 (RAW IN A)
|
||||
// OUT: 3 (IN A)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
@@ -14,16 +14,11 @@ uniform sampler2D iTex0;
|
||||
uniform sampler2D iTex1;
|
||||
uniform sampler2D iTex3;
|
||||
uniform int iInputFormat1;
|
||||
uniform int iInputSwap1;
|
||||
uniform vec2 iInputResolution1;
|
||||
|
||||
void main() {
|
||||
if (iInputFormat1 == YUYV_FOURCC) {
|
||||
if (iInputSwap1 > 0) {
|
||||
fragColor = yuyvTex(iTex3, vUV, int(iInputResolution1.x));
|
||||
} else {
|
||||
fragColor = yuyvTex(iTex1, vUV, int(iInputResolution1.x));
|
||||
}
|
||||
fragColor = yuyvTex(iTex1, vUV, int(iInputResolution1.x));
|
||||
} else {
|
||||
fragColor = texture(iTex0, vUV);
|
||||
}
|
||||
|
||||
+94
-22
@@ -9,13 +9,13 @@ out vec4 fragColor;
|
||||
#include inc_debug.glsl
|
||||
|
||||
uniform sampler2D iTex0;
|
||||
uniform sampler2D iTex3;
|
||||
uniform sampler2D iTex4;
|
||||
uniform sampler2D iTex5;
|
||||
uniform sampler2D iTex6;
|
||||
uniform sampler2D iTex7;
|
||||
uniform sampler2D iTex8;
|
||||
uniform sampler2D iTex9;
|
||||
uniform sampler2D iTex10;
|
||||
uniform sampler2D iTex11;
|
||||
uniform int iFPS;
|
||||
uniform int iInputFPS1;
|
||||
uniform int iInputFPS2;
|
||||
@@ -26,19 +26,91 @@ float s(vec2 uv, float x0, float y0) {
|
||||
}
|
||||
|
||||
const int texts[12][5] = {
|
||||
{0x49, 0x4E, 0x20, 0x41, 0x00}, // IN A
|
||||
{0x49, 0x4E, 0x20, 0x42, 0x00}, // IN B
|
||||
{0x53, 0x52, 0x43, 0x20, 0x41}, // SRC A
|
||||
{0x53, 0x52, 0x43, 0x20, 0x42}, // SRC B
|
||||
{0x46, 0x58, 0x20, 0x41, 0x00}, // FX A
|
||||
{0x46, 0x58, 0x20, 0x42, 0x00}, // FX B
|
||||
{0x41, 0x2B, 0x42, 0x00, 0x00}, // A+B
|
||||
{0x4D, 0x46, 0x58, 0x00, 0x00}, // MFX
|
||||
{0x46, 0x50, 0x53, 0x00, 0x00}, // FPS
|
||||
{0x4F, 0x46, 0x46, 0x00, 0x00}, // OFF
|
||||
{0x44, 0x45, 0x4D, 0x4F, 0x00}, // DEMO
|
||||
{0x4C, 0x49, 0x56, 0x45, 0x00}, // LIVE
|
||||
};
|
||||
{
|
||||
0x49,
|
||||
0x4E,
|
||||
0x20,
|
||||
0x41,
|
||||
0x00
|
||||
}, // IN A
|
||||
{
|
||||
0x49,
|
||||
0x4E,
|
||||
0x20,
|
||||
0x42,
|
||||
0x00
|
||||
}, // IN B
|
||||
{
|
||||
0x53,
|
||||
0x52,
|
||||
0x43,
|
||||
0x20,
|
||||
0x41
|
||||
}, // SRC A
|
||||
{
|
||||
0x53,
|
||||
0x52,
|
||||
0x43,
|
||||
0x20,
|
||||
0x42
|
||||
}, // SRC B
|
||||
{
|
||||
0x46,
|
||||
0x58,
|
||||
0x20,
|
||||
0x41,
|
||||
0x00
|
||||
}, // FX A
|
||||
{
|
||||
0x46,
|
||||
0x58,
|
||||
0x20,
|
||||
0x42,
|
||||
0x00
|
||||
}, // FX B
|
||||
{
|
||||
0x41,
|
||||
0x2B,
|
||||
0x42,
|
||||
0x00,
|
||||
0x00
|
||||
}, // A+B
|
||||
{
|
||||
0x4D,
|
||||
0x46,
|
||||
0x58,
|
||||
0x00,
|
||||
0x00
|
||||
}, // MFX
|
||||
{
|
||||
0x46,
|
||||
0x50,
|
||||
0x53,
|
||||
0x00,
|
||||
0x00
|
||||
}, // FPS
|
||||
{
|
||||
0x4F,
|
||||
0x46,
|
||||
0x46,
|
||||
0x00,
|
||||
0x00
|
||||
}, // OFF
|
||||
{
|
||||
0x44,
|
||||
0x45,
|
||||
0x4D,
|
||||
0x4F,
|
||||
0x00
|
||||
}, // DEMO
|
||||
{
|
||||
0x4C,
|
||||
0x49,
|
||||
0x56,
|
||||
0x45,
|
||||
0x00
|
||||
}, // LIVE
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec2 uv0 = vUV.st;
|
||||
@@ -50,14 +122,14 @@ void main() {
|
||||
|
||||
vec4 c = vec4(0);
|
||||
|
||||
c += s(uv2, 1, 2) * texture(iTex7, uv2);
|
||||
c += s(uv2, 2, 2) * texture(iTex9, uv2);
|
||||
c += s(uv2, 1, 2) * texture(iTex5, uv2);
|
||||
c += s(uv2, 2, 2) * texture(iTex7, uv2);
|
||||
|
||||
c += s(uv2, 1, 0) * texture(iTex8, uv2);
|
||||
c += s(uv2, 2, 0) * texture(iTex10, uv2);
|
||||
c += s(uv2, 1, 0) * texture(iTex6, uv2);
|
||||
c += s(uv2, 2, 0) * texture(iTex8, uv2);
|
||||
|
||||
c += s(uv2, 0, 1) * debug(mod(uv2, 1));
|
||||
c += s(uv2, 1, 1) * texture(iTex11, uv2);
|
||||
c += s(uv2, 1, 1) * texture(iTex9, uv2);
|
||||
c += s(uv2, 2, 1) * texture(iTex0, uv2);
|
||||
|
||||
float sel = 0;
|
||||
@@ -77,7 +149,7 @@ void main() {
|
||||
t += write_5(uv3, vec2(-37, 28), texts[0]);
|
||||
|
||||
if (iInputFormat1 == YUYV_FOURCC) {
|
||||
c += s(uv2, 0, 2) * texture(iTex5, uv2);
|
||||
c += s(uv2, 0, 2) * texture(iTex3, uv2);
|
||||
f += rect(uv3, vec2(-35, 26.75), vec2(2.8, 0.7));
|
||||
t += write_int(uv3, vec2(-37.6, 26.1), iInputFPS1, 2);
|
||||
t += write_5(uv3, vec2(-35.1, 26.1), texts[8]);
|
||||
@@ -90,7 +162,7 @@ void main() {
|
||||
t += write_5(uv3, vec2(-37, -12), texts[1]);
|
||||
|
||||
if (iInputFormat2 == YUYV_FOURCC) {
|
||||
c += s(uv2, 0, 0) * texture(iTex6, uv2);
|
||||
c += s(uv2, 0, 0) * texture(iTex4, uv2);
|
||||
f += rect(uv3, vec2(-35, -13.25), vec2(2.8, 0.7));
|
||||
t += write_int(uv3, vec2(-37.6, -13.9), iInputFPS2, 2);
|
||||
t += write_5(uv3, vec2(-35.1, -13.9), texts[8]);
|
||||
|
||||
+3
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
// VIDEO 2
|
||||
// -----------
|
||||
// IN: 2+4 (RAW IN B)
|
||||
// OUT: 6 (IN B)
|
||||
// IN: 2 (RAW IN B)
|
||||
// OUT: 4 (IN B)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
@@ -14,16 +14,11 @@ uniform sampler2D iTex0;
|
||||
uniform sampler2D iTex2;
|
||||
uniform sampler2D iTex4;
|
||||
uniform int iInputFormat2;
|
||||
uniform int iInputSwap2;
|
||||
uniform vec2 iInputResolution2;
|
||||
|
||||
void main() {
|
||||
if (iInputFormat2 == YUYV_FOURCC) {
|
||||
if (iInputSwap2 > 0) {
|
||||
fragColor = yuyvTex(iTex4, vUV, int(iInputResolution2.x));
|
||||
} else {
|
||||
fragColor = yuyvTex(iTex2, vUV, int(iInputResolution2.x));
|
||||
}
|
||||
fragColor = yuyvTex(iTex2, vUV, int(iInputResolution2.x));
|
||||
} else {
|
||||
fragColor = texture(iTex0, vUV);
|
||||
}
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
// SRC A
|
||||
// -----------
|
||||
// OUT: 7 (FX A)
|
||||
// OUT: 5 (FX A)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
@@ -13,8 +13,8 @@ out vec4 fragColor;
|
||||
subroutine uniform src_stage_sub src_stage;
|
||||
|
||||
uniform int iSeed3;
|
||||
uniform vec3 iMidi1_1[6];
|
||||
uniform vec3 iGroup1_1[6];
|
||||
|
||||
void main() {
|
||||
fragColor = src_stage(vUV, iSeed3, iMidi1_1[0], iMidi1_1[1].xy, iMidi1_1[2], iMidi1_1[3].xy, iMidi1_1[4], iMidi1_1[5].xy);
|
||||
fragColor = src_stage(vUV, iSeed3, iGroup1_1[0], iGroup1_1[1].xy, iGroup1_1[2], iGroup1_1[3].xy, iGroup1_1[4], iGroup1_1[5].xy);
|
||||
}
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
// SRC B
|
||||
// -----------
|
||||
// OUT: 8 (FX B)
|
||||
// OUT: 6 (FX B)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
@@ -12,8 +12,8 @@ out vec4 fragColor;
|
||||
subroutine uniform src_stage_sub src_stage;
|
||||
|
||||
uniform int iSeed4;
|
||||
uniform vec3 iMidi1_2[6];
|
||||
uniform vec3 iGroup1_2[6];
|
||||
|
||||
void main() {
|
||||
fragColor = src_stage(vUV, iSeed4, iMidi1_2[0], iMidi1_2[1].xy, iMidi1_2[2], iMidi1_2[3].xy, iMidi1_2[4], iMidi1_2[5].xy);
|
||||
fragColor = src_stage(vUV, iSeed4, iGroup1_2[0], iGroup1_2[1].xy, iGroup1_2[2], iGroup1_2[3].xy, iGroup1_2[4], iGroup1_2[5].xy);
|
||||
}
|
||||
|
||||
+6
-6
@@ -2,20 +2,20 @@
|
||||
|
||||
// FX A
|
||||
// -------------
|
||||
// IN: 7 (SRC A)
|
||||
// IN: 9 (FX A)
|
||||
// OUT: 9 (A+B)
|
||||
// IN: 5 (SRC A)
|
||||
// IN: 7 (FX A)
|
||||
// OUT: 7 (A+B)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
|
||||
#include inc_fx.glsl
|
||||
|
||||
uniform sampler2D iTex5;
|
||||
uniform sampler2D iTex7;
|
||||
uniform sampler2D iTex9;
|
||||
uniform int iSeed5;
|
||||
uniform vec3 iMidi2_1[7];
|
||||
uniform vec3 iGroup2_1[7];
|
||||
|
||||
void main() {
|
||||
fragColor = fx_stage(vUV, iTex7, iTex9, iSeed5, iMidi2_1[0], iMidi2_1[1].xy, iMidi2_1[2], iMidi2_1[3].xy, iMidi2_1[4], iMidi2_1[5].xy, iMidi2_1[6]);
|
||||
fragColor = fx_stage(vUV, iTex5, iTex7, iSeed5, iGroup2_1[0], iGroup2_1[1].xy, iGroup2_1[2], iGroup2_1[3].xy, iGroup2_1[4], iGroup2_1[5].xy, iGroup2_1[6]);
|
||||
}
|
||||
|
||||
+6
-6
@@ -2,20 +2,20 @@
|
||||
|
||||
// FX B
|
||||
// -------------
|
||||
// IN: 8 (SRC B)
|
||||
// IN: 10 (FX B)
|
||||
// OUT: 10 (A+B)
|
||||
// IN: 6 (SRC B)
|
||||
// IN: 8 (FX B)
|
||||
// OUT: 8 (A+B)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
|
||||
#include inc_fx.glsl
|
||||
|
||||
uniform sampler2D iTex6;
|
||||
uniform sampler2D iTex8;
|
||||
uniform sampler2D iTex10;
|
||||
uniform int iSeed6;
|
||||
uniform vec3 iMidi2_2[7];
|
||||
uniform vec3 iGroup2_2[7];
|
||||
|
||||
void main() {
|
||||
fragColor = fx_stage(vUV, iTex8, iTex10, iSeed6, iMidi2_2[0], iMidi2_2[1].xy, iMidi2_2[2], iMidi2_2[3].xy, iMidi2_2[4], iMidi2_2[5].xy, iMidi2_2[6]);
|
||||
fragColor = fx_stage(vUV, iTex6, iTex8, iSeed6, iGroup2_2[0], iGroup2_2[1].xy, iGroup2_2[2], iGroup2_2[3].xy, iGroup2_2[4], iGroup2_2[5].xy, iGroup2_2[6]);
|
||||
}
|
||||
|
||||
+10
-10
@@ -2,9 +2,9 @@
|
||||
|
||||
// A+B
|
||||
// ------------
|
||||
// IN: 9 (FX A)
|
||||
// IN: 10 (FX B)
|
||||
// OUT: 11 (MFX)
|
||||
// IN: 7 (FX A)
|
||||
// IN: 8 (FX B)
|
||||
// OUT: 9 (MFX)
|
||||
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
@@ -13,17 +13,17 @@ out vec4 fragColor;
|
||||
#include inc_functions.glsl
|
||||
|
||||
uniform int iDemo;
|
||||
uniform sampler2D iTex9;
|
||||
uniform sampler2D iTex10;
|
||||
uniform sampler2D iTex7;
|
||||
uniform sampler2D iTex8;
|
||||
uniform int iSeed7;
|
||||
uniform vec3 iMidi3_1[2];
|
||||
uniform vec3 iGroup3_1[2];
|
||||
|
||||
void main() {
|
||||
float mix_value = magic(iMidi3_1[1].xy, vec3(1, 0, 0), iSeed7);
|
||||
bool mix_type = magic_trigger(vec3(iMidi3_1[0].x, 0, 0), iSeed7 + 10);
|
||||
float mix_value = magic(iGroup3_1[1].xy, vec3(1, 0, 0), iSeed7);
|
||||
bool mix_type = magic_trigger(vec3(iGroup3_1[0].x, 0, 0), iSeed7 + 10);
|
||||
|
||||
vec4 color_a = texture(iTex9, vUV);
|
||||
vec4 color_b = texture(iTex10, vUV);
|
||||
vec4 color_a = texture(iTex7, vUV);
|
||||
vec4 color_b = texture(iTex8, vUV);
|
||||
|
||||
float k = mean(color_a);
|
||||
|
||||
|
||||
+6
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
// MFX
|
||||
// ------------
|
||||
// IN: 11 (A+B)
|
||||
// IN: 9 (A+B)
|
||||
// IN: 0 (OUT)
|
||||
// OUT: 0 (OUT)
|
||||
|
||||
@@ -11,19 +11,19 @@ out vec4 fragColor;
|
||||
|
||||
#include inc_fx.glsl
|
||||
|
||||
uniform sampler2D iTex11;
|
||||
uniform sampler2D iTex9;
|
||||
uniform sampler2D iTex0;
|
||||
uniform int iSeed8;
|
||||
uniform vec3 iMidi2_3[7];
|
||||
uniform vec3 iMidi3_1[2];
|
||||
uniform vec3 iGroup2_3[7];
|
||||
uniform vec3 iGroup3_1[2];
|
||||
uniform int iDemo;
|
||||
uniform int iAutoRand;
|
||||
|
||||
void main() {
|
||||
vec4 color = fx_stage(vUV, iTex11, iTex0, iSeed8, iMidi2_3[0], iMidi2_3[1].xy, iMidi2_3[2], iMidi2_3[3].xy, iMidi2_3[4], iMidi2_3[5].xy, iMidi2_3[6]);
|
||||
vec4 color = fx_stage(vUV, iTex9, iTex0, iSeed8, iGroup2_3[0], iGroup2_3[1].xy, iGroup2_3[2], iGroup2_3[3].xy, iGroup2_3[4], iGroup2_3[5].xy, iGroup2_3[6]);
|
||||
|
||||
if (iDemo < 1 && iAutoRand < 1) {
|
||||
color = mix(color, vec4(0), iMidi3_1[0].y);
|
||||
color = mix(color, vec4(0), iGroup3_1[0].y);
|
||||
}
|
||||
|
||||
fragColor = color;
|
||||
|
||||
+108
-50
@@ -35,17 +35,16 @@ uniform int iState8;
|
||||
uniform int iActive1;
|
||||
uniform int iActive2;
|
||||
|
||||
uniform vec3 iMidi2_1[7];
|
||||
uniform vec3 iMidi2_2[7];
|
||||
uniform vec3 iMidi2_3[7];
|
||||
uniform vec3 iMidi3_1[2];
|
||||
|
||||
uniform vec3 iGroup2_1[7];
|
||||
uniform vec3 iGroup2_2[7];
|
||||
uniform vec3 iGroup2_3[7];
|
||||
uniform vec3 iGroup3_1[2];
|
||||
|
||||
vec4 debug(vec2 vUV)
|
||||
{
|
||||
// start
|
||||
|
||||
vec2 uv0 = vUV.st;
|
||||
vec2 uv0 = vUV.st;
|
||||
float ratio = iResolution.x / iResolution.y;
|
||||
vec2 uv1 = (uv0 - .5) * vec2(ratio, 1);
|
||||
|
||||
@@ -92,30 +91,90 @@ vec4 debug(vec2 vUV)
|
||||
if (random_mfx) {
|
||||
selected_mfx = int(randTime(iSeed8 + 100) * 14);
|
||||
}
|
||||
float fxa_value = magic(iMidi2_1[6].xy, vec3(1, 0, 0), iSeed5);
|
||||
bool fxa_invert = magic_trigger(vec3(iMidi2_1[6].z, 0, 0), iSeed5);
|
||||
float fxb_value = magic(iMidi2_2[6].xy, vec3(1, 0, 0), iSeed6);
|
||||
bool fxb_invert = magic_trigger(vec3(iMidi2_2[6].z, 0, 0), iSeed6);
|
||||
float mfx_value = magic(iMidi2_3[6].xy, vec3(1, 0, 0), iSeed8);
|
||||
bool mfx_invert = magic_trigger(vec3(iMidi2_3[6].z, 0, 0), iSeed8);
|
||||
float mix_value = magic(iMidi3_1[1].xy, vec3(1, 0, 0), iSeed7);
|
||||
float fxa_value = magic(iGroup2_1[6].xy, vec3(1, 0, 0), iSeed5);
|
||||
bool fxa_invert = magic_trigger(vec3(iGroup2_1[6].z, 0, 0), iSeed5);
|
||||
float fxb_value = magic(iGroup2_2[6].xy, vec3(1, 0, 0), iSeed6);
|
||||
bool fxb_invert = magic_trigger(vec3(iGroup2_2[6].z, 0, 0), iSeed6);
|
||||
float mfx_value = magic(iGroup2_3[6].xy, vec3(1, 0, 0), iSeed8);
|
||||
bool mfx_invert = magic_trigger(vec3(iGroup2_3[6].z, 0, 0), iSeed8);
|
||||
float mix_value = magic(iGroup3_1[1].xy, vec3(1, 0, 0), iSeed7);
|
||||
mix_value = mix(mix_value, mix_value * 0.9 + 0.05, iDemo);
|
||||
bool mix_type = magic_trigger(vec3(iMidi3_1[0].x, 0, 0), iSeed7 + 10);
|
||||
bool mix_type = magic_trigger(vec3(iGroup3_1[0].x, 0, 0), iSeed7 + 10);
|
||||
|
||||
// logic
|
||||
|
||||
const int texts[10][5] = {
|
||||
{0x46, 0x50, 0x53, 0x00, 0x00}, // FPS
|
||||
{0x54, 0x45, 0x4D, 0x50, 0x4F}, // TEMPO
|
||||
{0x54, 0x49, 0x4D, 0x45, 0x00}, // TIME
|
||||
{0x44, 0x45, 0x4D, 0x4F, 0x00}, // DEMO
|
||||
{0x4C, 0x49, 0x56, 0x45, 0x00}, // LIVE
|
||||
{0x52, 0x41, 0x4E, 0x44, 0x00}, // RAND
|
||||
{0x53, 0x52, 0x43, 0x00, 0x00}, // SRC
|
||||
{0x46, 0x58, 0x00, 0x00, 0x00}, // FX
|
||||
{0x49, 0x4E, 0x00, 0x00, 0x00}, // IN
|
||||
{0x4D, 0x46, 0x58, 0x00, 0x00}, // MFX
|
||||
};
|
||||
{
|
||||
0x46,
|
||||
0x50,
|
||||
0x53,
|
||||
0x00,
|
||||
0x00
|
||||
}, // FPS
|
||||
{
|
||||
0x54,
|
||||
0x45,
|
||||
0x4D,
|
||||
0x50,
|
||||
0x4F
|
||||
}, // TEMPO
|
||||
{
|
||||
0x54,
|
||||
0x49,
|
||||
0x4D,
|
||||
0x45,
|
||||
0x00
|
||||
}, // TIME
|
||||
{
|
||||
0x44,
|
||||
0x45,
|
||||
0x4D,
|
||||
0x4F,
|
||||
0x00
|
||||
}, // DEMO
|
||||
{
|
||||
0x4C,
|
||||
0x49,
|
||||
0x56,
|
||||
0x45,
|
||||
0x00
|
||||
}, // LIVE
|
||||
{
|
||||
0x52,
|
||||
0x41,
|
||||
0x4E,
|
||||
0x44,
|
||||
0x00
|
||||
}, // RAND
|
||||
{
|
||||
0x53,
|
||||
0x52,
|
||||
0x43,
|
||||
0x00,
|
||||
0x00
|
||||
}, // SRC
|
||||
{
|
||||
0x46,
|
||||
0x58,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
}, // FX
|
||||
{
|
||||
0x49,
|
||||
0x4E,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
}, // IN
|
||||
{
|
||||
0x4D,
|
||||
0x46,
|
||||
0x58,
|
||||
0x00,
|
||||
0x00
|
||||
}, // MFX
|
||||
};
|
||||
|
||||
vec2 uv2 = uv1;
|
||||
|
||||
@@ -128,21 +187,20 @@ vec4 debug(vec2 vUV)
|
||||
// base frame
|
||||
float f =
|
||||
h_rect(uv2, vec2(-5, -2), vec2(1), 0.1) +
|
||||
h_rect(uv2, vec2(-2, -2), vec2(1), 0.1) +
|
||||
rect(uv2, vec2(-3.5, -2), vec2(0.5, 0.1)) +
|
||||
h_rect(uv2, vec2(-5, 2), vec2(1), 0.1) +
|
||||
h_rect(uv2, vec2(-2, 2), vec2(1), 0.1) +
|
||||
rect(uv2, vec2(-3.5, 2), vec2(0.5, 0.1)) +
|
||||
h_rect(uv2, vec2(2, 0), vec2(1), 0.1) +
|
||||
h_rect(uv2, vec2(5, 0), vec2(1), 0.1) +
|
||||
rect(uv2, vec2(3.5, 0), vec2(0.5, 0.1)) +
|
||||
rect(uv2, vec2(0.55, -2), vec2(1.5, 0.1)) +
|
||||
rect(uv2, vec2(2, -1.55), vec2(0.1, 0.55)) +
|
||||
rect(uv2, vec2(0.55, 2), vec2(1.5, 0.1)) +
|
||||
rect(uv2, vec2(2, 1.55), vec2(0.1, 0.55)) +
|
||||
rect(uv2, vec2(6.8, 0), vec2(0.75, 0.1)) +
|
||||
h_circle(uv2, vec2(7.8, 0), 0.3, 0.1)
|
||||
;
|
||||
h_rect(uv2, vec2(-2, -2), vec2(1), 0.1) +
|
||||
rect(uv2, vec2(-3.5, -2), vec2(0.5, 0.1)) +
|
||||
h_rect(uv2, vec2(-5, 2), vec2(1), 0.1) +
|
||||
h_rect(uv2, vec2(-2, 2), vec2(1), 0.1) +
|
||||
rect(uv2, vec2(-3.5, 2), vec2(0.5, 0.1)) +
|
||||
h_rect(uv2, vec2(2, 0), vec2(1), 0.1) +
|
||||
h_rect(uv2, vec2(5, 0), vec2(1), 0.1) +
|
||||
rect(uv2, vec2(3.5, 0), vec2(0.5, 0.1)) +
|
||||
rect(uv2, vec2(0.55, -2), vec2(1.5, 0.1)) +
|
||||
rect(uv2, vec2(2, -1.55), vec2(0.1, 0.55)) +
|
||||
rect(uv2, vec2(0.55, 2), vec2(1.5, 0.1)) +
|
||||
rect(uv2, vec2(2, 1.55), vec2(0.1, 0.55)) +
|
||||
rect(uv2, vec2(6.8, 0), vec2(0.75, 0.1)) +
|
||||
h_circle(uv2, vec2(7.8, 0), 0.3, 0.1);
|
||||
|
||||
if (iDemo < 1 && iInputFormat1 == YUYV_FOURCC) {
|
||||
f += circle(uv2, vec2(-9, 2), 0.3);
|
||||
@@ -183,14 +241,14 @@ vec4 debug(vec2 vUV)
|
||||
|
||||
// show src/fx
|
||||
|
||||
f += write_5(uv3 * 0.75, vec2(-11.6,-1.8), texts[6]);
|
||||
f += write_5(uv3 * 0.75, vec2(-4.2,-1.8), texts[7]);
|
||||
f += write_5(uv3 * 0.75, vec2(-11.6, -1.8), texts[6]);
|
||||
f += write_5(uv3 * 0.75, vec2(-4.2, -1.8), texts[7]);
|
||||
f += char_at(uv3 * 0.5, vec2(-11.5, 3.5), 0x41);
|
||||
f += char_at(uv3 * 0.5, vec2(-11.5, -6), 0x42);
|
||||
if (iDemo < 1 && (iInputFormat1 == YUYV_FOURCC || iInputFormat2 == YUYV_FOURCC)) {
|
||||
f += write_5(uv3 * 0.75, vec2(-19.7,-1.8), texts[8]);
|
||||
f += write_5(uv3 * 0.75, vec2(-19.7, -1.8), texts[8]);
|
||||
}
|
||||
f += write_5(uv3 * 0.75, vec2(10.9,2), texts[9]);
|
||||
f += write_5(uv3 * 0.75, vec2(10.9, 2), texts[9]);
|
||||
|
||||
// show inputs / feedback
|
||||
float line_a_a = rect(uv2, vec2(-7.5, 2), vec2(1.5, 0.1));
|
||||
@@ -236,21 +294,21 @@ vec4 debug(vec2 vUV)
|
||||
float x = 0;
|
||||
|
||||
x = -15;
|
||||
f += write_5(uv3, vec2(x - 4.5,13), texts[1]);
|
||||
f += write_int(uv3, vec2(x + 1.5,13), int(iTempo), 3);
|
||||
f += write_5(uv3, vec2(x - 4.5, 13), texts[1]);
|
||||
f += write_int(uv3, vec2(x + 1.5, 13), int(iTempo), 3);
|
||||
v = fract(iBeats);
|
||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||
|
||||
x = 15;
|
||||
if (iAutoRand > 0) {
|
||||
f += write_5(uv3, vec2(x - 4.5,13), texts[5]);
|
||||
f += write_int(uv3, vec2(x - 0.5,13), int(iAutoRandCycle), 5);
|
||||
f += write_5(uv3, vec2(x - 4.5, 13), texts[5]);
|
||||
f += write_int(uv3, vec2(x - 0.5, 13), int(iAutoRandCycle), 5);
|
||||
v = fract(iBeats / iAutoRandCycle);
|
||||
} else {
|
||||
f += write_int(uv3, vec2(x - 0.5,13), int(iTime), 5);
|
||||
f += write_int(uv3, vec2(x - 0.5, 13), int(iTime), 5);
|
||||
v = fract(iTime);
|
||||
f += write_5(uv3, vec2(x - 4.5,13), texts[2]);
|
||||
f += write_5(uv3, vec2(x - 4.5, 13), texts[2]);
|
||||
}
|
||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||
|
||||
+40
-6
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Loader generated by glad 2.0.8 on Sun Sep 21 11:51:45 2025
|
||||
* Loader generated by glad 2.0.8 on Wed May 13 21:51:29 2026
|
||||
*
|
||||
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
||||
*
|
||||
* Generator: C/C++
|
||||
* Specification: egl
|
||||
* Extensions: 10
|
||||
* Extensions: 11
|
||||
*
|
||||
* APIs:
|
||||
* - egl=1.5
|
||||
@@ -19,10 +19,10 @@
|
||||
* - ON_DEMAND = False
|
||||
*
|
||||
* Commandline:
|
||||
* --api='egl=1.5' --extensions='EGL_EXT_image_dma_buf_import,EGL_EXT_image_dma_buf_import_modifiers,EGL_KHR_gl_texture_2D_image,EGL_KHR_image,EGL_KHR_image_base,EGL_KHR_platform_android,EGL_KHR_platform_gbm,EGL_KHR_platform_wayland,EGL_KHR_platform_x11,EGL_MESA_drm_image' c --header-only --loader
|
||||
* --api='egl=1.5' --extensions='EGL_EXT_image_dma_buf_import,EGL_EXT_image_dma_buf_import_modifiers,EGL_KHR_debug,EGL_KHR_gl_texture_2D_image,EGL_KHR_image,EGL_KHR_image_base,EGL_KHR_platform_android,EGL_KHR_platform_gbm,EGL_KHR_platform_wayland,EGL_KHR_platform_x11,EGL_MESA_drm_image' c --header-only --loader
|
||||
*
|
||||
* Online:
|
||||
* http://glad.sh/#api=egl%3D1.5&extensions=EGL_EXT_image_dma_buf_import%2CEGL_EXT_image_dma_buf_import_modifiers%2CEGL_KHR_gl_texture_2D_image%2CEGL_KHR_image%2CEGL_KHR_image_base%2CEGL_KHR_platform_android%2CEGL_KHR_platform_gbm%2CEGL_KHR_platform_wayland%2CEGL_KHR_platform_x11%2CEGL_MESA_drm_image&generator=c&options=HEADER_ONLY%2CLOADER
|
||||
* http://glad.sh/#api=egl%3D1.5&extensions=EGL_EXT_image_dma_buf_import%2CEGL_EXT_image_dma_buf_import_modifiers%2CEGL_KHR_debug%2CEGL_KHR_gl_texture_2D_image%2CEGL_KHR_image%2CEGL_KHR_image_base%2CEGL_KHR_platform_android%2CEGL_KHR_platform_gbm%2CEGL_KHR_platform_wayland%2CEGL_KHR_platform_x11%2CEGL_MESA_drm_image&generator=c&options=HEADER_ONLY%2CLOADER
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -201,6 +201,11 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
|
||||
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
|
||||
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
|
||||
#define EGL_CORE_NATIVE_ENGINE 0x305B
|
||||
#define EGL_DEBUG_CALLBACK_KHR 0x33B8
|
||||
#define EGL_DEBUG_MSG_CRITICAL_KHR 0x33B9
|
||||
#define EGL_DEBUG_MSG_ERROR_KHR 0x33BA
|
||||
#define EGL_DEBUG_MSG_INFO_KHR 0x33BC
|
||||
#define EGL_DEBUG_MSG_WARN_KHR 0x33BB
|
||||
#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0)
|
||||
#define EGL_DEPTH_SIZE 0x3025
|
||||
#define EGL_DISPLAY_SCALING 10000
|
||||
@@ -295,6 +300,13 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
|
||||
#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
|
||||
#define EGL_NO_SYNC EGL_CAST(EGLSync,0)
|
||||
#define EGL_NO_TEXTURE 0x305C
|
||||
#define EGL_OBJECT_CONTEXT_KHR 0x33B2
|
||||
#define EGL_OBJECT_DISPLAY_KHR 0x33B1
|
||||
#define EGL_OBJECT_IMAGE_KHR 0x33B4
|
||||
#define EGL_OBJECT_STREAM_KHR 0x33B6
|
||||
#define EGL_OBJECT_SURFACE_KHR 0x33B3
|
||||
#define EGL_OBJECT_SYNC_KHR 0x33B5
|
||||
#define EGL_OBJECT_THREAD_KHR 0x33B0
|
||||
#define EGL_OPENGL_API 0x30A2
|
||||
#define EGL_OPENGL_BIT 0x0008
|
||||
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||
@@ -934,6 +946,8 @@ GLAD_API_CALL int GLAD_EGL_VERSION_1_5;
|
||||
GLAD_API_CALL int GLAD_EGL_EXT_image_dma_buf_import;
|
||||
#define EGL_EXT_image_dma_buf_import_modifiers 1
|
||||
GLAD_API_CALL int GLAD_EGL_EXT_image_dma_buf_import_modifiers;
|
||||
#define EGL_KHR_debug 1
|
||||
GLAD_API_CALL int GLAD_EGL_KHR_debug;
|
||||
#define EGL_KHR_gl_texture_2D_image 1
|
||||
GLAD_API_CALL int GLAD_EGL_KHR_gl_texture_2D_image;
|
||||
#define EGL_KHR_image 1
|
||||
@@ -968,6 +982,7 @@ typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC)(EGLDisp
|
||||
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list);
|
||||
typedef EGLSync (GLAD_API_PTR *PFNEGLCREATESYNCPROC)(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list);
|
||||
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint * attrib_list);
|
||||
typedef EGLint (GLAD_API_PTR *PFNEGLDEBUGMESSAGECONTROLKHRPROC)(EGLDEBUGPROCKHR callback, const EGLAttrib * attrib_list);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYIMAGEPROC)(EGLDisplay dpy, EGLImage image);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYIMAGEKHRPROC)(EGLDisplay dpy, EGLImageKHR image);
|
||||
@@ -985,9 +1000,11 @@ typedef EGLDisplay (GLAD_API_PTR *PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform
|
||||
typedef __eglMustCastToProperFunctionPointerType (GLAD_API_PTR *PFNEGLGETPROCADDRESSPROC)(const char * procname);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLGETSYNCATTRIBPROC)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint * major, EGLint * minor);
|
||||
typedef EGLint (GLAD_API_PTR *PFNEGLLABELOBJECTKHRPROC)(EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLenum (GLAD_API_PTR *PFNEGLQUERYAPIPROC)(void);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint * value);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLQUERYDEBUGKHRPROC)(EGLint attribute, EGLAttrib * value);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLQUERYDMABUFFORMATSEXTPROC)(EGLDisplay dpy, EGLint max_formats, EGLint * formats, EGLint * num_formats);
|
||||
typedef EGLBoolean (GLAD_API_PTR *PFNEGLQUERYDMABUFMODIFIERSEXTPROC)(EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR * modifiers, EGLBoolean * external_only, EGLint * num_modifiers);
|
||||
typedef const char * (GLAD_API_PTR *PFNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
|
||||
@@ -1035,6 +1052,8 @@ GLAD_API_CALL PFNEGLCREATESYNCPROC glad_eglCreateSync;
|
||||
#define eglCreateSync glad_eglCreateSync
|
||||
GLAD_API_CALL PFNEGLCREATEWINDOWSURFACEPROC glad_eglCreateWindowSurface;
|
||||
#define eglCreateWindowSurface glad_eglCreateWindowSurface
|
||||
GLAD_API_CALL PFNEGLDEBUGMESSAGECONTROLKHRPROC glad_eglDebugMessageControlKHR;
|
||||
#define eglDebugMessageControlKHR glad_eglDebugMessageControlKHR
|
||||
GLAD_API_CALL PFNEGLDESTROYCONTEXTPROC glad_eglDestroyContext;
|
||||
#define eglDestroyContext glad_eglDestroyContext
|
||||
GLAD_API_CALL PFNEGLDESTROYIMAGEPROC glad_eglDestroyImage;
|
||||
@@ -1069,12 +1088,16 @@ GLAD_API_CALL PFNEGLGETSYNCATTRIBPROC glad_eglGetSyncAttrib;
|
||||
#define eglGetSyncAttrib glad_eglGetSyncAttrib
|
||||
GLAD_API_CALL PFNEGLINITIALIZEPROC glad_eglInitialize;
|
||||
#define eglInitialize glad_eglInitialize
|
||||
GLAD_API_CALL PFNEGLLABELOBJECTKHRPROC glad_eglLabelObjectKHR;
|
||||
#define eglLabelObjectKHR glad_eglLabelObjectKHR
|
||||
GLAD_API_CALL PFNEGLMAKECURRENTPROC glad_eglMakeCurrent;
|
||||
#define eglMakeCurrent glad_eglMakeCurrent
|
||||
GLAD_API_CALL PFNEGLQUERYAPIPROC glad_eglQueryAPI;
|
||||
#define eglQueryAPI glad_eglQueryAPI
|
||||
GLAD_API_CALL PFNEGLQUERYCONTEXTPROC glad_eglQueryContext;
|
||||
#define eglQueryContext glad_eglQueryContext
|
||||
GLAD_API_CALL PFNEGLQUERYDEBUGKHRPROC glad_eglQueryDebugKHR;
|
||||
#define eglQueryDebugKHR glad_eglQueryDebugKHR
|
||||
GLAD_API_CALL PFNEGLQUERYDMABUFFORMATSEXTPROC glad_eglQueryDmaBufFormatsEXT;
|
||||
#define eglQueryDmaBufFormatsEXT glad_eglQueryDmaBufFormatsEXT
|
||||
GLAD_API_CALL PFNEGLQUERYDMABUFMODIFIERSEXTPROC glad_eglQueryDmaBufModifiersEXT;
|
||||
@@ -1157,6 +1180,7 @@ int GLAD_EGL_VERSION_1_4 = 0;
|
||||
int GLAD_EGL_VERSION_1_5 = 0;
|
||||
int GLAD_EGL_EXT_image_dma_buf_import = 0;
|
||||
int GLAD_EGL_EXT_image_dma_buf_import_modifiers = 0;
|
||||
int GLAD_EGL_KHR_debug = 0;
|
||||
int GLAD_EGL_KHR_gl_texture_2D_image = 0;
|
||||
int GLAD_EGL_KHR_image = 0;
|
||||
int GLAD_EGL_KHR_image_base = 0;
|
||||
@@ -1184,6 +1208,7 @@ PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC glad_eglCreatePlatformPixmapSurface = NULL
|
||||
PFNEGLCREATEPLATFORMWINDOWSURFACEPROC glad_eglCreatePlatformWindowSurface = NULL;
|
||||
PFNEGLCREATESYNCPROC glad_eglCreateSync = NULL;
|
||||
PFNEGLCREATEWINDOWSURFACEPROC glad_eglCreateWindowSurface = NULL;
|
||||
PFNEGLDEBUGMESSAGECONTROLKHRPROC glad_eglDebugMessageControlKHR = NULL;
|
||||
PFNEGLDESTROYCONTEXTPROC glad_eglDestroyContext = NULL;
|
||||
PFNEGLDESTROYIMAGEPROC glad_eglDestroyImage = NULL;
|
||||
PFNEGLDESTROYIMAGEKHRPROC glad_eglDestroyImageKHR = NULL;
|
||||
@@ -1201,9 +1226,11 @@ PFNEGLGETPLATFORMDISPLAYPROC glad_eglGetPlatformDisplay = NULL;
|
||||
PFNEGLGETPROCADDRESSPROC glad_eglGetProcAddress = NULL;
|
||||
PFNEGLGETSYNCATTRIBPROC glad_eglGetSyncAttrib = NULL;
|
||||
PFNEGLINITIALIZEPROC glad_eglInitialize = NULL;
|
||||
PFNEGLLABELOBJECTKHRPROC glad_eglLabelObjectKHR = NULL;
|
||||
PFNEGLMAKECURRENTPROC glad_eglMakeCurrent = NULL;
|
||||
PFNEGLQUERYAPIPROC glad_eglQueryAPI = NULL;
|
||||
PFNEGLQUERYCONTEXTPROC glad_eglQueryContext = NULL;
|
||||
PFNEGLQUERYDEBUGKHRPROC glad_eglQueryDebugKHR = NULL;
|
||||
PFNEGLQUERYDMABUFFORMATSEXTPROC glad_eglQueryDmaBufFormatsEXT = NULL;
|
||||
PFNEGLQUERYDMABUFMODIFIERSEXTPROC glad_eglQueryDmaBufModifiersEXT = NULL;
|
||||
PFNEGLQUERYSTRINGPROC glad_eglQueryString = NULL;
|
||||
@@ -1284,6 +1311,12 @@ static void glad_egl_load_EGL_EXT_image_dma_buf_import_modifiers( GLADuserptrloa
|
||||
glad_eglQueryDmaBufFormatsEXT = (PFNEGLQUERYDMABUFFORMATSEXTPROC) load(userptr, "eglQueryDmaBufFormatsEXT");
|
||||
glad_eglQueryDmaBufModifiersEXT = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC) load(userptr, "eglQueryDmaBufModifiersEXT");
|
||||
}
|
||||
static void glad_egl_load_EGL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
|
||||
if(!GLAD_EGL_KHR_debug) return;
|
||||
glad_eglDebugMessageControlKHR = (PFNEGLDEBUGMESSAGECONTROLKHRPROC) load(userptr, "eglDebugMessageControlKHR");
|
||||
glad_eglLabelObjectKHR = (PFNEGLLABELOBJECTKHRPROC) load(userptr, "eglLabelObjectKHR");
|
||||
glad_eglQueryDebugKHR = (PFNEGLQUERYDEBUGKHRPROC) load(userptr, "eglQueryDebugKHR");
|
||||
}
|
||||
static void glad_egl_load_EGL_KHR_image( GLADuserptrloadfunc load, void* userptr) {
|
||||
if(!GLAD_EGL_KHR_image) return;
|
||||
glad_eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) load(userptr, "eglCreateImageKHR");
|
||||
@@ -1338,6 +1371,7 @@ static int glad_egl_find_extensions_egl(EGLDisplay display) {
|
||||
|
||||
GLAD_EGL_EXT_image_dma_buf_import = glad_egl_has_extension(extensions, "EGL_EXT_image_dma_buf_import");
|
||||
GLAD_EGL_EXT_image_dma_buf_import_modifiers = glad_egl_has_extension(extensions, "EGL_EXT_image_dma_buf_import_modifiers");
|
||||
GLAD_EGL_KHR_debug = glad_egl_has_extension(extensions, "EGL_KHR_debug");
|
||||
GLAD_EGL_KHR_gl_texture_2D_image = glad_egl_has_extension(extensions, "EGL_KHR_gl_texture_2D_image");
|
||||
GLAD_EGL_KHR_image = glad_egl_has_extension(extensions, "EGL_KHR_image");
|
||||
GLAD_EGL_KHR_image_base = glad_egl_has_extension(extensions, "EGL_KHR_image_base");
|
||||
@@ -1409,6 +1443,7 @@ int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void* userp
|
||||
|
||||
if (!glad_egl_find_extensions_egl(display)) return 0;
|
||||
glad_egl_load_EGL_EXT_image_dma_buf_import_modifiers(load, userptr);
|
||||
glad_egl_load_EGL_KHR_debug(load, userptr);
|
||||
glad_egl_load_EGL_KHR_image(load, userptr);
|
||||
glad_egl_load_EGL_KHR_image_base(load, userptr);
|
||||
glad_egl_load_EGL_MESA_drm_image(load, userptr);
|
||||
@@ -1421,7 +1456,7 @@ int gladLoadEGL(EGLDisplay display, GLADloadfunc load) {
|
||||
return gladLoadEGLUserPtr(display, glad_egl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef GLAD_EGL
|
||||
|
||||
@@ -1572,4 +1607,3 @@ void gladLoaderUnloadEGL(void) {
|
||||
#endif
|
||||
|
||||
#endif /* GLAD_EGL_IMPLEMENTATION */
|
||||
|
||||
|
||||
+30
-7
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Loader generated by glad 2.0.8 on Sun Sep 21 13:34:57 2025
|
||||
* Loader generated by glad 2.0.8 on Wed May 13 21:57:23 2026
|
||||
*
|
||||
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
||||
*
|
||||
* Generator: C/C++
|
||||
* Specification: gl
|
||||
* Extensions: 3
|
||||
* Extensions: 4
|
||||
*
|
||||
* APIs:
|
||||
* - gl:compatibility=4.6
|
||||
@@ -19,10 +19,10 @@
|
||||
* - ON_DEMAND = False
|
||||
*
|
||||
* Commandline:
|
||||
* --api='gl:compatibility=4.6' --extensions='GL_ARB_direct_state_access,GL_EXT_EGL_image_storage,GL_EXT_direct_state_access' c --header-only --loader
|
||||
* --api='gl:compatibility=4.6' --extensions='GL_ARB_direct_state_access,GL_EXT_EGL_image_storage,GL_EXT_direct_state_access,GL_KHR_debug' c --header-only --loader
|
||||
*
|
||||
* Online:
|
||||
* http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_direct_state_access%2CGL_EXT_EGL_image_storage%2CGL_EXT_direct_state_access&generator=c&options=HEADER_ONLY%2CLOADER
|
||||
* http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_direct_state_access%2CGL_EXT_EGL_image_storage%2CGL_EXT_direct_state_access%2CGL_KHR_debug&generator=c&options=HEADER_ONLY%2CLOADER
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -2409,6 +2409,8 @@ GLAD_API_CALL int GLAD_GL_ARB_direct_state_access;
|
||||
GLAD_API_CALL int GLAD_GL_EXT_EGL_image_storage;
|
||||
#define GL_EXT_direct_state_access 1
|
||||
GLAD_API_CALL int GLAD_GL_EXT_direct_state_access;
|
||||
#define GL_KHR_debug 1
|
||||
GLAD_API_CALL int GLAD_GL_KHR_debug;
|
||||
|
||||
|
||||
typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum op, GLfloat value);
|
||||
@@ -6396,6 +6398,7 @@ int GLAD_GL_VERSION_4_6 = 0;
|
||||
int GLAD_GL_ARB_direct_state_access = 0;
|
||||
int GLAD_GL_EXT_EGL_image_storage = 0;
|
||||
int GLAD_GL_EXT_direct_state_access = 0;
|
||||
int GLAD_GL_KHR_debug = 0;
|
||||
|
||||
|
||||
|
||||
@@ -9178,6 +9181,20 @@ static void glad_gl_load_GL_EXT_direct_state_access( GLADuserptrloadfunc load, v
|
||||
glad_glVertexArrayVertexBindingDivisorEXT = (PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) load(userptr, "glVertexArrayVertexBindingDivisorEXT");
|
||||
glad_glVertexArrayVertexOffsetEXT = (PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) load(userptr, "glVertexArrayVertexOffsetEXT");
|
||||
}
|
||||
static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
|
||||
if(!GLAD_GL_KHR_debug) return;
|
||||
glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load(userptr, "glDebugMessageCallback");
|
||||
glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load(userptr, "glDebugMessageControl");
|
||||
glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load(userptr, "glDebugMessageInsert");
|
||||
glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load(userptr, "glGetDebugMessageLog");
|
||||
glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load(userptr, "glGetObjectLabel");
|
||||
glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load(userptr, "glGetObjectPtrLabel");
|
||||
glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
|
||||
glad_glObjectLabel = (PFNGLOBJECTLABELPROC) load(userptr, "glObjectLabel");
|
||||
glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load(userptr, "glObjectPtrLabel");
|
||||
glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load(userptr, "glPopDebugGroup");
|
||||
glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load(userptr, "glPushDebugGroup");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9276,6 +9293,7 @@ static int glad_gl_find_extensions_gl(void) {
|
||||
GLAD_GL_ARB_direct_state_access = glad_gl_has_extension(exts, exts_i, "GL_ARB_direct_state_access");
|
||||
GLAD_GL_EXT_EGL_image_storage = glad_gl_has_extension(exts, exts_i, "GL_EXT_EGL_image_storage");
|
||||
GLAD_GL_EXT_direct_state_access = glad_gl_has_extension(exts, exts_i, "GL_EXT_direct_state_access");
|
||||
GLAD_GL_KHR_debug = glad_gl_has_extension(exts, exts_i, "GL_KHR_debug");
|
||||
|
||||
glad_gl_free_extensions(exts_i);
|
||||
|
||||
@@ -9360,6 +9378,7 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
|
||||
glad_gl_load_GL_ARB_direct_state_access(load, userptr);
|
||||
glad_gl_load_GL_EXT_EGL_image_storage(load, userptr);
|
||||
glad_gl_load_GL_EXT_direct_state_access(load, userptr);
|
||||
glad_gl_load_GL_KHR_debug(load, userptr);
|
||||
|
||||
|
||||
|
||||
@@ -9373,7 +9392,7 @@ int gladLoadGL( GLADloadfunc load) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef GLAD_GL
|
||||
|
||||
@@ -9482,7 +9501,9 @@ static void* glad_gl_dlopen_handle(void) {
|
||||
"libGL-1.so",
|
||||
#endif
|
||||
"libGL.so.1",
|
||||
"libGL.so"
|
||||
"libGL.so",
|
||||
"libEGL.so.1",
|
||||
"libEGL.so"
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -9505,6 +9526,9 @@ static struct _glad_gl_userptr glad_gl_build_userptr(void *handle) {
|
||||
#else
|
||||
userptr.gl_get_proc_address_ptr =
|
||||
(GLADglprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB");
|
||||
if (!userptr.gl_get_proc_address_ptr)
|
||||
userptr.gl_get_proc_address_ptr =
|
||||
(GLADglprocaddrfunc) glad_dlsym_handle(handle, "eglGetProcAddress");
|
||||
#endif
|
||||
|
||||
return userptr;
|
||||
@@ -9547,4 +9571,3 @@ void gladLoaderUnloadGL(void) {
|
||||
#endif
|
||||
|
||||
#endif /* GLAD_GL_IMPLEMENTATION */
|
||||
|
||||
|
||||
+79
-71
@@ -6,7 +6,7 @@
|
||||
# (shaders, video devices, textures, midi inputs, etc.)
|
||||
# Every number based constant will be "one-based" (1,2,3,etc.)
|
||||
# To read more, go to
|
||||
# https://github.com/klemek/forge-steel
|
||||
# https://git.klemek.fr/klemek/forge-steel
|
||||
|
||||
|
||||
# ================
|
||||
@@ -24,7 +24,7 @@
|
||||
UNIFORM_TIME=iTime
|
||||
# Current tempo
|
||||
UNIFORM_TEMPO=iTempo
|
||||
# Current total beats
|
||||
# Current total beats
|
||||
UNIFORM_BEATS=iBeats
|
||||
|
||||
# --- uniform int ---
|
||||
@@ -44,8 +44,8 @@ UNIFORM_RESOLUTION=iResolution
|
||||
# --- uniform vec3 ---
|
||||
|
||||
# Midi group X layer Y (beware of group size)
|
||||
# Injected as "iMidiX_Y[Z]"
|
||||
UNIFORM_MIDI_PREFIX=iMidi
|
||||
# Injected as "iGroupX_Y[Z]"
|
||||
UNIFORM_GROUP_PREFIX=iGroup
|
||||
|
||||
# --- uniform sampler2D ---
|
||||
|
||||
@@ -79,9 +79,17 @@ FRAG_OUTPUT=2
|
||||
FRAG_MONITOR=2
|
||||
|
||||
|
||||
# ========
|
||||
# MIDI I/O
|
||||
# ========
|
||||
# ==========
|
||||
# I/O Inputs
|
||||
# ==========
|
||||
# Each code either maps to a midi event or a key code
|
||||
# 0 - 999 -> midi event
|
||||
# Keyboard modifiers are encoded like this:
|
||||
# 1000 -> keyboard event
|
||||
# 10000 -> shift
|
||||
# 100000 -> control
|
||||
# 1000000 -> alt
|
||||
# This means 111082 is control+alt+R
|
||||
|
||||
|
||||
# The recognized ALSA name of the midi device
|
||||
@@ -114,8 +122,8 @@ FADER_16=23
|
||||
# Midi code for tap tempo
|
||||
TAP_TEMPO=46
|
||||
|
||||
# === MIDI INPUT STATES
|
||||
# Midi inputs will control FORGE's state as follows
|
||||
# === GROUP INPUT STATES
|
||||
# Inputs will control FORGE's state as follows
|
||||
# X groups of Y layers sized Z
|
||||
# You can manipulate only 1 layer at a time
|
||||
# Every layer of every groups will be send as uniforms
|
||||
@@ -123,68 +131,68 @@ TAP_TEMPO=46
|
||||
# with the same codes for nice display
|
||||
|
||||
# Total number of groups
|
||||
MIDI_COUNT=1
|
||||
GROUP_COUNT=1
|
||||
|
||||
# Size of group 1
|
||||
MIDI_1_COUNT=20
|
||||
GROUP_1_COUNT=20
|
||||
# Every code of active layer manipulation of group 1
|
||||
MIDI_1_1_X=32
|
||||
MIDI_1_1_Y=48
|
||||
MIDI_1_1_Z=64
|
||||
MIDI_1_2_X=0
|
||||
MIDI_1_2_Y=16
|
||||
MIDI_1_2_Z=
|
||||
MIDI_1_3_X=33
|
||||
MIDI_1_3_Y=49
|
||||
MIDI_1_3_Z=65
|
||||
MIDI_1_4_X=1
|
||||
MIDI_1_4_Y=17
|
||||
MIDI_1_4_Z=
|
||||
MIDI_1_5_X=34
|
||||
MIDI_1_5_Y=50
|
||||
MIDI_1_5_Z=66
|
||||
MIDI_1_6_X=2
|
||||
MIDI_1_6_Y=18
|
||||
MIDI_1_6_Z=
|
||||
MIDI_1_7_X=35
|
||||
MIDI_1_7_Y=51
|
||||
MIDI_1_7_Z=67
|
||||
MIDI_1_8_X=3
|
||||
MIDI_1_8_Y=19
|
||||
MIDI_1_8_Z=
|
||||
MIDI_1_9_X=36
|
||||
MIDI_1_9_Y=52
|
||||
MIDI_1_9_Z=68
|
||||
MIDI_1_10_X=4
|
||||
MIDI_1_10_Y=20
|
||||
MIDI_1_10_Z=
|
||||
MIDI_1_11_X=37
|
||||
MIDI_1_11_Y=53
|
||||
MIDI_1_11_Z=69
|
||||
MIDI_1_12_X=5
|
||||
MIDI_1_12_Y=21
|
||||
MIDI_1_12_Z=
|
||||
MIDI_1_13_X=38
|
||||
MIDI_1_13_Y=54
|
||||
MIDI_1_13_Z=70
|
||||
MIDI_1_14_X=6
|
||||
MIDI_1_14_Y=22
|
||||
MIDI_1_14_Z=
|
||||
MIDI_1_15_X=39
|
||||
MIDI_1_15_Y=55
|
||||
MIDI_1_15_Z=71
|
||||
MIDI_1_16_X=7
|
||||
MIDI_1_16_Y=23
|
||||
MIDI_1_16_Z=
|
||||
MIDI_1_17_X=58
|
||||
MIDI_1_17_Y=59
|
||||
MIDI_1_17_Z=
|
||||
MIDI_1_18_X=60
|
||||
MIDI_1_18_Y=61
|
||||
MIDI_1_18_Z=62
|
||||
MIDI_1_19_X=43
|
||||
MIDI_1_19_Y=44
|
||||
MIDI_1_19_Z=42
|
||||
MIDI_1_20_X=41
|
||||
MIDI_1_20_Y=45
|
||||
MIDI_1_20_Z=
|
||||
GROUP_1_1_X=32
|
||||
GROUP_1_1_Y=48
|
||||
GROUP_1_1_Z=64
|
||||
GROUP_1_2_X=0
|
||||
GROUP_1_2_Y=16
|
||||
GROUP_1_2_Z=
|
||||
GROUP_1_3_X=33
|
||||
GROUP_1_3_Y=49
|
||||
GROUP_1_3_Z=65
|
||||
GROUP_1_4_X=1
|
||||
GROUP_1_4_Y=17
|
||||
GROUP_1_4_Z=
|
||||
GROUP_1_5_X=34
|
||||
GROUP_1_5_Y=50
|
||||
GROUP_1_5_Z=66
|
||||
GROUP_1_6_X=2
|
||||
GROUP_1_6_Y=18
|
||||
GROUP_1_6_Z=
|
||||
GROUP_1_7_X=35
|
||||
GROUP_1_7_Y=51
|
||||
GROUP_1_7_Z=67
|
||||
GROUP_1_8_X=3
|
||||
GROUP_1_8_Y=19
|
||||
GROUP_1_8_Z=
|
||||
GROUP_1_9_X=36
|
||||
GROUP_1_9_Y=52
|
||||
GROUP_1_9_Z=68
|
||||
GROUP_1_10_X=4
|
||||
GROUP_1_10_Y=20
|
||||
GROUP_1_10_Z=
|
||||
GROUP_1_11_X=37
|
||||
GROUP_1_11_Y=53
|
||||
GROUP_1_11_Z=69
|
||||
GROUP_1_12_X=5
|
||||
GROUP_1_12_Y=21
|
||||
GROUP_1_12_Z=
|
||||
GROUP_1_13_X=38
|
||||
GROUP_1_13_Y=54
|
||||
GROUP_1_13_Z=70
|
||||
GROUP_1_14_X=6
|
||||
GROUP_1_14_Y=22
|
||||
GROUP_1_14_Z=
|
||||
GROUP_1_15_X=39
|
||||
GROUP_1_15_Y=55
|
||||
GROUP_1_15_Z=71
|
||||
GROUP_1_16_X=7
|
||||
GROUP_1_16_Y=23
|
||||
GROUP_1_16_Z=
|
||||
GROUP_1_17_X=58
|
||||
GROUP_1_17_Y=59
|
||||
GROUP_1_17_Z=
|
||||
GROUP_1_18_X=60
|
||||
GROUP_1_18_Y=61
|
||||
GROUP_1_18_Z=62
|
||||
GROUP_1_19_X=43
|
||||
GROUP_1_19_Y=44
|
||||
GROUP_1_19_Z=42
|
||||
GROUP_1_20_X=41
|
||||
GROUP_1_20_Y=45
|
||||
GROUP_1_20_Z=
|
||||
|
||||
+29
-29
@@ -12,31 +12,31 @@ uniform int iFPS; // output window frames per seconds
|
||||
uniform int iDemo; // 0/1 if demo mode
|
||||
uniform int iSeed1; // a random seed assigned at start
|
||||
uniform vec2 iResolution; // output window resolution in pixels
|
||||
uniform vec3 iMidi1_1[20]; // all midi inputs defined
|
||||
uniform vec3 iGroup1_1[20]; // all midi inputs defined
|
||||
uniform sampler2D iTex0; // available texture (this code output, so feedback)
|
||||
|
||||
void main() {
|
||||
// all available buttons and faders
|
||||
vec3 b1 = iMidi1_1[0];
|
||||
vec2 f1 = iMidi1_1[1].xy;
|
||||
vec3 b2 = iMidi1_1[2];
|
||||
vec2 f2 = iMidi1_1[3].xy;
|
||||
vec3 b3 = iMidi1_1[4];
|
||||
vec2 f3 = iMidi1_1[5].xy;
|
||||
vec3 b4 = iMidi1_1[6];
|
||||
vec2 f4 = iMidi1_1[7].xy;
|
||||
vec3 b5 = iMidi1_1[8];
|
||||
vec2 f5 = iMidi1_1[9].xy;
|
||||
vec3 b6 = iMidi1_1[10];
|
||||
vec2 f6 = iMidi1_1[11].xy;
|
||||
vec3 b7 = iMidi1_1[12];
|
||||
vec2 f7 = iMidi1_1[13].xy;
|
||||
vec3 b8 = iMidi1_1[14];
|
||||
vec2 f8 = iMidi1_1[15].xy;
|
||||
vec3 b9 = iMidi1_1[16];
|
||||
vec3 b10 = iMidi1_1[17];
|
||||
vec3 b11 = iMidi1_1[18];
|
||||
vec3 b12 = iMidi1_1[19];
|
||||
vec3 b1 = iGroup1_1[0];
|
||||
vec2 f1 = iGroup1_1[1].xy;
|
||||
vec3 b2 = iGroup1_1[2];
|
||||
vec2 f2 = iGroup1_1[3].xy;
|
||||
vec3 b3 = iGroup1_1[4];
|
||||
vec2 f3 = iGroup1_1[5].xy;
|
||||
vec3 b4 = iGroup1_1[6];
|
||||
vec2 f4 = iGroup1_1[7].xy;
|
||||
vec3 b5 = iGroup1_1[8];
|
||||
vec2 f5 = iGroup1_1[9].xy;
|
||||
vec3 b6 = iGroup1_1[10];
|
||||
vec2 f6 = iGroup1_1[11].xy;
|
||||
vec3 b7 = iGroup1_1[12];
|
||||
vec2 f7 = iGroup1_1[13].xy;
|
||||
vec3 b8 = iGroup1_1[14];
|
||||
vec2 f8 = iGroup1_1[15].xy;
|
||||
vec3 b9 = iGroup1_1[16];
|
||||
vec3 b10 = iGroup1_1[17];
|
||||
vec3 b11 = iGroup1_1[18];
|
||||
vec3 b12 = iGroup1_1[19];
|
||||
|
||||
// center UV and scale it to ratio
|
||||
vec2 uv0 = vUV.st;
|
||||
@@ -47,19 +47,19 @@ void main() {
|
||||
float circle_dist = 0.1 + 0.9 * f1.x;
|
||||
float circle_size = 0.1 + 0.9 * f2.x;
|
||||
vec2 circle_pos = circle_dist * vec2(
|
||||
sin(iBeats * 2 * PI),
|
||||
cos(iBeats * 2 * PI)
|
||||
);
|
||||
sin(iBeats * 2 * PI),
|
||||
cos(iBeats * 2 * PI)
|
||||
);
|
||||
float circle = 1 - step(circle_size, length(uv1 - circle_pos));
|
||||
|
||||
// fader 3, 4 and 5 controls the color
|
||||
vec3 color = vec3(
|
||||
f3.x,
|
||||
f4.x,
|
||||
f5.x
|
||||
);
|
||||
f3.x,
|
||||
f4.x,
|
||||
f5.x
|
||||
);
|
||||
vec3 out_color = mix(color, 1 - color, circle);
|
||||
|
||||
// fader 8 controls the feedback value
|
||||
fragColor = mix(vec4(out_color, 1), texture(iTex0, vUV.st), f8.x);
|
||||
}
|
||||
}
|
||||
|
||||
+43
-33
@@ -32,11 +32,13 @@ static void print_help(int status_code) {
|
||||
#ifdef VIDEO_IN
|
||||
"[-vi=FILE] "
|
||||
"[-vs=SIZE] "
|
||||
"[-vb=COUNT] "
|
||||
"[-vr / -nvr] "
|
||||
#endif /* VIDEO_IN */
|
||||
"[-is=SIZE] "
|
||||
"[-ls / -nls] "
|
||||
"[-ss / -nss] "
|
||||
"[-mr / -nmr] "
|
||||
"[-tm] "
|
||||
"[-tf] "
|
||||
"\n\n"
|
||||
@@ -62,6 +64,8 @@ static void print_help(int status_code) {
|
||||
#ifdef VIDEO_IN
|
||||
" -vi, --video-in path to video capture device (multiple "
|
||||
"allowed)\n"
|
||||
" -vb, --video-buffers number of video buffers to use (default: "
|
||||
"2)\n"
|
||||
" -vs, --video-size video capture desired height (default: "
|
||||
"internal texture height)\n"
|
||||
" -vr, --video-reconnect auto-reconnect video (default)\n"
|
||||
@@ -72,6 +76,8 @@ static void print_help(int status_code) {
|
||||
" -nls, --no-load-state do not load saved state\n"
|
||||
" -ss, --save-state save state (default)\n"
|
||||
" -nss, --no-save-state do not save state\n"
|
||||
" -mr, --midi-reconnect auto-reconnect midi (default)\n"
|
||||
" -nmr, --no-midi-reconnect do not auto-reconnect midi\n"
|
||||
" -tm, --trace-midi print midi code and values\n"
|
||||
" -tf, --trace-fps print fps status of subsystems\n");
|
||||
exit(status_code);
|
||||
@@ -131,12 +137,16 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
||||
params->demo = false;
|
||||
params->auto_random = false;
|
||||
params->auto_random_cycle = 4;
|
||||
#ifdef VIDEO_IN
|
||||
params->video_in.length = 0;
|
||||
params->video_buffers = 2;
|
||||
params->video_size = 0;
|
||||
params->video_reconnect = true;
|
||||
#endif /* VIDEO_IN */
|
||||
params->internal_size = 720;
|
||||
params->load_state = true;
|
||||
params->save_state = true;
|
||||
params->midi_reconnect = true;
|
||||
params->trace_midi = false;
|
||||
params->trace_fps = false;
|
||||
|
||||
@@ -180,38 +190,6 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
||||
if (params->auto_random_cycle == 0) {
|
||||
invalid_value(arg, value);
|
||||
}
|
||||
} else if (is_arg(arg, "-vi") || is_arg(arg, "--video-in")) {
|
||||
#ifdef VIDEO_IN
|
||||
if (params->video_in.length == MAX_VIDEO) {
|
||||
log_error("maximum video input reached");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strlcpy(params->video_in.values[params->video_in.length++], value,
|
||||
STR_LEN);
|
||||
#else
|
||||
invalid_arg(arg);
|
||||
#endif /* VIDEO_IN */
|
||||
} else if (is_arg(arg, "-vs") || is_arg(arg, "--video-size")) {
|
||||
#ifdef VIDEO_IN
|
||||
params->video_size = parse_uint(arg, value);
|
||||
if (params->video_size == 0) {
|
||||
invalid_value(arg, value);
|
||||
}
|
||||
#else
|
||||
invalid_arg(arg);
|
||||
#endif /* VIDEO_IN */
|
||||
} else if (is_arg(arg, "-vr") || is_arg(arg, "--video-reconnect")) {
|
||||
#ifdef VIDEO_IN
|
||||
params->video_reconnect = true;
|
||||
#else
|
||||
invalid_arg(arg);
|
||||
#endif /* VIDEO_IN */
|
||||
} else if (is_arg(arg, "-nvr") || is_arg(arg, "--no-video-reconnect")) {
|
||||
#ifdef VIDEO_IN
|
||||
params->video_reconnect = false;
|
||||
#else
|
||||
invalid_arg(arg);
|
||||
#endif /* VIDEO_IN */
|
||||
} else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) {
|
||||
params->internal_size = parse_uint(arg, value);
|
||||
if (params->internal_size == 0) {
|
||||
@@ -225,12 +203,43 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
||||
params->save_state = true;
|
||||
} else if (is_arg(arg, "-nss") || is_arg(arg, "--no-save-state")) {
|
||||
params->save_state = false;
|
||||
} else if (is_arg(arg, "-mr") || is_arg(arg, "--midi-reconnect")) {
|
||||
params->midi_reconnect = true;
|
||||
} else if (is_arg(arg, "-nmr") || is_arg(arg, "--no-midi-reconnect")) {
|
||||
params->midi_reconnect = false;
|
||||
} else if (is_arg(arg, "-tm") || is_arg(arg, "--trace-midi")) {
|
||||
params->trace_midi = true;
|
||||
} else if (is_arg(arg, "-tf") || is_arg(arg, "--trace-fps")) {
|
||||
params->trace_fps = true;
|
||||
} else {
|
||||
#ifdef VIDEO_IN
|
||||
if (is_arg(arg, "-vi") || is_arg(arg, "--video-in")) {
|
||||
if (params->video_in.length == MAX_VIDEO) {
|
||||
log_error("maximum video input reached");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strlcpy(params->video_in.values[params->video_in.length++], value,
|
||||
STR_LEN);
|
||||
} else if (is_arg(arg, "-vb") || is_arg(arg, "--video-buffers")) {
|
||||
params->video_buffers = parse_uint(arg, value);
|
||||
if (params->video_buffers == 0) {
|
||||
invalid_value(arg, value);
|
||||
}
|
||||
} else if (is_arg(arg, "-vs") || is_arg(arg, "--video-size")) {
|
||||
params->video_size = parse_uint(arg, value);
|
||||
if (params->video_size == 0) {
|
||||
invalid_value(arg, value);
|
||||
}
|
||||
} else if (is_arg(arg, "-vr") || is_arg(arg, "--video-reconnect")) {
|
||||
params->video_reconnect = true;
|
||||
} else if (is_arg(arg, "-nvr") || is_arg(arg, "--no-video-reconnect")) {
|
||||
params->video_reconnect = false;
|
||||
} else {
|
||||
invalid_arg(arg);
|
||||
}
|
||||
#else
|
||||
invalid_arg(arg);
|
||||
#endif /* VIDEO_IN */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,8 +248,9 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
||||
log_error("monitor screen cannot be the same as output screen");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
if (params->video_size == 0) {
|
||||
params->video_size = params->internal_size;
|
||||
}
|
||||
#endif /* VIDEO_IN */
|
||||
}
|
||||
|
||||
+152
-104
@@ -1,5 +1,6 @@
|
||||
#include <log.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -14,7 +15,6 @@
|
||||
#include "midi.h"
|
||||
#include "project.h"
|
||||
#include "shaders.h"
|
||||
#include "shared.h"
|
||||
#include "state.h"
|
||||
#include "tempo.h"
|
||||
#include "timer.h"
|
||||
@@ -22,15 +22,18 @@
|
||||
#include "window.h"
|
||||
|
||||
static Parameters init_params;
|
||||
static SharedContext *context;
|
||||
static Context context;
|
||||
static ShaderProgram program;
|
||||
static Window *window_output;
|
||||
static Window *window_monitor;
|
||||
static Timer timer;
|
||||
static MidiDevice midi;
|
||||
static bool trace_midi;
|
||||
static Project project;
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
static VideoCaptureArray video_captures;
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
static void compute_fps() {
|
||||
double fps;
|
||||
char title[STR_LEN];
|
||||
@@ -52,103 +55,108 @@ static void compute_fps() {
|
||||
window_update_title(window_monitor, title);
|
||||
}
|
||||
|
||||
context->fps = (unsigned int)round(fps);
|
||||
context.fps = (unsigned int)round(fps);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_context() {
|
||||
context = shared_init_context("/" PACKAGE "_context");
|
||||
context.stop = false;
|
||||
|
||||
context->stop = false;
|
||||
|
||||
state_init(context, &project.state_config, init_params.demo,
|
||||
state_init(&context, project.state_config, init_params.demo,
|
||||
init_params.auto_random, init_params.auto_random_cycle,
|
||||
init_params.base_tempo, init_params.load_state);
|
||||
|
||||
memset(context->input_resolutions, 0, sizeof(context->input_resolutions));
|
||||
#ifdef VIDEO_IN
|
||||
memset(context.input_resolutions, 0, sizeof(context.input_resolutions));
|
||||
memset(context.input_formats, 0, sizeof(context.input_formats));
|
||||
memset(context.input_fps, 0, sizeof(context.input_fps));
|
||||
memset(context.input_index, 0, sizeof(context.input_index));
|
||||
#endif /* VIDEO_IN */
|
||||
}
|
||||
|
||||
static void free_context() { shared_close_context(context); }
|
||||
|
||||
static void reload_shader(unsigned int i) {
|
||||
shaders_update(&program, &project.fragment_shaders[i][0], i, &project);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
|
||||
static void init_inputs() {
|
||||
context->inputs.length = init_params.video_in.length;
|
||||
video_captures.length = init_params.video_in.length;
|
||||
|
||||
for (unsigned int i = 0; i < init_params.video_in.length; i++) {
|
||||
video_init(&context->inputs.values[i], init_params.video_in.values[i],
|
||||
init_params.video_size);
|
||||
video_init(&video_captures.values[i], init_params.video_in.values[i],
|
||||
init_params.video_size, init_params.video_buffers);
|
||||
|
||||
if (!context->inputs.values[i].error) {
|
||||
context->input_resolutions[i][0] = context->inputs.values[i].width;
|
||||
context->input_resolutions[i][1] = context->inputs.values[i].height;
|
||||
context->inputs.values[i].needs_reload = false;
|
||||
context->inputs.values[i].disconnected = false;
|
||||
if (!video_captures.values[i].error) {
|
||||
context.input_resolutions[i][0] = video_captures.values[i].width;
|
||||
context.input_resolutions[i][1] = video_captures.values[i].height;
|
||||
context.input_formats[i] = video_captures.values[i].pixelformat;
|
||||
video_captures.values[i].needs_reload = false;
|
||||
video_captures.values[i].disconnected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool reconnect_video_captures() {
|
||||
for (unsigned int i = 0; i < init_params.video_in.length; i++) {
|
||||
if (context->inputs.values[i].disconnected) {
|
||||
video_init(&context->inputs.values[i], init_params.video_in.values[i],
|
||||
init_params.video_size);
|
||||
static void start_video_background_read(VideoCapture *video_capture,
|
||||
Context *context, int input_index,
|
||||
bool trace_fps) {
|
||||
pthread_t thread;
|
||||
struct VideoBackgroundReadArgs *process_args =
|
||||
(struct VideoBackgroundReadArgs *)malloc(
|
||||
sizeof(struct VideoBackgroundReadArgs));
|
||||
process_args->capture = video_capture;
|
||||
process_args->context = context;
|
||||
process_args->input_index = input_index;
|
||||
process_args->trace_fps = trace_fps;
|
||||
pthread_create(&thread, NULL, video_background_read, (void *)process_args);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
|
||||
if (!context->inputs.values[i].error) {
|
||||
context->input_resolutions[i][0] = context->inputs.values[i].width;
|
||||
context->input_resolutions[i][1] = context->inputs.values[i].height;
|
||||
static void *
|
||||
background_reconnect_video_captures(__attribute__((unused)) void *args) {
|
||||
log_info("background video capture reconnect started");
|
||||
while (!context.stop) {
|
||||
sleep(1);
|
||||
for (unsigned int i = 0; i < init_params.video_in.length; i++) {
|
||||
if (video_captures.values[i].disconnected) {
|
||||
video_free(&video_captures.values[i]);
|
||||
video_init(&video_captures.values[i], init_params.video_in.values[i],
|
||||
init_params.video_size, init_params.video_buffers);
|
||||
|
||||
if (!video_background_read(&context->inputs.values[i], context, i,
|
||||
init_params.trace_fps)) {
|
||||
return false;
|
||||
if (!video_captures.values[i].error) {
|
||||
context.input_resolutions[i][0] = video_captures.values[i].width;
|
||||
context.input_resolutions[i][1] = video_captures.values[i].height;
|
||||
context.input_formats[i] = video_captures.values[i].pixelformat;
|
||||
video_captures.values[i].needs_reload = true;
|
||||
video_captures.values[i].disconnected = false;
|
||||
start_video_background_read(&video_captures.values[i], &context, i,
|
||||
init_params.trace_fps);
|
||||
}
|
||||
|
||||
context->inputs.values[i].needs_reload = true;
|
||||
context->inputs.values[i].disconnected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
static bool start_video_captures() {
|
||||
pid_t pid;
|
||||
for (unsigned int i = 0; i < context->inputs.length; i++) {
|
||||
if (!context->inputs.values[i].error &&
|
||||
!video_background_read(&context->inputs.values[i], context, i,
|
||||
init_params.trace_fps)) {
|
||||
return false;
|
||||
static void start_video_captures() {
|
||||
pthread_t thread;
|
||||
for (unsigned int i = 0; i < video_captures.length; i++) {
|
||||
if (!video_captures.values[i].error) {
|
||||
start_video_background_read(&video_captures.values[i], &context, i,
|
||||
init_params.trace_fps);
|
||||
}
|
||||
}
|
||||
if (!init_params.video_reconnect) {
|
||||
return true;
|
||||
if (init_params.video_reconnect) {
|
||||
pthread_create(&thread, NULL, background_reconnect_video_captures, NULL);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Could not create subprocess");
|
||||
return false;
|
||||
}
|
||||
if (pid == 0) {
|
||||
return true;
|
||||
}
|
||||
log_info("background reconnect acquisition started (pid: %d)", pid);
|
||||
while (!context->stop) {
|
||||
sleep(1);
|
||||
if (!reconnect_video_captures()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void free_video_captures() {
|
||||
for (unsigned int i = 0; i < context->inputs.length; i++) {
|
||||
for (unsigned int i = 0; i < video_captures.length; i++) {
|
||||
shaders_free_input(&program, i);
|
||||
|
||||
video_free(&context->inputs.values[i]);
|
||||
video_free(&video_captures.values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +165,7 @@ static void free_video_captures() {
|
||||
static void error_callback(int error, const char *description) {
|
||||
log_error("[GLFW] %d: %s", error, description);
|
||||
window_terminate();
|
||||
context->stop = true;
|
||||
context.stop = true;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -173,13 +181,66 @@ static void key_callback(Window *window, int key,
|
||||
log_info("[ESC] Closing...");
|
||||
window_close(window);
|
||||
} else if (event > 0) {
|
||||
state_key_event(context, &project.state_config, event, &midi);
|
||||
state_key_event(&context, project.state_config, event, midi);
|
||||
}
|
||||
}
|
||||
|
||||
static void midi_callback(unsigned char code, unsigned char value) {
|
||||
state_midi_event(context, &project.state_config, &midi, code, value,
|
||||
trace_midi);
|
||||
state_midi_event(&context, project.state_config, midi, code, value,
|
||||
init_params.trace_midi);
|
||||
}
|
||||
|
||||
static void start_state_background_write() {
|
||||
pthread_t thread;
|
||||
struct StateBackgroundWriteArgs *process_args =
|
||||
(struct StateBackgroundWriteArgs *)malloc(
|
||||
sizeof(struct StateBackgroundWriteArgs));
|
||||
process_args->context = &context;
|
||||
process_args->state_config = project.state_config;
|
||||
process_args->midi = &midi;
|
||||
pthread_create(&thread, NULL, state_background_write, process_args);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
|
||||
static void start_midi_background_listen() {
|
||||
pthread_t thread;
|
||||
struct MidiBackgroundListenArgs *process_args =
|
||||
(struct MidiBackgroundListenArgs *)malloc(
|
||||
sizeof(struct MidiBackgroundListenArgs));
|
||||
process_args->device = &midi;
|
||||
process_args->context = &context;
|
||||
process_args->event_callback = midi_callback;
|
||||
pthread_create(&thread, NULL, midi_background_listen, process_args);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
|
||||
static void *background_reconnect_midi(__attribute__((unused)) void *args) {
|
||||
log_info("background midi reconnect started");
|
||||
while (!context.stop) {
|
||||
sleep(1);
|
||||
if (!midi.connected) {
|
||||
midi_open(&midi, config_file_get_str(&project.config, "MIDI_HW", "hw"));
|
||||
if (midi.connected) {
|
||||
start_midi_background_listen();
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
static void init_midi() {
|
||||
pthread_t thread;
|
||||
|
||||
midi_open(&midi, config_file_get_str(&project.config, "MIDI_HW", "hw"));
|
||||
|
||||
if (midi.connected) {
|
||||
start_midi_background_listen();
|
||||
}
|
||||
|
||||
if (init_params.midi_reconnect) {
|
||||
pthread_create(&thread, NULL, background_reconnect_midi, NULL);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
}
|
||||
|
||||
static bool init(const Parameters *params) {
|
||||
@@ -196,38 +257,24 @@ static bool init(const Parameters *params) {
|
||||
#ifdef VIDEO_IN
|
||||
init_inputs();
|
||||
|
||||
if (!start_video_captures()) {
|
||||
return false;
|
||||
}
|
||||
start_video_captures();
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
midi_open(&midi, config_file_get_str(&project.config, "MIDI_HW", "hw"));
|
||||
init_midi();
|
||||
|
||||
if (midi.error) {
|
||||
context->demo = true;
|
||||
} else {
|
||||
trace_midi = params->trace_midi;
|
||||
|
||||
if (!midi_background_listen(&midi, context, midi_callback)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!state_background_write(context, &project.state_config, &midi)) {
|
||||
return false;
|
||||
}
|
||||
start_state_background_write();
|
||||
|
||||
window_startup(error_callback);
|
||||
|
||||
context->tex_resolution[1] = params->internal_size;
|
||||
context.tex_resolution[1] = params->internal_size;
|
||||
|
||||
if (params->output) {
|
||||
window_output = window_init(PACKAGE " " VERSION, params->output_screen,
|
||||
params->windowed, NULL, key_callback);
|
||||
|
||||
window_use(window_output, context);
|
||||
window_use(window_output, &context);
|
||||
|
||||
shaders_init(&program, &project, context, false);
|
||||
shaders_init(&program, &project, &context, false);
|
||||
} else {
|
||||
window_output = NULL;
|
||||
}
|
||||
@@ -237,19 +284,20 @@ static bool init(const Parameters *params) {
|
||||
window_init(PACKAGE " " VERSION " (monitor)", params->monitor_screen,
|
||||
params->windowed, window_output, key_callback);
|
||||
|
||||
window_use(window_monitor, context);
|
||||
window_use(window_monitor, &context);
|
||||
|
||||
shaders_init(&program, &project, context, window_output != NULL);
|
||||
shaders_init(&program, &project, &context, window_output != NULL);
|
||||
} else {
|
||||
window_monitor = NULL;
|
||||
}
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
shaders_link_inputs(&program, &project, &context->inputs);
|
||||
shaders_link_inputs(&program, &project, &video_captures,
|
||||
init_params.video_buffers);
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
if (program.error) {
|
||||
context->stop = true;
|
||||
context.stop = true;
|
||||
window_terminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -273,10 +321,10 @@ static bool loop() {
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
if (init_params.video_reconnect) {
|
||||
for (unsigned int i = 0; i < context->inputs.length; i++) {
|
||||
if (context->inputs.values[i].needs_reload) {
|
||||
shaders_relink_input(&program, &project, &context->inputs, i);
|
||||
context->inputs.values[i].needs_reload = false;
|
||||
for (unsigned int i = 0; i < video_captures.length; i++) {
|
||||
if (video_captures.values[i].needs_reload) {
|
||||
shaders_relink_input(&program, &project, &video_captures, i);
|
||||
video_captures.values[i].needs_reload = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,21 +332,21 @@ static bool loop() {
|
||||
|
||||
compute_fps();
|
||||
|
||||
context->time = window_get_time();
|
||||
context->tempo_total = (float)tempo_total(&context->tempo);
|
||||
context.time = window_get_time();
|
||||
context.tempo_total = (float)tempo_total(&context.tempo);
|
||||
|
||||
if (window_output != NULL) {
|
||||
window_use(window_output, context);
|
||||
window_use(window_output, &context);
|
||||
|
||||
shaders_compute(&program, context, false, false);
|
||||
shaders_compute(&program, &context, false, false);
|
||||
|
||||
window_refresh(window_output);
|
||||
}
|
||||
|
||||
if (window_monitor != NULL) {
|
||||
window_use(window_monitor, context);
|
||||
window_use(window_monitor, &context);
|
||||
|
||||
shaders_compute(&program, context, true, window_output != NULL);
|
||||
shaders_compute(&program, &context, true, window_output != NULL);
|
||||
|
||||
window_refresh(window_monitor);
|
||||
}
|
||||
@@ -309,22 +357,22 @@ static bool loop() {
|
||||
}
|
||||
|
||||
static void shutdown() {
|
||||
context->stop = true;
|
||||
context.stop = true;
|
||||
|
||||
if (init_params.save_state) {
|
||||
state_save(context, &project.state_config);
|
||||
state_save(&context, project.state_config);
|
||||
}
|
||||
|
||||
shaders_free(&program);
|
||||
|
||||
if (window_output != NULL) {
|
||||
window_use(window_output, context);
|
||||
window_use(window_output, &context);
|
||||
|
||||
shaders_free_window(&program, false);
|
||||
}
|
||||
|
||||
if (window_monitor != NULL) {
|
||||
window_use(window_monitor, context);
|
||||
window_use(window_monitor, &context);
|
||||
|
||||
shaders_free_window(&program, init_params.output);
|
||||
}
|
||||
@@ -333,7 +381,7 @@ static void shutdown() {
|
||||
free_video_captures();
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
free_context();
|
||||
midi_close(&midi);
|
||||
|
||||
project_free(&project);
|
||||
|
||||
|
||||
+39
-26
@@ -1,6 +1,6 @@
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <log.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
@@ -13,14 +13,17 @@ void midi_open(MidiDevice *device, const char *name) {
|
||||
|
||||
snd_rawmidi_open(&device->input, &device->output, name, SND_RAWMIDI_NONBLOCK);
|
||||
|
||||
device->error = device->input == NULL || device->output == NULL;
|
||||
device->connected = device->input != NULL && device->output != NULL;
|
||||
|
||||
log_info("(%s) MIDI open", name);
|
||||
if (device->connected) {
|
||||
log_info("(%s) MIDI open", name);
|
||||
} else {
|
||||
log_warn("(%s) MIDI open failed", name);
|
||||
}
|
||||
}
|
||||
|
||||
void midi_write(const MidiDevice *device, unsigned char code,
|
||||
unsigned char value) {
|
||||
if (device->error) {
|
||||
void midi_write(MidiDevice device, unsigned char code, unsigned char value) {
|
||||
if (!device.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -30,35 +33,45 @@ void midi_write(const MidiDevice *device, unsigned char code,
|
||||
buffer[1] = code;
|
||||
buffer[2] = value;
|
||||
|
||||
snd_rawmidi_write(device->output, buffer, 3);
|
||||
snd_rawmidi_write(device.output, buffer, 3);
|
||||
}
|
||||
|
||||
bool midi_background_listen(const MidiDevice *device,
|
||||
const SharedContext *context,
|
||||
void (*event_callback)(unsigned char code,
|
||||
unsigned char value)) {
|
||||
pid_t pid;
|
||||
void midi_close(MidiDevice *device) {
|
||||
if (device->connected) {
|
||||
snd_rawmidi_close(device->input);
|
||||
snd_rawmidi_close(device->output);
|
||||
device->connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
void *midi_background_listen(void *args) {
|
||||
MidiBackgroundReadArgs *process_args = (MidiBackgroundReadArgs *)args;
|
||||
MidiDevice *device = process_args->device;
|
||||
Context *context = process_args->context;
|
||||
|
||||
int bytes_read;
|
||||
snd_rawmidi_info_t *info;
|
||||
unsigned char buffer[3];
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Could not create subprocess");
|
||||
return false;
|
||||
}
|
||||
if (pid == 0) {
|
||||
return true;
|
||||
}
|
||||
log_info("(%s) background acquisition started (pid: %d)", device->name, pid);
|
||||
log_info("(%s) background acquisition started", device->name);
|
||||
|
||||
while (!context->stop) {
|
||||
snd_rawmidi_info_malloc(&info);
|
||||
|
||||
while (!context->stop && snd_rawmidi_info(device->output, info) == 0) {
|
||||
bytes_read = snd_rawmidi_read(device->input, buffer, 3);
|
||||
if (bytes_read == 3) {
|
||||
event_callback(buffer[1], buffer[2]);
|
||||
process_args->event_callback(buffer[1], buffer[2]);
|
||||
}
|
||||
}
|
||||
|
||||
log_info("(%s) background acquisition stopped by main thread (pid: %d)",
|
||||
device->name, pid);
|
||||
exit(EXIT_SUCCESS);
|
||||
snd_rawmidi_info_free(info);
|
||||
|
||||
if (context->stop) {
|
||||
log_info("(%s) background acquisition stopped by main thread",
|
||||
device->name);
|
||||
} else {
|
||||
log_info("(%s) background acquisition stopped after error", device->name);
|
||||
midi_close(device);
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
+3
-6
@@ -4,11 +4,8 @@
|
||||
#define MIDI_H
|
||||
|
||||
void midi_open(MidiDevice *device, const char *name);
|
||||
void midi_write(const MidiDevice *device, unsigned char code,
|
||||
unsigned char value);
|
||||
bool midi_background_listen(const MidiDevice *device,
|
||||
const SharedContext *context,
|
||||
void (*event_callback)(unsigned char code,
|
||||
unsigned char value));
|
||||
void midi_write(MidiDevice device, unsigned char code, unsigned char value);
|
||||
void *midi_background_listen(void *args);
|
||||
void midi_close(MidiDevice *device);
|
||||
|
||||
#endif /* MIDI_H */
|
||||
|
||||
+160
-86
@@ -26,7 +26,7 @@
|
||||
|
||||
static const GLuint unused_uniform = (GLuint)-1;
|
||||
|
||||
bool check_glerror_ro(const char *context) {
|
||||
static bool check_glerror_ro(const char *context) {
|
||||
unsigned int code;
|
||||
|
||||
code = glGetError();
|
||||
@@ -39,7 +39,7 @@ bool check_glerror_ro(const char *context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_glerror(ShaderProgram *program, const char *context) {
|
||||
static bool check_glerror(ShaderProgram *program, const char *context) {
|
||||
if (check_glerror_ro(context)) {
|
||||
program->error = true;
|
||||
return true;
|
||||
@@ -47,7 +47,21 @@ bool check_glerror(ShaderProgram *program, const char *context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_eglerror_ro(const char *context) {
|
||||
#ifdef GL_DEBUG
|
||||
|
||||
static void gl_debug_callback(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity,
|
||||
__attribute__((unused)) GLsizei length,
|
||||
const GLchar *message,
|
||||
__attribute__((unused)) const void *userParam) {
|
||||
log_debug("GL Debug: source=%x, type=%x, id=%d, severity=%x, message=%s",
|
||||
source, type, id, severity, message ? message : "(null)");
|
||||
}
|
||||
|
||||
#endif /* GL_DEBUG */
|
||||
|
||||
static bool check_eglerror_ro(const char *context) {
|
||||
#ifdef VIDEO_IN
|
||||
unsigned int code;
|
||||
|
||||
code = eglGetError();
|
||||
@@ -56,11 +70,11 @@ bool check_eglerror_ro(const char *context) {
|
||||
log_warn("EGL Error: %04x (%s)", code, context);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_eglerror(ShaderProgram *program, const char *context) {
|
||||
static bool check_eglerror(ShaderProgram *program, const char *context) {
|
||||
if (check_eglerror_ro(context)) {
|
||||
program->error = true;
|
||||
return true;
|
||||
@@ -68,9 +82,29 @@ bool check_eglerror(ShaderProgram *program, const char *context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
#ifdef EGL_DEBUG
|
||||
|
||||
static void egl_debug_callback(EGLenum error, const char *command,
|
||||
EGLint messageType, EGLLabelKHR threadLabel,
|
||||
EGLLabelKHR objectLabel, const char *message) {
|
||||
log_debug("EGL Debug: error=%04x, command=%s, type=%d, "
|
||||
"thread=%p, object=%p, message=%s",
|
||||
error, command ? command : "(null)", messageType, threadLabel,
|
||||
objectLabel, message ? message : "(null)");
|
||||
}
|
||||
|
||||
#endif /* EGL_DEBUG */
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
static bool init_gl(ShaderProgram *program) {
|
||||
gladLoadGL(glfwGetProcAddress);
|
||||
|
||||
#ifdef GL_DEBUG
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(gl_debug_callback, NULL);
|
||||
#endif /* GL_DEBUG */
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
program->egl_display = glfwGetEGLDisplay();
|
||||
if (program->egl_display == EGL_NO_DISPLAY) {
|
||||
@@ -80,14 +114,27 @@ static bool init_gl(ShaderProgram *program) {
|
||||
}
|
||||
|
||||
gladLoadEGL(program->egl_display, glfwGetProcAddress);
|
||||
|
||||
#ifdef EGL_DEBUG
|
||||
{
|
||||
PFNEGLDEBUGMESSAGECONTROLKHRPROC debug_ctrl =
|
||||
(PFNEGLDEBUGMESSAGECONTROLKHRPROC)glfwGetProcAddress(
|
||||
"eglDebugMessageControlKHR");
|
||||
if (debug_ctrl != NULL) {
|
||||
const EGLAttrib attrib_list[] = {EGL_NONE};
|
||||
debug_ctrl(egl_debug_callback, attrib_list);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* EGL_DEBUG */
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
return !check_glerror(program, "init_gl") &&
|
||||
!check_eglerror(program, "init_gl");
|
||||
}
|
||||
|
||||
static bool init_textures(ShaderProgram *program,
|
||||
const SharedContext *context) {
|
||||
static bool init_textures(ShaderProgram *program, const Context *context) {
|
||||
glGenTextures(program->tex_count, program->textures);
|
||||
if (check_glerror(program, "init_textures/glGenTextures")) {
|
||||
return false;
|
||||
@@ -144,18 +191,20 @@ static void rebind_textures(const ShaderProgram *program) {
|
||||
#ifdef VIDEO_IN
|
||||
static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
|
||||
unsigned int input_index,
|
||||
unsigned int texture_index, bool swap,
|
||||
bool reload) {
|
||||
unsigned int sub_index, bool reload) {
|
||||
unsigned int texture_index =
|
||||
program->tex_count + input_index * program->sub_video_count + sub_index;
|
||||
|
||||
if (reload) {
|
||||
glDeleteTextures(1, program->textures + texture_index);
|
||||
if (check_glerror(program, "link_input_to_texture/glDeleteTextures")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
glGenTextures(1, program->textures + texture_index);
|
||||
if (check_glerror(program, "link_input_to_texture/glGenTextures")) {
|
||||
return false;
|
||||
}
|
||||
glGenTextures(1, program->textures + texture_index);
|
||||
if (check_glerror(program, "link_input_to_texture/glGenTextures")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLImageKHR dma_image;
|
||||
@@ -170,7 +219,7 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
|
||||
EGL_LINUX_DRM_FOURCC_EXT,
|
||||
input->pixelformat,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT,
|
||||
swap ? input->exp_fd_swap : input->exp_fd,
|
||||
input->exp_fd[sub_index],
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
|
||||
0,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT,
|
||||
@@ -183,11 +232,8 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (swap) {
|
||||
program->dma_images_swap[input_index] = dma_image;
|
||||
} else {
|
||||
program->dma_images[input_index] = dma_image;
|
||||
}
|
||||
program->dma_images[input_index * program->sub_video_count + sub_index] =
|
||||
dma_image;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + texture_index);
|
||||
if (check_glerror(program, "link_input_to_texture/glActiveTexture")) {
|
||||
@@ -212,33 +258,35 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("Texture %d linked to %s", texture_index, input->name);
|
||||
log_info("Texture %d linked to %s[%d]", texture_index, input->name,
|
||||
sub_index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool init_input(ShaderProgram *program, const ConfigFile *config,
|
||||
VideoCaptureArray *inputs, unsigned int i, bool reload) {
|
||||
VideoCaptureArray *inputs, unsigned int input_index,
|
||||
bool reload) {
|
||||
unsigned int tex_i;
|
||||
unsigned int sub_index;
|
||||
char name[STR_LEN];
|
||||
|
||||
if (i < inputs->length && !inputs->values[i].error) {
|
||||
snprintf(name, STR_LEN, "IN_%d_OUT", i + 1);
|
||||
if (input_index < inputs->length && input_index < program->in_count &&
|
||||
!inputs->values[input_index].error) {
|
||||
snprintf(name, STR_LEN, "IN_%d_OUT", input_index + 1);
|
||||
tex_i = config_file_get_int(config, name, 0);
|
||||
if (!link_input_to_texture(program, &inputs->values[i], i, tex_i, false,
|
||||
reload)) {
|
||||
return false;
|
||||
}
|
||||
if (inputs->values[i].with_swap) {
|
||||
snprintf(name, STR_LEN, "IN_%d_SWAP_OUT", i + 1);
|
||||
tex_i = config_file_get_int(config, name, 0);
|
||||
if (!link_input_to_texture(program, &inputs->values[i], i, tex_i, true,
|
||||
reload)) {
|
||||
for (sub_index = 0; sub_index < inputs->values[input_index].buf_count;
|
||||
sub_index++) {
|
||||
if (!link_input_to_texture(program, &inputs->values[input_index],
|
||||
input_index, sub_index, reload)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
program->input_tex_map[input_index] = tex_i;
|
||||
program->tex_map[tex_i] =
|
||||
program->tex_count + input_index * program->sub_video_count;
|
||||
} else {
|
||||
log_warn("Cannot link input %d", i + 1);
|
||||
log_warn("Cannot link input %d", input_index + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -488,13 +536,6 @@ static bool init_single_program(ShaderProgram *program, unsigned int i,
|
||||
glGetUniformLocation(program->programs[i], name);
|
||||
}
|
||||
|
||||
prefix = config_file_get_str(config, "UNIFORM_IN_SWAP_PREFIX", "iInputSwap");
|
||||
for (unsigned int j = 0; j < program->in_count; j++) {
|
||||
snprintf(name, STR_LEN, "%s%d", prefix, j + 1);
|
||||
program->iinswap_locations[i * program->in_count + j] =
|
||||
glGetUniformLocation(program->programs[i], name);
|
||||
}
|
||||
|
||||
prefix = config_file_get_str(config, "UNIFORM_SEED_PREFIX", "iSeed");
|
||||
for (unsigned int j = 0; j < program->frag_count; j++) {
|
||||
snprintf(name, STR_LEN, "%s%d", prefix, j + 1);
|
||||
@@ -518,23 +559,24 @@ static bool init_single_program(ShaderProgram *program, unsigned int i,
|
||||
|
||||
if (program->midi_lengths.length == 0) {
|
||||
index1 = 0;
|
||||
for (unsigned int j = 0; j < state_config->midi_active_counts.length; j++) {
|
||||
for (unsigned int k = 0; k < state_config->midi_active_counts.values[j];
|
||||
for (unsigned int j = 0; j < state_config->group_active_counts.length;
|
||||
j++) {
|
||||
for (unsigned int k = 0; k < state_config->group_active_counts.values[j];
|
||||
k++) {
|
||||
program->midi_lengths.values[index1++] =
|
||||
state_config->midi_counts.values[j];
|
||||
state_config->group_counts.values[j];
|
||||
}
|
||||
}
|
||||
program->midi_lengths.length = index1;
|
||||
}
|
||||
|
||||
prefix = config_file_get_str(config, "UNIFORM_MIDI_PREFIX", "iMidi");
|
||||
prefix = config_file_get_str(config, "UNIFORM_GROUP_PREFIX", "iGroup");
|
||||
index2 = 0;
|
||||
for (unsigned int j = 0; j < state_config->midi_active_counts.length; j++) {
|
||||
for (unsigned int k = 0; k < state_config->midi_active_counts.values[j];
|
||||
for (unsigned int j = 0; j < state_config->group_active_counts.length; j++) {
|
||||
for (unsigned int k = 0; k < state_config->group_active_counts.values[j];
|
||||
k++) {
|
||||
snprintf(name, STR_LEN, "%s%d_%d", prefix, j + 1, k + 1);
|
||||
program->imidi_locations[i * program->midi_lengths.length + index2++] =
|
||||
program->igroup_locations[i * program->midi_lengths.length + index2++] =
|
||||
glGetUniformLocation(program->programs[i], name);
|
||||
}
|
||||
}
|
||||
@@ -591,8 +633,7 @@ static bool init_programs(ShaderProgram *program, const ConfigFile *config,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void update_viewport(ShaderProgram *program,
|
||||
const SharedContext *context) {
|
||||
static void update_viewport(ShaderProgram *program, const Context *context) {
|
||||
// viewport changed
|
||||
if (context->resolution[0] != program->last_resolution[0] ||
|
||||
context->resolution[1] != program->last_resolution[1]) {
|
||||
@@ -603,8 +644,7 @@ static void update_viewport(ShaderProgram *program,
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, context->tex_resolution[0],
|
||||
context->tex_resolution[1], 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
check_glerror_ro(
|
||||
"update_viewport/glTexImage2D"); // TODO dont remap input textures
|
||||
check_glerror_ro("update_viewport/glTexImage2D");
|
||||
}
|
||||
program->last_resolution[0] = context->resolution[0];
|
||||
program->last_resolution[1] = context->resolution[1];
|
||||
@@ -637,7 +677,7 @@ static void write_uniform_multi_3f(GLuint location, unsigned int count,
|
||||
}
|
||||
|
||||
static void use_program(const ShaderProgram *program, int i, bool output,
|
||||
const SharedContext *context) {
|
||||
const Context *context) {
|
||||
unsigned int k;
|
||||
unsigned int offset;
|
||||
unsigned int subcount;
|
||||
@@ -680,17 +720,19 @@ static void use_program(const ShaderProgram *program, int i, bool output,
|
||||
context->active[j] + 1);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
|
||||
for (unsigned int j = 0; j < program->in_count; j++) {
|
||||
write_uniform_2f(program->iinres_locations[i * program->in_count + j],
|
||||
&context->input_resolutions[j]);
|
||||
write_uniform_1i(program->iinfmt_locations[i * program->in_count + j],
|
||||
context->inputs.values[j].pixelformat);
|
||||
context->input_formats[j]);
|
||||
write_uniform_1i(program->iinfps_locations[i * program->in_count + j],
|
||||
context->inputs.values[j].fps);
|
||||
write_uniform_1i(program->iinswap_locations[i * program->in_count + j],
|
||||
context->inputs.values[j].swap ? 1 : 0);
|
||||
context->input_fps[j]);
|
||||
}
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
// set seeds uniforms
|
||||
for (unsigned int j = 0; j < program->frag_count; j++) {
|
||||
write_uniform_1i(program->iseed_locations[i * program->frag_count + j],
|
||||
@@ -705,7 +747,7 @@ static void use_program(const ShaderProgram *program, int i, bool output,
|
||||
offset = 0;
|
||||
for (unsigned int j = 0; j < program->midi_lengths.length; j++) {
|
||||
write_uniform_multi_3f(
|
||||
program->imidi_locations[i * program->midi_lengths.length + j],
|
||||
program->igroup_locations[i * program->midi_lengths.length + j],
|
||||
program->midi_lengths.values[j], context->values + offset);
|
||||
offset += program->midi_lengths.values[j];
|
||||
}
|
||||
@@ -732,7 +774,7 @@ static void use_program(const ShaderProgram *program, int i, bool output,
|
||||
// set GL_TEXTURE(X) to uniform sampler2D texX
|
||||
for (unsigned int j = 0; j < program->tex_count; j++) {
|
||||
write_uniform_1i(program->textures_locations[i * program->tex_count + j],
|
||||
j);
|
||||
program->tex_map[j]);
|
||||
}
|
||||
|
||||
// draw output
|
||||
@@ -740,12 +782,17 @@ static void use_program(const ShaderProgram *program, int i, bool output,
|
||||
}
|
||||
|
||||
void shaders_init(ShaderProgram *program, const Project *project,
|
||||
const SharedContext *context, bool rebind) {
|
||||
const Context *context, bool rebind) {
|
||||
unsigned int i;
|
||||
if (!rebind) {
|
||||
program->error = false;
|
||||
program->last_resolution[0] = context->resolution[0];
|
||||
program->last_resolution[1] = context->resolution[1];
|
||||
program->tex_count = config_file_get_int(&project->config, "TEX_COUNT", 9);
|
||||
memset(program->tex_map, 0, sizeof(program->tex_map));
|
||||
for (i = 0; i < program->tex_count; i++) {
|
||||
program->tex_map[i] = i;
|
||||
}
|
||||
program->frag_count = project->frag_count;
|
||||
program->frag_output_index =
|
||||
config_file_get_int(&project->config, "FRAG_OUTPUT", 1) - 1;
|
||||
@@ -755,12 +802,12 @@ void shaders_init(ShaderProgram *program, const Project *project,
|
||||
config_file_get_int(&project->config, "SUB_TYPE_COUNT", 0);
|
||||
program->in_count = config_file_get_int(&project->config, "IN_COUNT", 0);
|
||||
program->sub_variant_count = project->state_config.state_max;
|
||||
program->active_count = project->state_config.midi_active_counts.length;
|
||||
program->active_count = project->state_config.group_active_counts.length;
|
||||
program->midi_lengths.length = 0;
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
memset(program->dma_images, 0, sizeof(program->dma_images));
|
||||
memset(program->dma_images_swap, 0, sizeof(program->dma_images_swap));
|
||||
memset(program->input_tex_map, 0, sizeof(program->input_tex_map));
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
if (!init_gl(program)) {
|
||||
@@ -793,23 +840,55 @@ void shaders_init(ShaderProgram *program, const Project *project,
|
||||
}
|
||||
}
|
||||
|
||||
void shaders_relink_input(ShaderProgram *program, const Project *project,
|
||||
VideoCaptureArray *inputs, unsigned int i) {
|
||||
#ifdef VIDEO_IN
|
||||
// shaders_free_input(program, i);
|
||||
init_input(program, &project->config, inputs, i, true);
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
void shaders_relink_input(ShaderProgram *program, const Project *project,
|
||||
VideoCaptureArray *inputs, unsigned int input_index) {
|
||||
shaders_free_input(program, input_index);
|
||||
init_input(program, &project->config, inputs, input_index, true);
|
||||
}
|
||||
|
||||
void shaders_link_inputs(ShaderProgram *program, const Project *project,
|
||||
VideoCaptureArray *inputs) {
|
||||
#ifdef VIDEO_IN
|
||||
for (unsigned int i = 0; i < program->in_count; i++) {
|
||||
VideoCaptureArray *inputs, unsigned int buffer_count) {
|
||||
unsigned int i;
|
||||
program->sub_video_count = buffer_count;
|
||||
for (i = 0; i < program->in_count; i++) {
|
||||
init_input(program, &project->config, inputs, i, false);
|
||||
}
|
||||
#endif /* VIDEO_IN */
|
||||
}
|
||||
|
||||
void shaders_free_input(ShaderProgram *program, unsigned int input_index) {
|
||||
unsigned int sub_index;
|
||||
for (sub_index = 0; sub_index < program->sub_video_count; sub_index++) {
|
||||
if (program->dma_images[input_index * program->sub_video_count +
|
||||
sub_index] != EGL_NO_IMAGE_KHR) {
|
||||
eglDestroyImageKHR(
|
||||
program->egl_display,
|
||||
program
|
||||
->dma_images[input_index * program->sub_video_count + sub_index]);
|
||||
program->dma_images[input_index * program->sub_video_count + sub_index] =
|
||||
EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
}
|
||||
check_eglerror_ro("shaders_free_input/eglDestroyImageKHR");
|
||||
}
|
||||
|
||||
static void update_inputs_tex_map(ShaderProgram *program,
|
||||
const Context *context) {
|
||||
unsigned int i;
|
||||
unsigned int tex_i;
|
||||
for (i = 0; i < program->in_count; i++) {
|
||||
if (context->input_formats[i] != 0) {
|
||||
tex_i = program->input_tex_map[i];
|
||||
program->tex_map[tex_i] = program->tex_count +
|
||||
i * program->sub_video_count +
|
||||
context->input_index[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
void shaders_update(ShaderProgram *program, const File *fragment_shader,
|
||||
unsigned int i, const Project *project) {
|
||||
if (compile_shader(program->fragment_shaders[i], fragment_shader->path,
|
||||
@@ -820,8 +899,12 @@ void shaders_update(ShaderProgram *program, const File *fragment_shader,
|
||||
}
|
||||
}
|
||||
|
||||
void shaders_compute(ShaderProgram *program, const SharedContext *context,
|
||||
void shaders_compute(ShaderProgram *program, const Context *context,
|
||||
bool monitor, bool output_only) {
|
||||
#ifdef VIDEO_IN
|
||||
update_inputs_tex_map(program, context);
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
if (!output_only) {
|
||||
glBindVertexArray(program->vertex_array[0]);
|
||||
|
||||
@@ -858,6 +941,12 @@ void shaders_free(const ShaderProgram *program) {
|
||||
glDeleteTextures(program->tex_count, program->textures);
|
||||
check_glerror_ro("shaders_free/glDeleteTextures");
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
glDeleteTextures(program->in_count * program->sub_video_count,
|
||||
program->textures + program->tex_count);
|
||||
check_glerror_ro("shaders_free/glDeleteTextures");
|
||||
#endif
|
||||
|
||||
glDeleteBuffers(1, &program->vertex_buffer);
|
||||
check_glerror_ro("shaders_free/glDeleteBuffers");
|
||||
}
|
||||
@@ -866,18 +955,3 @@ void shaders_free_window(const ShaderProgram *program, bool secondary) {
|
||||
glDeleteVertexArrays(1, &program->vertex_array[secondary ? 1 : 0]);
|
||||
check_glerror_ro("shaders_free_window/glDeleteVertexArrays");
|
||||
}
|
||||
|
||||
void shaders_free_input(ShaderProgram *program, unsigned int input_index) {
|
||||
#ifdef VIDEO_IN
|
||||
if (program->dma_images[input_index] != EGL_NO_IMAGE_KHR) {
|
||||
eglDestroyImageKHR(program->egl_display, program->dma_images[input_index]);
|
||||
program->dma_images[input_index] = EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
if (program->dma_images_swap[input_index] != EGL_NO_IMAGE_KHR) {
|
||||
eglDestroyImageKHR(program->egl_display,
|
||||
program->dma_images_swap[input_index]);
|
||||
program->dma_images_swap[input_index] = EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
check_eglerror_ro("shaders_free_input/eglDestroyImageKHR");
|
||||
#endif /* VIDEO_IN */
|
||||
}
|
||||
|
||||
+9
-5
@@ -4,24 +4,28 @@
|
||||
#define SHADERS_H
|
||||
|
||||
void shaders_init(ShaderProgram *program, const Project *project,
|
||||
const SharedContext *context, bool rebind);
|
||||
const Context *context, bool rebind);
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
|
||||
void shaders_relink_input(ShaderProgram *program, const Project *project,
|
||||
VideoCaptureArray *inputs, unsigned int i);
|
||||
|
||||
void shaders_link_inputs(ShaderProgram *program, const Project *project,
|
||||
VideoCaptureArray *inputs);
|
||||
VideoCaptureArray *inputs, unsigned int buffer_count);
|
||||
|
||||
void shaders_free_input(ShaderProgram *program, unsigned int input_index);
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
void shaders_update(ShaderProgram *program, const File *fragment_shader,
|
||||
unsigned int i, const Project *project);
|
||||
|
||||
void shaders_compute(ShaderProgram *program, const SharedContext *context,
|
||||
void shaders_compute(ShaderProgram *program, const Context *context,
|
||||
bool monitor, bool output_only);
|
||||
|
||||
void shaders_free(const ShaderProgram *program);
|
||||
|
||||
void shaders_free_window(const ShaderProgram *program, bool secondary);
|
||||
|
||||
void shaders_free_input(ShaderProgram *program, unsigned int input_index);
|
||||
|
||||
#endif /* SHADERS_H */
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
static void *open_shared(const char *key, size_t size, int *fd) {
|
||||
*fd = shm_open(key, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
ftruncate(*fd, size);
|
||||
|
||||
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
|
||||
}
|
||||
|
||||
static void close_shared(void *shared, size_t size, int fd) {
|
||||
munmap(shared, size);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
SharedContext *shared_init_context(const char *key) {
|
||||
int shared_fd;
|
||||
SharedContext *shared;
|
||||
|
||||
shared = open_shared(key, sizeof(SharedContext), &shared_fd);
|
||||
|
||||
shared->fd = shared_fd;
|
||||
|
||||
return shared;
|
||||
}
|
||||
|
||||
void shared_close_context(SharedContext *shared) {
|
||||
close_shared(shared, sizeof(SharedContext), shared->fd);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#include "types.h"
|
||||
|
||||
#ifndef SHARED_H
|
||||
#define SHARED_H
|
||||
|
||||
SharedContext *shared_init_context(const char *key);
|
||||
void shared_close_context(SharedContext *shared);
|
||||
|
||||
#endif /* SHARED_H */
|
||||
+284
-261
@@ -1,6 +1,6 @@
|
||||
#include <log.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
@@ -13,97 +13,93 @@
|
||||
#include "state.h"
|
||||
#include "tempo.h"
|
||||
|
||||
static void safe_midi_write(const MidiDevice *midi, unsigned int code,
|
||||
static void safe_midi_write(MidiDevice midi, unsigned int code,
|
||||
unsigned char value) {
|
||||
if (code != UNSET_MIDI_CODE) {
|
||||
if (code != UNSET_MIDI_CODE && code < 1000) {
|
||||
midi_write(midi, code, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_page(const SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
const MidiDevice *midi) {
|
||||
static void update_page(const Context *context, StateConfig state_config,
|
||||
MidiDevice midi) {
|
||||
unsigned int page_item_min;
|
||||
unsigned int page_item_max;
|
||||
// SHOW PAGE
|
||||
for (unsigned int i = 0; i < state_config->select_page_codes.length; i++) {
|
||||
safe_midi_write(midi, state_config->select_page_codes.values[i],
|
||||
for (unsigned int i = 0; i < state_config.select_page_codes.length; i++) {
|
||||
safe_midi_write(midi, state_config.select_page_codes.values[i],
|
||||
i == context->page ? MIDI_MAX : 0);
|
||||
}
|
||||
|
||||
// SHOW PAGE ITEM
|
||||
page_item_min = state_config->select_item_codes.length * context->page;
|
||||
page_item_max = page_item_min + state_config->select_item_codes.length;
|
||||
page_item_min = state_config.select_item_codes.length * context->page;
|
||||
page_item_max = page_item_min + state_config.select_item_codes.length;
|
||||
|
||||
if (context->state.values[context->selected] >= page_item_min &&
|
||||
context->state.values[context->selected] < page_item_max) {
|
||||
for (unsigned int i = 0; i < state_config->select_item_codes.length; i++) {
|
||||
safe_midi_write(midi, state_config->select_item_codes.values[i],
|
||||
for (unsigned int i = 0; i < state_config.select_item_codes.length; i++) {
|
||||
safe_midi_write(midi, state_config.select_item_codes.values[i],
|
||||
i == context->state.values[context->selected] -
|
||||
page_item_min
|
||||
? MIDI_MAX
|
||||
: 0);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 0; i < state_config->select_item_codes.length; i++) {
|
||||
safe_midi_write(midi, state_config->select_item_codes.values[i], 0);
|
||||
for (unsigned int i = 0; i < state_config.select_item_codes.length; i++) {
|
||||
safe_midi_write(midi, state_config.select_item_codes.values[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_active(const SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
const MidiDevice *midi) {
|
||||
static void update_active(const Context *context, StateConfig state_config,
|
||||
MidiDevice midi, bool beat_active) {
|
||||
unsigned int k;
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
|
||||
for (unsigned int j = 0; j < state_config->midi_active_counts.values[i];
|
||||
for (unsigned int i = 0; i < state_config.group_active_counts.length; i++) {
|
||||
for (unsigned int j = 0; j < state_config.group_active_counts.values[i];
|
||||
j++) {
|
||||
k = state_config->midi_active_offsets.values[i] + j;
|
||||
safe_midi_write(midi, state_config->midi_active_codes.values[k],
|
||||
context->active[i] == j ? MIDI_MAX : 0);
|
||||
k = state_config.group_active_offsets.values[i] + j;
|
||||
safe_midi_write(midi, state_config.group_active_codes.values[k],
|
||||
context->active[i] == j && beat_active ? MIDI_MAX : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_values(const SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
const MidiDevice *midi) {
|
||||
static void update_values(const Context *context, StateConfig state_config,
|
||||
MidiDevice midi) {
|
||||
unsigned int j;
|
||||
unsigned int k;
|
||||
unsigned int part;
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_codes.length; i++) {
|
||||
for (unsigned int i = 0; i < state_config.codes.length; i++) {
|
||||
j = i / 3;
|
||||
part = arr_uint_remap_index(state_config->midi_offsets, &j);
|
||||
k = state_config->values_offsets.values[part] +
|
||||
context->active[part] * state_config->midi_counts.values[part] + j;
|
||||
safe_midi_write(midi, state_config->midi_codes.values[i],
|
||||
part = arr_uint_remap_index(state_config.group_offsets, &j);
|
||||
k = state_config.values_offsets.values[part] +
|
||||
context->active[part] * state_config.group_counts.values[part] + j;
|
||||
safe_midi_write(midi, state_config.codes.values[i],
|
||||
context->values[k][i % 3] * MIDI_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset(SharedContext *context) {
|
||||
static void reset(Context *context) {
|
||||
memset(context->values, 0, sizeof(context->values));
|
||||
memset(context->state.values, 0, sizeof(context->state.values));
|
||||
}
|
||||
|
||||
static void randomize(SharedContext *context, const StateConfig *state_config) {
|
||||
static void randomize(Context *context, StateConfig state_config) {
|
||||
unsigned int j;
|
||||
unsigned int l;
|
||||
unsigned int part;
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_codes.length; i++) {
|
||||
for (unsigned int i = 0; i < state_config.codes.length; i++) {
|
||||
j = i / 3;
|
||||
part = arr_uint_remap_index(state_config->midi_offsets, &j);
|
||||
for (unsigned int k = 0; k < state_config->midi_active_counts.values[part];
|
||||
part = arr_uint_remap_index(state_config.group_offsets, &j);
|
||||
for (unsigned int k = 0; k < state_config.group_active_counts.values[part];
|
||||
k++) {
|
||||
l = state_config->values_offsets.values[part] +
|
||||
k * state_config->midi_counts.values[part] + j;
|
||||
l = state_config.values_offsets.values[part] +
|
||||
k * state_config.group_counts.values[part] + j;
|
||||
|
||||
if (arr_uint_index_of(state_config->fader_codes,
|
||||
state_config->midi_codes.values[i]) !=
|
||||
ARRAY_NOT_FOUND) {
|
||||
if (arr_uint_index_of(state_config.fader_codes,
|
||||
state_config.codes.values[i]) != ARRAY_NOT_FOUND) {
|
||||
context->values[l][i % 3] = (float)rand_uint(MIDI_MAX + 1) / MIDI_MAX;
|
||||
} else {
|
||||
context->values[l][i % 3] = rand_uint(2) == 1 ? 1 : 0;
|
||||
@@ -112,12 +108,11 @@ static void randomize(SharedContext *context, const StateConfig *state_config) {
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < context->state.length; i++) {
|
||||
context->state.values[i] = rand_uint(state_config->state_max);
|
||||
context->state.values[i] = rand_uint(state_config.state_max);
|
||||
}
|
||||
}
|
||||
|
||||
static void load_from_file(SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
static void load_from_file(Context *context, StateConfig state_config,
|
||||
const char *state_file) {
|
||||
ConfigFile saved_state;
|
||||
char key[STR_LEN];
|
||||
@@ -141,12 +136,12 @@ static void load_from_file(SharedContext *context,
|
||||
context->state.values[i] = config_file_get_int(&saved_state, key, 0);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
|
||||
for (unsigned int i = 0; i < state_config.group_active_counts.length; i++) {
|
||||
snprintf(key, STR_LEN, "active_%d", i);
|
||||
context->active[i] = config_file_get_int(&saved_state, key, 0);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < state_config->value_count; i++) {
|
||||
for (unsigned int i = 0; i < state_config.value_count; i++) {
|
||||
snprintf(key, STR_LEN, "value_%d_x", i);
|
||||
context->values[i][0] =
|
||||
(float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
|
||||
@@ -161,28 +156,25 @@ static void load_from_file(SharedContext *context,
|
||||
config_file_free(&saved_state);
|
||||
}
|
||||
|
||||
static void load_from_default_file(SharedContext *context,
|
||||
const StateConfig *state_config) {
|
||||
static void load_from_default_file(Context *context, StateConfig state_config) {
|
||||
char state_file[STR_LEN];
|
||||
|
||||
snprintf(state_file, STR_LEN, "%s.txt", state_config->save_file_prefix);
|
||||
snprintf(state_file, STR_LEN, "%s.txt", state_config.save_file_prefix);
|
||||
|
||||
load_from_file(context, state_config, state_file);
|
||||
}
|
||||
|
||||
static void load_from_index_file(SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
static void load_from_index_file(Context *context, StateConfig state_config,
|
||||
unsigned int index) {
|
||||
char state_file[STR_LEN];
|
||||
|
||||
snprintf(state_file, STR_LEN, "%s.%d.txt", state_config->save_file_prefix,
|
||||
snprintf(state_file, STR_LEN, "%s.%d.txt", state_config.save_file_prefix,
|
||||
index);
|
||||
|
||||
load_from_file(context, state_config, state_file);
|
||||
}
|
||||
|
||||
static void save_to_file(const SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
static void save_to_file(const Context *context, StateConfig state_config,
|
||||
const char *state_file) {
|
||||
StringArray lines;
|
||||
|
||||
@@ -203,12 +195,12 @@ static void save_to_file(const SharedContext *context,
|
||||
context->state.values[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
|
||||
for (unsigned int i = 0; i < state_config.group_active_counts.length; i++) {
|
||||
snprintf(lines.values[lines.length++], STR_LEN, "active_%d=%d", i,
|
||||
context->active[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < state_config->value_count; i++) {
|
||||
for (unsigned int i = 0; i < state_config.value_count; i++) {
|
||||
snprintf(lines.values[lines.length++], STR_LEN, "value_%d_x=%d", i,
|
||||
(unsigned int)(context->values[i][0] * MIDI_MAX));
|
||||
snprintf(lines.values[lines.length++], STR_LEN, "value_%d_y=%d", i,
|
||||
@@ -220,21 +212,20 @@ static void save_to_file(const SharedContext *context,
|
||||
file_write(state_file, &lines);
|
||||
}
|
||||
|
||||
static void save_to_default_file(const SharedContext *context,
|
||||
const StateConfig *state_config) {
|
||||
static void save_to_default_file(const Context *context,
|
||||
StateConfig state_config) {
|
||||
char state_file[STR_LEN];
|
||||
|
||||
snprintf(state_file, STR_LEN, "%s.txt", state_config->save_file_prefix);
|
||||
snprintf(state_file, STR_LEN, "%s.txt", state_config.save_file_prefix);
|
||||
|
||||
save_to_file(context, state_config, state_file);
|
||||
}
|
||||
|
||||
static void save_to_index_file(const SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
static void save_to_index_file(const Context *context, StateConfig state_config,
|
||||
unsigned int index) {
|
||||
char state_file[STR_LEN];
|
||||
|
||||
snprintf(state_file, STR_LEN, "%s.%d.txt", state_config->save_file_prefix,
|
||||
snprintf(state_file, STR_LEN, "%s.%d.txt", state_config.save_file_prefix,
|
||||
index);
|
||||
|
||||
save_to_file(context, state_config, state_file);
|
||||
@@ -275,62 +266,62 @@ void state_parse_config(StateConfig *state_config, const ConfigFile *config) {
|
||||
config_file_get_int(config, name, UNSET_MIDI_CODE);
|
||||
}
|
||||
|
||||
state_config->midi_active_counts.length = state_config->midi_counts.length =
|
||||
state_config->midi_active_offsets.length =
|
||||
state_config->midi_offsets.length =
|
||||
state_config->group_active_counts.length = state_config->group_counts.length =
|
||||
state_config->group_active_offsets.length =
|
||||
state_config->group_offsets.length =
|
||||
state_config->values_offsets.length =
|
||||
config_file_get_int(config, "MIDI_COUNT", 0);
|
||||
config_file_get_int(config, "GROUP_COUNT", 0);
|
||||
|
||||
count = 0;
|
||||
for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
|
||||
snprintf(name, STR_LEN, "MIDI_%d_ACTIVE_COUNT", i + 1);
|
||||
state_config->midi_active_counts.values[i] =
|
||||
for (unsigned int i = 0; i < state_config->group_active_counts.length; i++) {
|
||||
snprintf(name, STR_LEN, "GROUP_%d_ACTIVE_COUNT", i + 1);
|
||||
state_config->group_active_counts.values[i] =
|
||||
config_file_get_int(config, name, 1);
|
||||
state_config->midi_active_offsets.values[i] = count;
|
||||
count += state_config->midi_active_counts.values[i];
|
||||
state_config->group_active_offsets.values[i] = count;
|
||||
count += state_config->group_active_counts.values[i];
|
||||
}
|
||||
|
||||
state_config->midi_active_codes.length = count;
|
||||
state_config->group_active_codes.length = count;
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
|
||||
for (unsigned int j = 0; j < state_config->midi_active_counts.values[i];
|
||||
for (unsigned int i = 0; i < state_config->group_active_counts.length; i++) {
|
||||
for (unsigned int j = 0; j < state_config->group_active_counts.values[i];
|
||||
j++) {
|
||||
snprintf(name, STR_LEN, "MIDI_%d_ACTIVE_%d", i + 1, j + 1);
|
||||
state_config->midi_active_codes
|
||||
.values[state_config->midi_active_offsets.values[i] + j] =
|
||||
snprintf(name, STR_LEN, "GROUP_%d_ACTIVE_%d", i + 1, j + 1);
|
||||
state_config->group_active_codes
|
||||
.values[state_config->group_active_offsets.values[i] + j] =
|
||||
config_file_get_int(config, name, UNSET_MIDI_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
count = 0;
|
||||
offset = 0;
|
||||
for (unsigned int i = 0; i < state_config->midi_counts.length; i++) {
|
||||
snprintf(name, STR_LEN, "MIDI_%d_COUNT", i + 1);
|
||||
state_config->midi_counts.values[i] = config_file_get_int(config, name, 0);
|
||||
state_config->midi_offsets.values[i] = count;
|
||||
for (unsigned int i = 0; i < state_config->group_counts.length; i++) {
|
||||
snprintf(name, STR_LEN, "GROUP_%d_COUNT", i + 1);
|
||||
state_config->group_counts.values[i] = config_file_get_int(config, name, 0);
|
||||
state_config->group_offsets.values[i] = count;
|
||||
state_config->values_offsets.values[i] = offset;
|
||||
offset += state_config->midi_counts.values[i] *
|
||||
state_config->midi_active_counts.values[i];
|
||||
count += state_config->midi_counts.values[i];
|
||||
offset += state_config->group_counts.values[i] *
|
||||
state_config->group_active_counts.values[i];
|
||||
count += state_config->group_counts.values[i];
|
||||
}
|
||||
|
||||
state_config->value_count = offset;
|
||||
|
||||
state_config->midi_codes.length = count * 3;
|
||||
state_config->codes.length = count * 3;
|
||||
|
||||
for (unsigned int i = 0; i < state_config->midi_counts.length; i++) {
|
||||
offset = state_config->midi_offsets.values[i];
|
||||
for (unsigned int j = 0; j < state_config->midi_counts.values[i]; j++) {
|
||||
snprintf(name, STR_LEN, "MIDI_%d_%d_X", i + 1, j + 1);
|
||||
state_config->midi_codes.values[(offset + j) * 3] =
|
||||
for (unsigned int i = 0; i < state_config->group_counts.length; i++) {
|
||||
offset = state_config->group_offsets.values[i];
|
||||
for (unsigned int j = 0; j < state_config->group_counts.values[i]; j++) {
|
||||
snprintf(name, STR_LEN, "GROUP_%d_%d_X", i + 1, j + 1);
|
||||
state_config->codes.values[(offset + j) * 3] =
|
||||
config_file_get_int(config, name, UNSET_MIDI_CODE);
|
||||
|
||||
snprintf(name, STR_LEN, "MIDI_%d_%d_Y", i + 1, j + 1);
|
||||
state_config->midi_codes.values[(offset + j) * 3 + 1] =
|
||||
snprintf(name, STR_LEN, "GROUP_%d_%d_Y", i + 1, j + 1);
|
||||
state_config->codes.values[(offset + j) * 3 + 1] =
|
||||
config_file_get_int(config, name, UNSET_MIDI_CODE);
|
||||
|
||||
snprintf(name, STR_LEN, "MIDI_%d_%d_Z", i + 1, j + 1);
|
||||
state_config->midi_codes.values[(offset + j) * 3 + 2] =
|
||||
snprintf(name, STR_LEN, "GROUP_%d_%d_Z", i + 1, j + 1);
|
||||
state_config->codes.values[(offset + j) * 3 + 2] =
|
||||
config_file_get_int(config, name, UNSET_MIDI_CODE);
|
||||
}
|
||||
}
|
||||
@@ -351,244 +342,276 @@ void state_parse_config(StateConfig *state_config, const ConfigFile *config) {
|
||||
config_file_get_str(config, "SAVE_FILE_PREFIX", "forge_save"),
|
||||
STR_LEN);
|
||||
|
||||
state_config->hotkey_randomize =
|
||||
config_file_get_int(config, "HOTKEY_RANDOMIZE", 82);
|
||||
state_config->hotkey_reset =
|
||||
config_file_get_int(config, "HOTKEY_RESET", 1082);
|
||||
state_config->hotkey_demo = config_file_get_int(config, "HOTKEY_DEMO", 68);
|
||||
state_config->hotkey_autorand =
|
||||
config_file_get_int(config, "HOTKEY_AUTORAND", 65);
|
||||
state_config->hotkey_autorand_down =
|
||||
config_file_get_int(config, "HOTKEY_AUTORAND_DOWN", 263);
|
||||
state_config->hotkey_autorand_up =
|
||||
config_file_get_int(config, "HOTKEY_AUTORAND_UP", 262);
|
||||
state_config->hotkey_tempo_down =
|
||||
config_file_get_int(config, "HOTKEY_TEMPO_DOWN", 264);
|
||||
state_config->hotkey_tempo_up =
|
||||
config_file_get_int(config, "HOTKEY_TEMPO_UP", 265);
|
||||
state_config->key_randomize =
|
||||
config_file_get_int(config, "KEY_RANDOMIZE", 1082);
|
||||
state_config->key_reset = config_file_get_int(config, "KEY_RESET", 11082);
|
||||
state_config->key_demo = config_file_get_int(config, "KEY_DEMO", 1068);
|
||||
state_config->key_autorand =
|
||||
config_file_get_int(config, "KEY_AUTORAND", 1065);
|
||||
state_config->key_autorand_down =
|
||||
config_file_get_int(config, "KEY_AUTORAND_DOWN", 1263);
|
||||
state_config->key_autorand_up =
|
||||
config_file_get_int(config, "KEY_AUTORAND_UP", 1262);
|
||||
state_config->key_tempo_down =
|
||||
config_file_get_int(config, "KEY_TEMPO_DOWN", 1264);
|
||||
state_config->key_tempo_up =
|
||||
config_file_get_int(config, "KEY_TEMPO_UP", 1265);
|
||||
|
||||
if (config_file_has(config, "HOTKEY_LOAD_COUNT")) {
|
||||
state_config->hotkey_load.length =
|
||||
config_file_get_int(config, "HOTKEY_LOAD_COUNT", 0);
|
||||
if (config_file_has(config, "KEY_LOAD_COUNT")) {
|
||||
state_config->key_load.length =
|
||||
config_file_get_int(config, "KEY_LOAD_COUNT", 0);
|
||||
|
||||
for (unsigned int i = 0; i < state_config->hotkey_load.length; i++) {
|
||||
snprintf(name, STR_LEN, "HOTKEY_LOAD_%d", i + 1);
|
||||
state_config->hotkey_load.values[i] =
|
||||
config_file_get_int(config, name, 0);
|
||||
for (unsigned int i = 0; i < state_config->key_load.length; i++) {
|
||||
snprintf(name, STR_LEN, "KEY_LOAD_%d", i + 1);
|
||||
state_config->key_load.values[i] = config_file_get_int(config, name, 0);
|
||||
}
|
||||
} else {
|
||||
state_config->hotkey_load.length = 10;
|
||||
state_config->hotkey_load.values[0] = 49;
|
||||
state_config->hotkey_load.values[1] = 50;
|
||||
state_config->hotkey_load.values[2] = 51;
|
||||
state_config->hotkey_load.values[3] = 52;
|
||||
state_config->hotkey_load.values[4] = 53;
|
||||
state_config->hotkey_load.values[5] = 54;
|
||||
state_config->hotkey_load.values[6] = 55;
|
||||
state_config->hotkey_load.values[7] = 56;
|
||||
state_config->hotkey_load.values[8] = 57;
|
||||
state_config->hotkey_load.values[9] = 48;
|
||||
state_config->key_load.length = 10;
|
||||
state_config->key_load.values[0] = 1049;
|
||||
state_config->key_load.values[1] = 1050;
|
||||
state_config->key_load.values[2] = 1051;
|
||||
state_config->key_load.values[3] = 1052;
|
||||
state_config->key_load.values[4] = 1053;
|
||||
state_config->key_load.values[5] = 1054;
|
||||
state_config->key_load.values[6] = 1055;
|
||||
state_config->key_load.values[7] = 1056;
|
||||
state_config->key_load.values[8] = 1057;
|
||||
state_config->key_load.values[9] = 1048;
|
||||
}
|
||||
|
||||
if (config_file_has(config, "HOTKEY_SAVE_COUNT")) {
|
||||
state_config->hotkey_save.length =
|
||||
config_file_get_int(config, "HOTKEY_SAVE_COUNT", 0);
|
||||
if (config_file_has(config, "KEY_SAVE_COUNT")) {
|
||||
state_config->key_save.length =
|
||||
config_file_get_int(config, "KEY_SAVE_COUNT", 0);
|
||||
|
||||
for (unsigned int i = 0; i < state_config->hotkey_save.length; i++) {
|
||||
snprintf(name, STR_LEN, "HOTKEY_SAVE_%d", i + 1);
|
||||
state_config->hotkey_save.values[i] =
|
||||
config_file_get_int(config, name, 0);
|
||||
for (unsigned int i = 0; i < state_config->key_save.length; i++) {
|
||||
snprintf(name, STR_LEN, "KEY_SAVE_%d", i + 1);
|
||||
state_config->key_save.values[i] = config_file_get_int(config, name, 0);
|
||||
}
|
||||
} else {
|
||||
state_config->hotkey_save.length = 10;
|
||||
state_config->hotkey_save.values[0] = 1049;
|
||||
state_config->hotkey_save.values[1] = 1050;
|
||||
state_config->hotkey_save.values[2] = 1051;
|
||||
state_config->hotkey_save.values[3] = 1052;
|
||||
state_config->hotkey_save.values[4] = 1053;
|
||||
state_config->hotkey_save.values[5] = 1054;
|
||||
state_config->hotkey_save.values[6] = 1055;
|
||||
state_config->hotkey_save.values[7] = 1056;
|
||||
state_config->hotkey_save.values[8] = 1057;
|
||||
state_config->hotkey_save.values[9] = 1048;
|
||||
state_config->key_save.length = 10;
|
||||
state_config->key_save.values[0] = 11049;
|
||||
state_config->key_save.values[1] = 11050;
|
||||
state_config->key_save.values[2] = 11051;
|
||||
state_config->key_save.values[3] = 11052;
|
||||
state_config->key_save.values[4] = 11053;
|
||||
state_config->key_save.values[5] = 11054;
|
||||
state_config->key_save.values[6] = 11055;
|
||||
state_config->key_save.values[7] = 11056;
|
||||
state_config->key_save.values[8] = 11057;
|
||||
state_config->key_save.values[9] = 11048;
|
||||
}
|
||||
}
|
||||
|
||||
void state_midi_event(SharedContext *context, const StateConfig *state_config,
|
||||
const MidiDevice *midi, unsigned char code,
|
||||
unsigned char value, bool trace_midi) {
|
||||
static bool compute_event(Context *context, StateConfig state_config,
|
||||
MidiDevice midi, unsigned int code,
|
||||
unsigned int value) {
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int k;
|
||||
unsigned int part;
|
||||
bool found;
|
||||
|
||||
found = false;
|
||||
|
||||
// PAGE CHANGE
|
||||
i = arr_uint_index_of(state_config->select_page_codes, code);
|
||||
i = arr_uint_index_of(state_config.select_page_codes, code);
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
found = true;
|
||||
if (value > 0) {
|
||||
context->page = i;
|
||||
update_page(context, state_config, midi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TARGET CHANGE
|
||||
i = arr_uint_index_of(state_config->select_frag_codes, code);
|
||||
i = arr_uint_index_of(state_config.select_frag_codes, code);
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
found = true;
|
||||
if (value > 0) {
|
||||
context->selected = i;
|
||||
update_page(context, state_config, midi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ITEM CHANGE
|
||||
i = arr_uint_index_of(state_config->select_item_codes, code);
|
||||
i = arr_uint_index_of(state_config.select_item_codes, code);
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
found = true;
|
||||
if (value > 0) {
|
||||
context->state.values[context->selected] =
|
||||
context->page * state_config->select_item_codes.length + i;
|
||||
context->page * state_config.select_item_codes.length + i;
|
||||
update_page(context, state_config, midi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ACTIVE CHANGE
|
||||
i = arr_uint_index_of(state_config->midi_active_codes, code);
|
||||
i = arr_uint_index_of(state_config.group_active_codes, code);
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
found = true;
|
||||
if (value > 0) {
|
||||
part = arr_uint_remap_index(state_config->midi_active_offsets, &i);
|
||||
part = arr_uint_remap_index(state_config.group_active_offsets, &i);
|
||||
context->active[part] = i;
|
||||
update_active(context, state_config, midi);
|
||||
update_active(context, state_config, midi, true);
|
||||
update_values(context, state_config, midi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// VALUE CHANGE
|
||||
i = arr_uint_index_of(state_config->midi_codes, code);
|
||||
i = arr_uint_index_of(state_config.codes, code);
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
found = true;
|
||||
j = i / 3;
|
||||
part = arr_uint_remap_index(state_config->midi_offsets, &j);
|
||||
k = state_config->values_offsets.values[part] +
|
||||
context->active[part] * state_config->midi_counts.values[part] + j;
|
||||
part = arr_uint_remap_index(state_config.group_offsets, &j);
|
||||
k = state_config.values_offsets.values[part] +
|
||||
context->active[part] * state_config.group_counts.values[part] + j;
|
||||
|
||||
if (arr_uint_index_of(state_config->fader_codes, code) != ARRAY_NOT_FOUND) {
|
||||
if (arr_uint_index_of(state_config.fader_codes, code) != ARRAY_NOT_FOUND) {
|
||||
context->values[k][i % 3] = (float)value / MIDI_MAX;
|
||||
} else if (value > 0) {
|
||||
if (context->values[k][i % 3] > 0.5) {
|
||||
context->values[k][i % 3] = 0;
|
||||
midi_write(midi, code, 0);
|
||||
safe_midi_write(midi, code, 0);
|
||||
} else {
|
||||
context->values[k][i % 3] = 1;
|
||||
midi_write(midi, code, MIDI_MAX);
|
||||
safe_midi_write(midi, code, MIDI_MAX);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config->tap_tempo_code) {
|
||||
found = true;
|
||||
midi_write(midi, code, value);
|
||||
// TAP TEMPO
|
||||
if (code == state_config.tap_tempo_code) {
|
||||
safe_midi_write(midi, code, value);
|
||||
if (value > 0) {
|
||||
tempo_tap(&context->tempo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (trace_midi) {
|
||||
log_trace("unknown midi: %d %d", code, value);
|
||||
// OTHER KEYS
|
||||
if (code == state_config.key_randomize) {
|
||||
if (value > 0) {
|
||||
log_info("[%d] Randomized", code);
|
||||
randomize(context, state_config);
|
||||
update_values(context, state_config, midi);
|
||||
}
|
||||
midi_write(midi, code, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_reset) {
|
||||
if (value > 0) {
|
||||
log_info("[%d] Reset", code);
|
||||
reset(context);
|
||||
update_values(context, state_config, midi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_demo) {
|
||||
if (value > 0) {
|
||||
log_info((context->demo ? "[%d] Demo OFF" : "[%d] Demo ON"), code);
|
||||
context->demo = !context->demo;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_autorand) {
|
||||
if (value > 0) {
|
||||
log_info((context->auto_random ? "[%d] Auto Random OFF"
|
||||
: "[%d] Auto Random ON"),
|
||||
code);
|
||||
context->auto_random = !context->auto_random;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_autorand_down) {
|
||||
if (value > 0) {
|
||||
if (context->auto_random_cycle > 1) {
|
||||
context->auto_random_cycle -= 1;
|
||||
}
|
||||
log_info("[%d] Auto Random Cycle: %d", code, context->auto_random_cycle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_autorand_up) {
|
||||
if (value > 0) {
|
||||
context->auto_random_cycle += 1;
|
||||
log_info("[%d] Auto Random Cycle: %d", code, context->auto_random_cycle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_tempo_up) {
|
||||
if (value > 0) {
|
||||
tempo_set(&context->tempo, context->tempo.tempo + 1);
|
||||
log_info("[%d] Tempo: %f", code, context->tempo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code == state_config.key_tempo_down) {
|
||||
if (value > 0) {
|
||||
if (context->tempo.tempo > 0) {
|
||||
tempo_set(&context->tempo, context->tempo.tempo - 1);
|
||||
}
|
||||
log_info("[%d] Tempo: %f", code, context->tempo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// LOAD STATE
|
||||
i = arr_uint_index_of(state_config.key_load, code);
|
||||
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
if (value > 0) {
|
||||
log_info("[%d] Loading state %d", code, i + 1);
|
||||
load_from_index_file(context, state_config, i + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SAVE STATE
|
||||
i = arr_uint_index_of(state_config.key_save, code);
|
||||
|
||||
if (i != ARRAY_NOT_FOUND) {
|
||||
if (value > 0) {
|
||||
log_info("[%d] Saving state %d", code, i + 1);
|
||||
save_to_index_file(context, state_config, i + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void state_midi_event(Context *context, StateConfig state_config,
|
||||
MidiDevice midi, unsigned char code, unsigned char value,
|
||||
bool trace_midi) {
|
||||
if (!compute_event(context, state_config, midi, code, value)) {
|
||||
log_warn("unknown midi: %d %d", code, value);
|
||||
safe_midi_write(midi, code, value);
|
||||
} else if (trace_midi) {
|
||||
log_trace("midi: %d %d", code, value);
|
||||
}
|
||||
}
|
||||
|
||||
void state_key_event(SharedContext *context, const StateConfig *state_config,
|
||||
unsigned int code, const MidiDevice *midi) {
|
||||
unsigned int index;
|
||||
|
||||
if (code == state_config->hotkey_randomize) {
|
||||
log_info("[%d] Randomized", code);
|
||||
randomize(context, state_config);
|
||||
update_values(context, state_config, midi);
|
||||
} else if (code == state_config->hotkey_reset) {
|
||||
log_info("[%d] Reset", code);
|
||||
reset(context);
|
||||
update_values(context, state_config, midi);
|
||||
} else if (code == state_config->hotkey_demo) {
|
||||
log_info((context->demo ? "[%d] Demo OFF" : "[%d] Demo ON"), code);
|
||||
context->demo = !context->demo;
|
||||
} else if (code == state_config->hotkey_autorand) {
|
||||
log_info(
|
||||
(context->auto_random ? "[%d] Auto Random OFF" : "[%d] Auto Random ON"),
|
||||
code);
|
||||
context->auto_random = !context->auto_random;
|
||||
} else if (code == state_config->hotkey_autorand_down) {
|
||||
if (context->auto_random_cycle > 1) {
|
||||
context->auto_random_cycle -= 1;
|
||||
}
|
||||
log_info("[%d] Auto Random Cycle: %d", code, context->auto_random_cycle);
|
||||
} else if (code == state_config->hotkey_autorand_up) {
|
||||
context->auto_random_cycle += 1;
|
||||
log_info("[%d] Auto Random Cycle: %d", code, context->auto_random_cycle);
|
||||
} else if (code == state_config->hotkey_tempo_up) {
|
||||
tempo_set(&context->tempo, context->tempo.tempo + 1);
|
||||
log_info("[%d] Tempo: %f", code, context->tempo);
|
||||
} else if (code == state_config->hotkey_tempo_down) {
|
||||
if (context->tempo.tempo > 0) {
|
||||
tempo_set(&context->tempo, context->tempo.tempo - 1);
|
||||
}
|
||||
log_info("[%d] Tempo: %f", code, context->tempo);
|
||||
} else {
|
||||
index = arr_uint_index_of(state_config->hotkey_load, code);
|
||||
|
||||
if (index != ARRAY_NOT_FOUND) {
|
||||
log_info("[%d] Loading state %d", code, index + 1);
|
||||
load_from_index_file(context, state_config, index + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
index = arr_uint_index_of(state_config->hotkey_save, code);
|
||||
|
||||
if (index != ARRAY_NOT_FOUND) {
|
||||
log_info("[%d] Saving state %d", code, index + 1);
|
||||
save_to_index_file(context, state_config, index + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("[%d] No hotkey defined", code);
|
||||
void state_key_event(Context *context, StateConfig state_config,
|
||||
unsigned int code, MidiDevice midi) {
|
||||
if (!compute_event(context, state_config, midi, code, MIDI_MAX)) {
|
||||
log_warn("[%d] No hotkey defined", code);
|
||||
}
|
||||
}
|
||||
|
||||
bool state_background_write(SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
const MidiDevice *midi) {
|
||||
pid_t pid;
|
||||
void *state_background_write(void *args) {
|
||||
StateBackgroundWriteArgs *process_args = (StateBackgroundWriteArgs *)args;
|
||||
Context *context = process_args->context;
|
||||
StateConfig state_config = process_args->state_config;
|
||||
MidiDevice *midi = process_args->midi;
|
||||
|
||||
bool beat_active;
|
||||
bool last_active;
|
||||
bool change;
|
||||
bool last_change;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Could not create subprocess");
|
||||
return false;
|
||||
}
|
||||
if (pid == 0) {
|
||||
return true;
|
||||
}
|
||||
log_info("(state) background writing started (pid: %d)", pid);
|
||||
|
||||
if (!midi->error) {
|
||||
update_page(context, state_config, midi);
|
||||
update_active(context, state_config, midi);
|
||||
update_values(context, state_config, midi);
|
||||
}
|
||||
log_info("(state) background writing started");
|
||||
|
||||
last_active = false;
|
||||
last_change = false;
|
||||
@@ -596,12 +619,12 @@ bool state_background_write(SharedContext *context,
|
||||
while (!context->stop) {
|
||||
beat_active = tempo_progress(&context->tempo, 1.0) < 0.5;
|
||||
|
||||
if (!midi->error && beat_active != last_active) {
|
||||
safe_midi_write(midi, state_config->tap_tempo_code,
|
||||
beat_active ? MIDI_MAX : 0);
|
||||
if (midi->connected && beat_active != last_active) {
|
||||
update_values(context, state_config, *midi);
|
||||
update_page(context, state_config, *midi);
|
||||
update_active(context, state_config, *midi, beat_active);
|
||||
|
||||
safe_midi_write(midi,
|
||||
state_config->select_frag_codes.values[context->selected],
|
||||
safe_midi_write(*midi, state_config.tap_tempo_code,
|
||||
beat_active ? MIDI_MAX : 0);
|
||||
}
|
||||
|
||||
@@ -613,25 +636,25 @@ bool state_background_write(SharedContext *context,
|
||||
if (context->auto_random && change && !last_change) {
|
||||
randomize(context, state_config);
|
||||
|
||||
update_values(context, state_config, midi);
|
||||
update_values(context, state_config, *midi);
|
||||
}
|
||||
|
||||
last_change = change;
|
||||
}
|
||||
|
||||
log_info("(state) background writing stopped by main thread (pid: %d)", pid);
|
||||
exit(EXIT_SUCCESS);
|
||||
log_info("(state) background writing stopped by main thread");
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void state_init(SharedContext *context, const StateConfig *state_config,
|
||||
bool demo, bool auto_random, unsigned int auto_random_cycles,
|
||||
void state_init(Context *context, StateConfig state_config, bool demo,
|
||||
bool auto_random, unsigned int auto_random_cycles,
|
||||
unsigned int base_tempo, bool load_state) {
|
||||
tempo_init(&context->tempo, base_tempo);
|
||||
context->demo = demo;
|
||||
context->auto_random = auto_random;
|
||||
context->auto_random_cycle = auto_random_cycles;
|
||||
|
||||
context->state.length = state_config->select_frag_codes.length;
|
||||
context->state.length = state_config.select_frag_codes.length;
|
||||
memset(context->state.values, 0, sizeof(context->state.values));
|
||||
|
||||
if (auto_random) {
|
||||
@@ -655,6 +678,6 @@ void state_init(SharedContext *context, const StateConfig *state_config,
|
||||
}
|
||||
}
|
||||
|
||||
void state_save(const SharedContext *context, const StateConfig *state_config) {
|
||||
void state_save(const Context *context, StateConfig state_config) {
|
||||
save_to_default_file(context, state_config);
|
||||
}
|
||||
|
||||
+8
-10
@@ -5,21 +5,19 @@
|
||||
|
||||
void state_parse_config(StateConfig *state_config, const ConfigFile *config);
|
||||
|
||||
void state_midi_event(SharedContext *context, const StateConfig *state_config,
|
||||
const MidiDevice *midi, unsigned char code,
|
||||
void state_midi_event(Context *context, StateConfig state_config,
|
||||
MidiDevice midi, unsigned char code,
|
||||
unsigned char value, bool trace_midi);
|
||||
|
||||
void state_key_event(SharedContext *context, const StateConfig *state_config,
|
||||
unsigned int code, const MidiDevice *midi);
|
||||
void state_key_event(Context *context, StateConfig state_config,
|
||||
unsigned int code, MidiDevice midi);
|
||||
|
||||
bool state_background_write(SharedContext *context,
|
||||
const StateConfig *state_config,
|
||||
const MidiDevice *midi);
|
||||
void *state_background_write(void *args);
|
||||
|
||||
void state_init(SharedContext *context, const StateConfig *state_config,
|
||||
bool demo, bool auto_random, unsigned int auto_random_cycles,
|
||||
void state_init(Context *context, StateConfig state_config, bool demo,
|
||||
bool auto_random, unsigned int auto_random_cycles,
|
||||
unsigned int base_tempo, bool load_state);
|
||||
|
||||
void state_save(const SharedContext *context, const StateConfig *state_config);
|
||||
void state_save(const Context *context, StateConfig state_config);
|
||||
|
||||
#endif /* STATE_H */
|
||||
|
||||
+88
-61
@@ -45,12 +45,16 @@ typedef struct Parameters {
|
||||
bool demo;
|
||||
bool auto_random;
|
||||
unsigned int auto_random_cycle;
|
||||
#ifdef VIDEO_IN
|
||||
StringArray video_in;
|
||||
unsigned int video_buffers;
|
||||
unsigned int video_size;
|
||||
unsigned int internal_size;
|
||||
bool video_reconnect;
|
||||
#endif /* VIDEO_IN */
|
||||
unsigned int internal_size;
|
||||
bool load_state;
|
||||
bool save_state;
|
||||
bool midi_reconnect;
|
||||
bool trace_midi;
|
||||
bool trace_fps;
|
||||
} Parameters;
|
||||
@@ -84,6 +88,7 @@ typedef struct ShaderProgram {
|
||||
GLuint vertex_array[2];
|
||||
|
||||
unsigned int tex_count;
|
||||
unsigned int tex_map[ARRAY_SIZE];
|
||||
GLuint textures[ARRAY_SIZE];
|
||||
|
||||
unsigned int frag_count;
|
||||
@@ -104,7 +109,6 @@ typedef struct ShaderProgram {
|
||||
GLuint iinres_locations[ARRAY_SIZE];
|
||||
GLuint iinfmt_locations[ARRAY_SIZE];
|
||||
GLuint iinfps_locations[ARRAY_SIZE];
|
||||
GLuint iinswap_locations[ARRAY_SIZE];
|
||||
GLuint idemo_locations[ARRAY_SIZE];
|
||||
GLuint iautorand_locations[ARRAY_SIZE];
|
||||
GLuint iautorandcycle_locations[ARRAY_SIZE];
|
||||
@@ -115,7 +119,7 @@ typedef struct ShaderProgram {
|
||||
GLuint iactive_locations[ARRAY_SIZE];
|
||||
|
||||
UintArray midi_lengths;
|
||||
GLuint imidi_locations[ARRAY_SIZE];
|
||||
GLuint igroup_locations[ARRAY_SIZE];
|
||||
|
||||
GLuint vpos_locations[ARRAY_SIZE];
|
||||
|
||||
@@ -129,40 +133,13 @@ typedef struct ShaderProgram {
|
||||
|
||||
unsigned int in_count;
|
||||
#ifdef VIDEO_IN
|
||||
unsigned int sub_video_count;
|
||||
unsigned int input_tex_map[MAX_VIDEO];
|
||||
EGLDisplay egl_display;
|
||||
EGLImageKHR dma_images[MAX_VIDEO];
|
||||
EGLImageKHR dma_images_swap[MAX_VIDEO];
|
||||
#endif /* VIDEO_IN */
|
||||
} ShaderProgram;
|
||||
|
||||
// video.c
|
||||
|
||||
typedef struct VideoCapture {
|
||||
char name[STR_LEN];
|
||||
bool error;
|
||||
bool disconnected;
|
||||
bool needs_reload;
|
||||
bool with_swap;
|
||||
bool swap;
|
||||
unsigned int fps;
|
||||
int fd;
|
||||
int exp_fd;
|
||||
int exp_fd_swap;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int pixelformat;
|
||||
unsigned int bytesperline;
|
||||
#ifdef VIDEO_IN
|
||||
struct v4l2_buffer buf;
|
||||
struct v4l2_buffer buf_swap;
|
||||
#endif /* VIDEO_IN */
|
||||
} VideoCapture;
|
||||
|
||||
typedef struct VideoCaptureArray {
|
||||
VideoCapture values[MAX_VIDEO];
|
||||
unsigned int length;
|
||||
} VideoCaptureArray;
|
||||
|
||||
// window.c
|
||||
|
||||
typedef GLFWwindow Window;
|
||||
@@ -182,11 +159,16 @@ typedef struct Tempo {
|
||||
|
||||
// context.c
|
||||
|
||||
typedef struct SharedContext {
|
||||
typedef struct Context {
|
||||
int fd;
|
||||
vec2 resolution;
|
||||
vec2 tex_resolution;
|
||||
#ifdef VIDEO_IN
|
||||
vec2 input_resolutions[MAX_VIDEO];
|
||||
unsigned int input_formats[MAX_VIDEO];
|
||||
unsigned int input_fps[MAX_VIDEO];
|
||||
unsigned int input_index[MAX_VIDEO];
|
||||
#endif /* VIDEO_IN */
|
||||
double time;
|
||||
Tempo tempo;
|
||||
double tempo_total;
|
||||
@@ -200,9 +182,57 @@ typedef struct SharedContext {
|
||||
unsigned int auto_random_cycle;
|
||||
unsigned int seeds[MAX_FRAG];
|
||||
unsigned int fps;
|
||||
VideoCaptureArray inputs;
|
||||
bool stop;
|
||||
} SharedContext;
|
||||
_Atomic bool stop;
|
||||
} Context;
|
||||
|
||||
// video.c
|
||||
|
||||
#ifdef VIDEO_IN
|
||||
|
||||
typedef struct VideoCapture {
|
||||
char name[STR_LEN];
|
||||
_Atomic bool error;
|
||||
_Atomic bool disconnected;
|
||||
_Atomic bool needs_reload;
|
||||
unsigned int buf_count;
|
||||
unsigned int buf_index;
|
||||
int fd;
|
||||
int exp_fd[ARRAY_SIZE];
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int pixelformat;
|
||||
unsigned int bytesperline;
|
||||
struct v4l2_buffer buf[ARRAY_SIZE];
|
||||
} VideoCapture;
|
||||
|
||||
typedef struct VideoCaptureArray {
|
||||
VideoCapture values[MAX_VIDEO];
|
||||
unsigned int length;
|
||||
} VideoCaptureArray;
|
||||
|
||||
typedef struct VideoBackgroundReadArgs {
|
||||
VideoCapture *capture;
|
||||
Context *context;
|
||||
int input_index;
|
||||
bool trace_fps;
|
||||
} VideoBackgroundReadArgs;
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
// midi.c
|
||||
|
||||
typedef struct MidiDevice {
|
||||
_Atomic bool connected;
|
||||
char name[STR_LEN];
|
||||
snd_rawmidi_t *input;
|
||||
snd_rawmidi_t *output;
|
||||
} MidiDevice;
|
||||
|
||||
typedef struct MidiBackgroundListenArgs {
|
||||
MidiDevice *device;
|
||||
Context *context;
|
||||
void (*event_callback)(unsigned char code, unsigned char value);
|
||||
} MidiBackgroundReadArgs;
|
||||
|
||||
// state.c
|
||||
|
||||
@@ -212,12 +242,12 @@ typedef struct StateConfig {
|
||||
UintArray select_page_codes;
|
||||
UintArray select_item_codes;
|
||||
UintArray select_frag_codes;
|
||||
UintArray midi_active_counts;
|
||||
UintArray midi_active_offsets;
|
||||
UintArray midi_active_codes;
|
||||
UintArray midi_counts;
|
||||
UintArray midi_offsets;
|
||||
UintArray midi_codes;
|
||||
UintArray group_active_counts;
|
||||
UintArray group_active_offsets;
|
||||
UintArray group_active_codes;
|
||||
UintArray group_counts;
|
||||
UintArray group_offsets;
|
||||
UintArray codes;
|
||||
UintArray fader_codes;
|
||||
UintArray values_offsets;
|
||||
|
||||
@@ -227,19 +257,25 @@ typedef struct StateConfig {
|
||||
|
||||
char save_file_prefix[STR_LEN];
|
||||
|
||||
unsigned int hotkey_randomize;
|
||||
unsigned int hotkey_reset;
|
||||
unsigned int hotkey_demo;
|
||||
unsigned int hotkey_autorand;
|
||||
unsigned int hotkey_autorand_up;
|
||||
unsigned int hotkey_autorand_down;
|
||||
unsigned int hotkey_tempo_up;
|
||||
unsigned int hotkey_tempo_down;
|
||||
unsigned int key_randomize;
|
||||
unsigned int key_reset;
|
||||
unsigned int key_demo;
|
||||
unsigned int key_autorand;
|
||||
unsigned int key_autorand_up;
|
||||
unsigned int key_autorand_down;
|
||||
unsigned int key_tempo_up;
|
||||
unsigned int key_tempo_down;
|
||||
|
||||
UintArray hotkey_load;
|
||||
UintArray hotkey_save;
|
||||
UintArray key_load;
|
||||
UintArray key_save;
|
||||
} StateConfig;
|
||||
|
||||
typedef struct StateBackgroundWriteArgs {
|
||||
Context *context;
|
||||
StateConfig state_config;
|
||||
MidiDevice *midi;
|
||||
} StateBackgroundWriteArgs;
|
||||
|
||||
// timer.c
|
||||
|
||||
typedef struct Timer {
|
||||
@@ -260,15 +296,6 @@ typedef struct ConfigFileItem {
|
||||
char value[STR_LEN];
|
||||
} ConfigFileItem;
|
||||
|
||||
// midi.c
|
||||
|
||||
typedef struct MidiDevice {
|
||||
bool error;
|
||||
char name[STR_LEN];
|
||||
snd_rawmidi_t *input;
|
||||
snd_rawmidi_t *output;
|
||||
} MidiDevice;
|
||||
|
||||
// project.c
|
||||
|
||||
typedef struct Project {
|
||||
|
||||
+53
-62
@@ -4,8 +4,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <log.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
@@ -192,14 +192,15 @@ static bool set_format(VideoCapture *video_capture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool request_buffers(VideoCapture *video_capture) {
|
||||
static bool request_buffers(VideoCapture *video_capture,
|
||||
unsigned int buffer_count) {
|
||||
struct v4l2_requestbuffers reqbuf;
|
||||
|
||||
memset(&reqbuf, 0, sizeof(reqbuf));
|
||||
|
||||
reqbuf.type = buf_type;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
reqbuf.count = 2;
|
||||
reqbuf.count = buffer_count;
|
||||
|
||||
if (ioctl(video_capture->fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
|
||||
ioctl_error(video_capture, "VIDIOC_REQBUFS",
|
||||
@@ -209,7 +210,7 @@ static bool request_buffers(VideoCapture *video_capture) {
|
||||
|
||||
log_info("(%s) V4L2 Buffer Count: %d", video_capture->name, reqbuf.count);
|
||||
|
||||
video_capture->with_swap = reqbuf.count > 1;
|
||||
video_capture->buf_count = reqbuf.count;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -239,16 +240,15 @@ static bool export_buffer(VideoCapture *video_capture, int *fd,
|
||||
}
|
||||
|
||||
static bool export_buffers(VideoCapture *video_capture) {
|
||||
bool result;
|
||||
unsigned int i;
|
||||
|
||||
result = export_buffer(video_capture, &video_capture->exp_fd, 0);
|
||||
|
||||
if (result && video_capture->with_swap) {
|
||||
result =
|
||||
result && export_buffer(video_capture, &video_capture->exp_fd_swap, 1);
|
||||
for (i = 0; i < video_capture->buf_count; i++) {
|
||||
if (!export_buffer(video_capture, &video_capture->exp_fd[i], i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool open_stream(VideoCapture *video_capture) {
|
||||
@@ -274,10 +274,10 @@ static void create_image_buffer(const VideoCapture *video_capture,
|
||||
}
|
||||
|
||||
static void create_image_buffers(VideoCapture *video_capture) {
|
||||
create_image_buffer(video_capture, &video_capture->buf, 0);
|
||||
unsigned int i;
|
||||
|
||||
if (video_capture->with_swap) {
|
||||
create_image_buffer(video_capture, &video_capture->buf_swap, 1);
|
||||
for (i = 0; i < video_capture->buf_count; i++) {
|
||||
create_image_buffer(video_capture, &video_capture->buf[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,31 +286,26 @@ static void close_stream(const VideoCapture *video_capture) {
|
||||
}
|
||||
|
||||
static unsigned int read_video(VideoCapture *video_capture) {
|
||||
unsigned int result;
|
||||
struct v4l2_capability cap;
|
||||
|
||||
result = 0;
|
||||
if (ioctl(video_capture->fd, VIDIOC_DQBUF,
|
||||
&video_capture->buf[video_capture->buf_index]) != -1) {
|
||||
ioctl(video_capture->fd, VIDIOC_QBUF,
|
||||
&video_capture->buf[video_capture->buf_index]);
|
||||
video_capture->buf_index =
|
||||
(video_capture->buf_index + 1) % video_capture->buf_count;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((video_capture->swap || !video_capture->with_swap) &&
|
||||
ioctl(video_capture->fd, VIDIOC_DQBUF, &video_capture->buf) != -1) {
|
||||
ioctl(video_capture->fd, VIDIOC_QBUF, &video_capture->buf);
|
||||
|
||||
result = 1;
|
||||
} else if (!video_capture->swap && video_capture->with_swap &&
|
||||
ioctl(video_capture->fd, VIDIOC_DQBUF, &video_capture->buf_swap) !=
|
||||
-1) {
|
||||
ioctl(video_capture->fd, VIDIOC_QBUF, &video_capture->buf_swap);
|
||||
|
||||
result = 2;
|
||||
} else if (ioctl(video_capture->fd, VIDIOC_QUERYCAP, &cap) == -1) {
|
||||
if (ioctl(video_capture->fd, VIDIOC_QUERYCAP, &cap) == -1) {
|
||||
video_capture->error = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
void video_init(VideoCapture *video_capture, const char *name,
|
||||
unsigned int preferred_height) {
|
||||
unsigned int preferred_height, unsigned int buffer_count) {
|
||||
open_device(video_capture, name);
|
||||
|
||||
if (video_capture->error) {
|
||||
@@ -329,7 +324,7 @@ void video_init(VideoCapture *video_capture, const char *name,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request_buffers(video_capture)) {
|
||||
if (!request_buffers(video_capture, buffer_count)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -344,60 +339,56 @@ void video_init(VideoCapture *video_capture, const char *name,
|
||||
create_image_buffers(video_capture);
|
||||
}
|
||||
|
||||
bool video_background_read(VideoCapture *video_capture, SharedContext *context,
|
||||
int input_index, bool trace_fps) {
|
||||
pid_t pid;
|
||||
void *video_background_read(void *args) {
|
||||
VideoBackgroundReadArgs *process_args = (VideoBackgroundReadArgs *)args;
|
||||
VideoCapture *video_capture = process_args->capture;
|
||||
Context *context = process_args->context;
|
||||
int input_index = process_args->input_index;
|
||||
bool trace_fps = process_args->trace_fps;
|
||||
Timer timer;
|
||||
double fps;
|
||||
unsigned int video_result;
|
||||
bool result;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Could not create subprocess");
|
||||
return false;
|
||||
}
|
||||
if (pid == 0) {
|
||||
return true;
|
||||
}
|
||||
log_info("(%s) background acquisition started (pid: %d)", video_capture->name,
|
||||
pid);
|
||||
log_info("(%s) background acquisition started", video_capture->name);
|
||||
timer_init(&timer, 30);
|
||||
|
||||
while (!context->stop && !video_capture->error) {
|
||||
video_result = read_video(video_capture);
|
||||
if (video_result > 0 && timer_inc(&timer)) {
|
||||
result = read_video(video_capture);
|
||||
|
||||
if (result && timer_inc(&timer)) {
|
||||
fps = timer_reset(&timer);
|
||||
|
||||
context->inputs.values[input_index].fps = (unsigned int)round(fps);
|
||||
context->input_fps[input_index] = (unsigned int)round(fps);
|
||||
if (trace_fps) {
|
||||
log_trace("(%s) %.2ffps", video_capture->name, fps);
|
||||
}
|
||||
}
|
||||
if (video_result > 0) {
|
||||
video_capture->swap = video_result == 2;
|
||||
|
||||
if (result) {
|
||||
context->input_index[input_index] = video_capture->buf_index;
|
||||
}
|
||||
}
|
||||
if (context->stop) {
|
||||
log_info("(%s) background acquisition stopped by main thread (pid: %d)",
|
||||
video_capture->name, pid);
|
||||
log_info("(%s) background acquisition stopped by main thread",
|
||||
video_capture->name);
|
||||
} else {
|
||||
log_info("(%s) background acquisition stopped after error (pid: %d)",
|
||||
video_capture->name, pid);
|
||||
log_info("(%s) background acquisition stopped after error",
|
||||
video_capture->name);
|
||||
video_capture->disconnected = true;
|
||||
video_capture->pixelformat = 0;
|
||||
video_free(video_capture);
|
||||
context->input_formats[input_index] = 0;
|
||||
}
|
||||
exit(context->stop ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void video_free(const VideoCapture *video_capture) {
|
||||
unsigned int i;
|
||||
|
||||
close_stream(video_capture);
|
||||
if (video_capture->exp_fd != -1) {
|
||||
close(video_capture->exp_fd);
|
||||
}
|
||||
if (video_capture->exp_fd_swap != -1) {
|
||||
close(video_capture->exp_fd);
|
||||
|
||||
for (i = 0; i < video_capture->buf_count; i++) {
|
||||
close(video_capture->exp_fd[i]);
|
||||
}
|
||||
|
||||
if (video_capture->fd != -1) {
|
||||
close(video_capture->fd);
|
||||
}
|
||||
|
||||
+7
-4
@@ -3,12 +3,15 @@
|
||||
#ifndef VIDEO_H
|
||||
#define VIDEO_H
|
||||
|
||||
void video_init(VideoCapture *video_capture, const char *name,
|
||||
unsigned int preferred_height);
|
||||
#ifdef VIDEO_IN
|
||||
|
||||
bool video_background_read(VideoCapture *video_capture, SharedContext *context,
|
||||
int input_index, bool trace_fps);
|
||||
void video_init(VideoCapture *video_capture, const char *name,
|
||||
unsigned int preferred_height, unsigned int buffer_count);
|
||||
|
||||
void *video_background_read(void *args);
|
||||
|
||||
void video_free(const VideoCapture *video_capture);
|
||||
|
||||
#endif /* VIDEO_IN */
|
||||
|
||||
#endif /* VIDEO_H */
|
||||
|
||||
+9
-6
@@ -59,6 +59,9 @@ create_window(GLFWmonitor *monitor, const char *title, Window *shared_context,
|
||||
// Context related hints
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
#ifdef GL_DEBUG
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
||||
#endif
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// create fullscreen window in selected monitor
|
||||
@@ -120,7 +123,7 @@ void window_events() { glfwPollEvents(); }
|
||||
|
||||
double window_get_time() { return glfwGetTime(); }
|
||||
|
||||
void window_use(Window *window, SharedContext *context) {
|
||||
void window_use(Window *window, Context *context) {
|
||||
int width;
|
||||
int height;
|
||||
|
||||
@@ -154,15 +157,15 @@ unsigned int window_read_key(int key, int action, int mods) {
|
||||
key == GLFW_KEY_RIGHT_ALT) {
|
||||
return 0;
|
||||
}
|
||||
result = key;
|
||||
result = 1000 + key;
|
||||
if ((mods & GLFW_MOD_SHIFT) > 0) {
|
||||
result += 1000;
|
||||
}
|
||||
if ((mods & GLFW_MOD_CONTROL) > 0) {
|
||||
result += 10000;
|
||||
}
|
||||
if ((mods & GLFW_MOD_ALT) > 0) {
|
||||
if ((mods & GLFW_MOD_CONTROL) > 0) {
|
||||
result += 100000;
|
||||
}
|
||||
if ((mods & GLFW_MOD_ALT) > 0) {
|
||||
result += 1000000;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ void window_update_title(Window *window, const char *title);
|
||||
|
||||
double window_get_time();
|
||||
|
||||
void window_use(Window *window, SharedContext *context);
|
||||
void window_use(Window *window, Context *context);
|
||||
|
||||
void window_refresh(Window *window);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user