Compare commits
102 Commits
Author | SHA1 | Date | |
---|---|---|---|
9310b08670 | |||
![]() |
59838dda25 | ||
1e5d2b49da | |||
69cff1ebab | |||
![]() |
50118f66a4 | ||
![]() |
6695731d09 | ||
![]() |
9a86ef2de8 | ||
bb9d68c633 | |||
![]() |
e7e65a6dc6 | ||
![]() |
a350588115 | ||
![]() |
245ae36cf4 | ||
41c0b3e704 | |||
![]() |
b8469d8b86 | ||
![]() |
f0fd47bc27 | ||
e3a39dbb6e | |||
31a0e8925e | |||
![]() |
f507660841 | ||
![]() |
063f7122b9 | ||
![]() |
d78a375c95 | ||
![]() |
5b46c45f4a | ||
![]() |
db77378776 | ||
![]() |
931cdd922a | ||
![]() |
a905009db0 | ||
![]() |
3448832862 | ||
![]() |
8eaf255762 | ||
fb767d9bbf | |||
a5727492cd | |||
402df416f8 | |||
a437e54408 | |||
![]() |
261db0e579 | ||
![]() |
fc7b20a956 | ||
0417448cbd | |||
1f620b46fd | |||
786a999c5e | |||
7311d47b9a | |||
![]() |
429543e7af | ||
bdfcf19fdf | |||
44b21010f3 | |||
1a4d158bc0 | |||
b3da04681d | |||
33e4dc39ce | |||
5ddc28440c | |||
5211cf5a3e | |||
35f9c0c091 | |||
f5c9ebab6a | |||
c81cc828aa | |||
![]() |
ecded4fd65 | ||
691e0d633d | |||
2cefabb82f | |||
83f333ef6b | |||
c6de99898d | |||
85f70c29c1 | |||
aa9597b5c2 | |||
efd6033c4b | |||
5663b4389c | |||
440b49c14d | |||
1af0fb6261 | |||
f942ed5dbb | |||
8f6285a884 | |||
ae513dae30 | |||
63391b158f | |||
6e9bdb0ad9 | |||
355cc690fb | |||
10896d7d5b | |||
84888a6433 | |||
50f5b4b378 | |||
dae279564e | |||
a1281745c9 | |||
3f55be309d | |||
18ca2f9cb5 | |||
a13f293479 | |||
3c6719097e | |||
211d86f5e9 | |||
bda8b75c78 | |||
762c670560 | |||
cbe446dd20 | |||
acf85a35cf | |||
7bdceca9dd | |||
dce3373d9b | |||
21df671d15 | |||
1be33ad3f0 | |||
471d6739ef | |||
fb24537804 | |||
6abbbf11ff | |||
322e7e0239 | |||
d479f6493f | |||
b74f4c3e87 | |||
![]() |
3958c0d22d | ||
f803bbb009 | |||
b0f72d6a7d | |||
a89dcbcd20 | |||
7e1d3a2be2 | |||
709a9b7fae | |||
6b0037a332 | |||
3277c4ce08 | |||
792372e5f1 | |||
![]() |
f02a9fa554 | ||
![]() |
98b7ab1354 | ||
c55a1385f2 | |||
0782f8b05d | |||
d8323436f1 | |||
![]() |
0be1b41597 |
@ -20,7 +20,7 @@ Feel free to try it out anyway and perhaps give us some feedback (we'd appreciat
|
|||||||
|
|
||||||
## Legal
|
## Legal
|
||||||
|
|
||||||
Copyright (C) 2021-2024 Orastron Srl unipersonale.
|
Copyright (C) 2021-2025 Orastron Srl unipersonale.
|
||||||
|
|
||||||
Authors: Stefano D'Angelo, Paolo Marrone.
|
Authors: Stefano D'Angelo, Paolo Marrone.
|
||||||
|
|
||||||
|
28
notes
28
notes
@ -84,7 +84,7 @@ product {
|
|||||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: data.h, index.html
|
ios: lots of places
|
||||||
type:
|
type:
|
||||||
"audio" or "midi", required
|
"audio" or "midi", required
|
||||||
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
||||||
@ -92,7 +92,7 @@ product {
|
|||||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: data.h, index.html
|
ios: lots of places
|
||||||
channels:
|
channels:
|
||||||
"mono" or "stereo", audio type only, required
|
"mono" or "stereo", audio type only, required
|
||||||
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
||||||
@ -100,7 +100,7 @@ product {
|
|||||||
web: AudioWorkletNode.outputChannelCount - lots of implications
|
web: AudioWorkletNode.outputChannelCount - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: data.h
|
ios: lots of places
|
||||||
sidechain:
|
sidechain:
|
||||||
bus is not part of main audio path (sidechain)? boolean, default false
|
bus is not part of main audio path (sidechain)? boolean, default false
|
||||||
VST3: BusInfo busType
|
VST3: BusInfo busType
|
||||||
@ -108,7 +108,6 @@ product {
|
|||||||
web: web-demo choice of audio I/O buses
|
web: web-demo choice of audio I/O buses
|
||||||
cmd: choice of audio I/O buses
|
cmd: choice of audio I/O buses
|
||||||
android: choice of audio I/O buses
|
android: choice of audio I/O buses
|
||||||
ios: choice of audio I/O buses
|
|
||||||
cv:
|
cv:
|
||||||
bus is control voltage audio-rate? boolean, audio type only, default false
|
bus is control voltage audio-rate? boolean, audio type only, default false
|
||||||
VST3: BusInfo flags
|
VST3: BusInfo flags
|
||||||
@ -168,7 +167,7 @@ product {
|
|||||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: data.h, index.html
|
ios: lots of places
|
||||||
isBypass:
|
isBypass:
|
||||||
parameter is bypass/enabled? boolean - lots of implications, default false
|
parameter is bypass/enabled? boolean - lots of implications, default false
|
||||||
VST3: ParameterInfo, controller get/set parameter/state
|
VST3: ParameterInfo, controller get/set parameter/state
|
||||||
@ -183,16 +182,8 @@ product {
|
|||||||
LV2: manifest.ttl lv2:port, TBD round output value
|
LV2: manifest.ttl lv2:port, TBD round output value
|
||||||
web: not (yet) used
|
web: not (yet) used
|
||||||
cmd: not (yet) used
|
cmd: not (yet) used
|
||||||
ios: not used
|
|
||||||
android: not (yet) used
|
android: not (yet) used
|
||||||
isCpumeter:
|
ios: not (yet) used
|
||||||
parameter is output cpu meter? boolean. It must be an output parameter. It is handled within the wrappers, and not by the plugin user code
|
|
||||||
VST3: data.h, vst3.c
|
|
||||||
LV2: data.h, lv2.c
|
|
||||||
web: processor.js
|
|
||||||
cmd: TODO
|
|
||||||
android: data.h jni.cpp
|
|
||||||
ios: data.h native.mm
|
|
||||||
defaultValue:
|
defaultValue:
|
||||||
default value, number, mapped, required for non-bypass
|
default value, number, mapped, required for non-bypass
|
||||||
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
||||||
@ -277,3 +268,12 @@ product {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makefile dirs:
|
||||||
|
- make always executed from Makefile directory
|
||||||
|
- COMMON_DIR: static common sources (e.g., src/lv2.c)
|
||||||
|
- DATA_DIR: generated sources/data (e.g., src/data.h, data/manifest.ttl.in)
|
||||||
|
- PLUGIN_DIR: plugin sources (e.g., plugin.h)
|
||||||
|
- API_DIR: generated Tibia-related API sources (e.g., plugin_api.h)
|
||||||
|
- MKINC_DIR: Makefile includes (e.g., vars-pre.mk)
|
||||||
|
- build: build files
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,23 +18,60 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
SHELL := bash -o pipefail
|
||||||
|
|
||||||
|
TEMPLATE := android
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
|
COMMON_DIR ?= .
|
||||||
|
DATA_DIR ?= .
|
||||||
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
|
BUILD_BIN_DIR := build/apk/lib/armeabi-v7a
|
||||||
|
BUILD_DATA_DIR := build/assets/index.html
|
||||||
|
|
||||||
|
include $(MKINC_DIR)/vars-pre.mk
|
||||||
|
|
||||||
ifeq ($(HAS_MIDI_IN), yes)
|
ifeq ($(HAS_MIDI_IN), yes)
|
||||||
MIN_API := 29
|
MIN_API := 29
|
||||||
else
|
else
|
||||||
MIN_API := 26
|
MIN_API := 26
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CC := $(ANDROID_NDK_DIR)/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi$(MIN_API)-clang
|
NDK_DIR := $(SDK_DIR)/ndk/$(NDK_VERSION)
|
||||||
CXX := $(ANDROID_NDK_DIR)/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi$(MIN_API)-clang++
|
BUILD_TOOLS_DIR := $(SDK_DIR)/build-tools/$(BUILD_TOOLS_VERSION)
|
||||||
|
|
||||||
|
ANDROID_JAR_FILE := $(SDK_DIR)/platforms/android-$(ANDROID_VERSION)/android.jar
|
||||||
|
ANDROIDX_CORE_FILE := $(ANDROIDX_DIR)/core-$(ANDROIDX_CORE_VERSION).jar
|
||||||
|
ANDROIDX_LIFECYCLE_COMMON_FILE := $(ANDROIDX_DIR)/lifecycle-common-$(ANDROIDX_LIFECYCLE_COMMON_VERSION).jar
|
||||||
|
ANDROIDX_VERSIONEDPARCELABLE_FILE := $(ANDROIDX_DIR)/versionedparcelable-$(ANDROIDX_VERSIONEDPARCELABLE_VERSION).jar
|
||||||
|
KOTLIN_STDLIB_FILE := $(KOTLIN_DIR)/kotlin-stdlib-$(KOTLIN_STDLIB_VERSION).jar
|
||||||
|
KOTLINX_COROUTINES_CORE_FILE := $(KOTLIN_DIR)/kotlinx-coroutines-core-$(KOTLINX_COROUTINES_CORE_VERSION).jar
|
||||||
|
KOTLINX_COROUTINES_CORE_JVM_FILE := $(KOTLIN_DIR)/kotlinx-coroutines-core-jvm-$(KOTLINX_COROUTINES_CORE_JVM_VERSION).jar
|
||||||
|
|
||||||
|
ifeq ($(OS), Windows_NT)
|
||||||
|
NDK_BIN_DIR ?= $(NDK_DIR)/toolchains/llvm/prebuilt/windows-x86_64/bin/
|
||||||
|
else
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
ifeq ($(UNAME_S), Darwin)
|
||||||
|
NDK_BIN_DIR ?= $(NDK_DIR)/toolchains/llvm/prebuilt/darwin-x86_64/bin/
|
||||||
|
else
|
||||||
|
NDK_BIN_DIR ?= $(NDK_DIR)/toolchains/llvm/prebuilt/linux-x86_64/bin/
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
CC := $(NDK_BIN_DIR)/armv7a-linux-androideabi$(MIN_API)-clang
|
||||||
|
CXX := $(NDK_BIN_DIR)/armv7a-linux-androideabi$(MIN_API)-clang++
|
||||||
JC := javac
|
JC := javac
|
||||||
|
|
||||||
APKSIGNER := $(BUILD_TOOLS_DIR)/apksigner
|
APKSIGNER := $(BUILD_TOOLS_DIR)/apksigner
|
||||||
ZIPALIGN := $(BUILD_TOOLS_DIR)/zipalign
|
ZIPALIGN := $(BUILD_TOOLS_DIR)/zipalign
|
||||||
AAPT := $(BUILD_TOOLS_DIR)/aapt
|
AAPT := $(BUILD_TOOLS_DIR)/aapt
|
||||||
D8 := $(BUILD_TOOLS_DIR)/d8
|
D8 := $(BUILD_TOOLS_DIR)/d8
|
||||||
ADB := $(ANDROID_SDK_DIR)/platform-tools/adb
|
ADB := $(SDK_DIR)/platform-tools/adb
|
||||||
|
|
||||||
JARS := \
|
JARS := \
|
||||||
$(ANDROID_JAR_FILE) \
|
$(ANDROID_JAR_FILE) \
|
||||||
@ -54,25 +91,21 @@ ifeq ($(HAS_MIDI_IN), yes)
|
|||||||
CLASSES += MainActivity$$WebAppInterface$$MidiDeviceCallback MainActivity$$WebAppInterface$$1
|
CLASSES += MainActivity$$WebAppInterface$$MidiDeviceCallback MainActivity$$WebAppInterface$$1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -fPIC $(CFLAGS) $(CFLAGS_EXTRA)
|
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS)
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -fPIC -std=c++11 $(CXXFLAGS) $(CXXFLAGS_EXTRA)
|
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -fvisibility=hidden -std=c++11 $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||||
|
|
||||||
LDFLAGS :=
|
LDFLAGS :=
|
||||||
LDFLAGS_ALL := -shared -static-libstdc++ -landroid
|
LDFLAGS_ALL := -shared -static-libstdc++ -landroid
|
||||||
ifeq ($(HAS_MIDI_IN), yes)
|
ifeq ($(HAS_MIDI_IN), yes)
|
||||||
LDFLAGS += -lamidi
|
LDFLAGS += -lamidi
|
||||||
endif
|
endif
|
||||||
LDFLAGS_ALL += $(LDFLAGS) $(LDFLAGS_EXTRA)
|
LDFLAGS_ALL += $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||||
|
|
||||||
JFLAGS :=
|
JFLAGS :=
|
||||||
JFLAGS_ALL := $(JFLAGS) $(JFLAGS_EXTRA)
|
JFLAGS_ALL := $(JFLAGS_EXTRA) $(JFLAGS)
|
||||||
|
|
||||||
C_SRCS := $(C_SRCS_EXTRA)
|
C_SRCS := $(C_SRCS_EXTRA)
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
@ -80,9 +113,13 @@ C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
|||||||
CXX_SRCS := $(COMMON_DIR)/src/jni.cpp $(CXX_SRCS_EXTRA)
|
CXX_SRCS := $(COMMON_DIR)/src/jni.cpp $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
|
DIRS := build build/gen build/apk build/obj build/apk/lib build/apk/lib/armeabi-v7a build/assets
|
||||||
|
|
||||||
ALL := build/$(BUNDLE_NAME).apk
|
ALL := build/$(BUNDLE_NAME).apk
|
||||||
|
|
||||||
-include $(COMMON_DIR)/vars-extra.mk
|
PHONY := all clean install
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
@ -111,7 +148,7 @@ build/apk/lib/armeabi-v7a/lib$(BUNDLE_NAME).so: $(C_OBJS) $(CXX_OBJS) | build/ap
|
|||||||
build/assets/index.html: $(DATA_DIR)/src/index.html | build/assets
|
build/assets/index.html: $(DATA_DIR)/src/index.html | build/assets
|
||||||
cp $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
build/gen build/apk build/obj build/apk/lib/armeabi-v7a build/assets:
|
$(DIRS):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@ -121,9 +158,9 @@ install: build/$(BUNDLE_NAME).apk
|
|||||||
[ -n "`$(ADB) shell pm list packages | grep ^package:$(JAVA_PACKAGE_NAME)`" ] && $(ADB) uninstall $(JAVA_PACKAGE_NAME); exit 0
|
[ -n "`$(ADB) shell pm list packages | grep ^package:$(JAVA_PACKAGE_NAME)`" ] && $(ADB) uninstall $(JAVA_PACKAGE_NAME); exit 0
|
||||||
$(ADB) install $^
|
$(ADB) install $^
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-extra.mk
|
-include $(MKINC_DIR)/rules-extra.mk
|
||||||
|
|
||||||
.PHONY: all clean install
|
.PHONY: $(PHONY)
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
@ -135,4 +172,6 @@ $(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$
|
|||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-secondexp-extra.mk
|
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
@ -20,36 +20,29 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
||||||
|
ANDROID_VERSION := {{=it.android.androidVersion}}
|
||||||
|
|
||||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.android_make?.cflags ?? ""}}
|
{{?(it.android_make?.commonDir || it.make?.commonDir)}}
|
||||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.android_make?.cxxflags ?? ""}}
|
|
||||||
JFLAGS_EXTRA := {{=it.make?.jflags ?? ""}} {{=it.android_make?.jflags ?? ""}}
|
|
||||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.android_make?.ldflags ?? ""}}
|
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.android_make?.cSrcs ?? ""}}
|
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.android_make?.cxxSrcs ?? ""}}
|
|
||||||
|
|
||||||
COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.android_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.android_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
KEY_STORE := {{=it.android_make.keyStore}}
|
{{?(it.android_make?.apiDir || it.make?.apiDir)}}
|
||||||
KEY_ALIAS := {{=it.android_make.keyAlias}}
|
API_DIR := {{=it.android_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
STORE_PASS := {{=it.android_make.storePass}}
|
{{?}}
|
||||||
KEY_PASS := {{=it.android_make.keyPass}}
|
{{?(it.android_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
|
MKINC_DIR := {{=it.android_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
ANDROID_SDK_DIR := {{=it.android_make.sdkDir}}
|
{{?}}
|
||||||
ANDROID_NDK_DIR := ${ANDROID_SDK_DIR}/ndk/{{=it.android_make.ndkVersion}}
|
|
||||||
BUILD_TOOLS_DIR := ${ANDROID_SDK_DIR}/build-tools/{{=it.android_make.buildToolsVersion}}
|
|
||||||
ANDROIDX_DIR := {{=it.android_make.androidxDir}}
|
|
||||||
KOTLIN_DIR := {{=it.android_make.kotlinDir}}
|
|
||||||
|
|
||||||
ANDROID_JAR_FILE := ${ANDROID_SDK_DIR}/platforms/android-{{=it.android_make.androidVersion}}/android.jar
|
|
||||||
ANDROIDX_CORE_FILE := ${ANDROIDX_DIR}/core-{{=it.android_make.androidxCoreVersion}}.jar
|
|
||||||
ANDROIDX_LIFECYCLE_COMMON_FILE := ${ANDROIDX_DIR}/lifecycle-common-{{=it.android_make.androidxLifecycleCommonVersion}}.jar
|
|
||||||
ANDROIDX_VERSIONEDPARCELABLE_FILE := ${ANDROIDX_DIR}/versionedparcelable-{{=it.android_make.androidxVersionedparcelableVersion}}.jar
|
|
||||||
KOTLIN_STDLIB_FILE := ${KOTLIN_DIR}/kotlin-stdlib-{{=it.android_make.kotlinStdlibVersion}}.jar
|
|
||||||
KOTLINX_COROUTINES_CORE_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-{{=it.android_make.kotlinxCoroutinesCoreVersion}}.jar
|
|
||||||
KOTLINX_COROUTINES_CORE_JVM_FILE := ${KOTLIN_DIR}/kotlinx-coroutines-core-jvm-{{=it.android_make.kotlinxCoroutinesCoreJVMVersion}}.jar
|
|
||||||
|
|
||||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
|
{{?it.make?.extra}}
|
||||||
|
{{=it.make.extra}}
|
||||||
|
{{?}}
|
||||||
|
{{?it.android_make?.extra}}
|
||||||
|
{{=it.android_make.extra}}
|
||||||
|
{{?}}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
{{??}}
|
{{??}}
|
||||||
<uses-sdk android:minSdkVersion="26" /> <!-- for androidx core and AAudio -->
|
<uses-sdk android:minSdkVersion="26" /> <!-- for androidx core and AAudio -->
|
||||||
{{?}}
|
{{?}}
|
||||||
<uses-sdk android:targetSdkVersion="34" />
|
<uses-sdk android:targetSdkVersion="{{=it.android.androidVersion}}" />
|
||||||
<application android:label="{{=it.product.name}}">
|
<application android:label="{{=it.product.name}}">
|
||||||
<activity android:name=".MainActivity" android:label="{{=it.product.name}}" android:exported="true">
|
<activity android:name=".MainActivity" android:label="{{=it.product.name}}" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -28,7 +28,7 @@
|
|||||||
#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
#define NUM_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional).length > 0 ? (it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.cv && !x.sidechain && !x.optional)[0].channels == "mono" ? 1 : 2) : 0}}
|
||||||
#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
#define NUM_NON_OPT_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||||
#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
#define NUM_NON_OPT_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output" && !x.optional).reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||||
#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input") .reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
#define NUM_ALL_CHANNELS_IN {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||||
#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
#define NUM_ALL_CHANNELS_OUT {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||||
|
|
||||||
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
#define NUM_MIDI_INPUTS {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||||
@ -80,11 +80,10 @@ static struct {
|
|||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
|
||||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -46,11 +46,8 @@
|
|||||||
|
|
||||||
#if NUM_MIDI_INPUTS > 0
|
#if NUM_MIDI_INPUTS > 0
|
||||||
# include <vector>
|
# include <vector>
|
||||||
# include <amidi/AMidi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
# include <amidi/AMidi.h>
|
||||||
# include "fatica.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
@ -60,29 +57,29 @@
|
|||||||
|
|
||||||
static ma_device device;
|
static ma_device device;
|
||||||
static plugin instance;
|
static plugin instance;
|
||||||
static void *mem;
|
static void * mem;
|
||||||
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
||||||
float zero[BLOCK_SIZE];
|
float zero[BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_IN > 0
|
#if NUM_CHANNELS_IN > 0
|
||||||
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
||||||
float *x_in[NUM_CHANNELS_IN];
|
float * x_in[NUM_CHANNELS_IN];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_IN > 0
|
#if NUM_ALL_CHANNELS_IN > 0
|
||||||
const float *x[NUM_ALL_CHANNELS_IN];
|
const float * x[NUM_ALL_CHANNELS_IN];
|
||||||
#else
|
#else
|
||||||
const float **x;
|
const float ** x;
|
||||||
#endif
|
#endif
|
||||||
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
||||||
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_OUT > 0
|
||||||
float *y_out[NUM_CHANNELS_OUT];
|
float * y_out[NUM_CHANNELS_OUT];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_OUT > 0
|
#if NUM_ALL_CHANNELS_OUT > 0
|
||||||
float *y[NUM_ALL_CHANNELS_OUT];
|
float * y[NUM_ALL_CHANNELS_OUT];
|
||||||
#else
|
#else
|
||||||
float **y;
|
float ** y;
|
||||||
#endif
|
#endif
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
@ -99,18 +96,10 @@ std::vector<PortData> midiPorts;
|
|||||||
# define MIDI_BUFFER_SIZE 1024
|
# define MIDI_BUFFER_SIZE 1024
|
||||||
uint8_t midiBuffer[MIDI_BUFFER_SIZE];
|
uint8_t midiBuffer[MIDI_BUFFER_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
float cpu_meter = 0.f;
|
|
||||||
float sample_rate = 1.f;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
||||||
(void)pDevice;
|
(void)pDevice;
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
const unsigned long long processTimeStart = fatica_time_process();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -127,15 +116,8 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
if (mutex.try_lock()) {
|
if (mutex.try_lock()) {
|
||||||
# if PARAMETERS_N > 0
|
# if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||||
if (param_data[i].out) {
|
if (param_data[i].out)
|
||||||
# ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
if (i == PARAM_OUT_CPU_INDEX) {
|
|
||||||
param_values_prev[i] = param_values[i] = cpu_meter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
||||||
}
|
|
||||||
else if (param_values_prev[i] != param_values[i]) {
|
else if (param_values_prev[i] != param_values[i]) {
|
||||||
plugin_set_parameter(&instance, i, param_values[i]);
|
plugin_set_parameter(&instance, i, param_values[i]);
|
||||||
param_values_prev[i] = param_values[i];
|
param_values_prev[i] = param_values[i];
|
||||||
@ -200,11 +182,6 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
const unsigned long long processTimeEnd = fatica_time_process();
|
|
||||||
fatica_cpu_meter(&cpu_meter, processTimeStart, processTimeEnd, frameCount, sample_rate);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -212,6 +189,10 @@ JNIEXPORT jboolean JNICALL
|
|||||||
JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
||||||
(void)env;
|
(void)env;
|
||||||
(void)thiz;
|
(void)thiz;
|
||||||
|
#ifdef STATE_DSP_CUSTOM
|
||||||
|
(void)plugin_state_load;
|
||||||
|
(void)plugin_state_save;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
||||||
# if NUM_CHANNELS_IN == 0
|
# if NUM_CHANNELS_IN == 0
|
||||||
@ -266,10 +247,6 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
sample_rate = (float)device.sampleRate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t req = plugin_mem_req(&instance);
|
size_t req = plugin_mem_req(&instance);
|
||||||
if (req != 0) {
|
if (req != 0) {
|
||||||
mem = malloc(req);
|
mem = malloc(req);
|
||||||
|
@ -27,5 +27,4 @@ module.exports = function (data, api) {
|
|||||||
api.copyFile(`src${sep}jni.cpp`, `src${sep}jni.cpp`);
|
api.copyFile(`src${sep}jni.cpp`, `src${sep}jni.cpp`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}MainActivity.java`, `src${sep}MainActivity.java`, data);
|
api.generateFileFromTemplateFile(`src${sep}MainActivity.java`, `src${sep}MainActivity.java`, data);
|
||||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -21,25 +21,35 @@
|
|||||||
#ifndef PLUGIN_API_H
|
#ifndef PLUGIN_API_H
|
||||||
#define PLUGIN_API_H
|
#define PLUGIN_API_H
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *handle;
|
void * handle;
|
||||||
const char *format;
|
const char * format;
|
||||||
|
const char * (*get_bindir)(void *handle);
|
||||||
const char * (*get_bindir) (void *handle);
|
|
||||||
const char * (*get_datadir)(void *handle);
|
const char * (*get_datadir)(void *handle);
|
||||||
} plugin_callbacks;
|
} plugin_callbacks;
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *handle;
|
void * handle;
|
||||||
const char *format;
|
void (*lock)(void *handle);
|
||||||
|
void (*unlock)(void *handle);
|
||||||
|
int (*write)(void *handle, const char *data, size_t length);
|
||||||
|
{{?it.product.parameters.find(x => x.direction == "input")}}
|
||||||
|
void (*set_parameter)(void *handle, size_t index, float value);
|
||||||
|
{{?}}
|
||||||
|
} plugin_state_callbacks;
|
||||||
|
{{?}}
|
||||||
|
|
||||||
const char * (*get_bindir) (void *handle);
|
typedef struct {
|
||||||
const char * (*get_datadir) (void *handle);
|
void * handle;
|
||||||
void (*set_parameter_begin)(void *handle, size_t index);
|
const char * format;
|
||||||
void (*set_parameter) (void *handle, size_t index, float value);
|
const char * (*get_bindir)(void *handle);
|
||||||
void (*set_parameter_end) (void *handle, size_t index);
|
const char * (*get_datadir)(void *handle);
|
||||||
|
{{?it.product.parameters.find(x => x.direction == "input")}}
|
||||||
|
void (*set_parameter_begin)(void *handle, size_t index, float value);
|
||||||
|
void (*set_parameter)(void *handle, size_t index, float value);
|
||||||
|
void (*set_parameter_end)(void *handle, size_t index, float value);
|
||||||
|
{{?}}
|
||||||
} plugin_ui_callbacks;
|
} plugin_ui_callbacks;
|
||||||
|
|
||||||
{{?it.product.parameters.length > 0}}
|
{{?it.product.parameters.length > 0}}
|
||||||
@ -47,8 +57,7 @@ enum {
|
|||||||
{{~it.product.parameters :p}}
|
{{~it.product.parameters :p}}
|
||||||
plugin_parameter_{{=p.id}},
|
plugin_parameter_{{=p.id}},
|
||||||
{{~}}
|
{{~}}
|
||||||
|
plugin_parameter__count
|
||||||
plugin_parameter_count
|
|
||||||
};
|
};
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
@ -22,5 +22,5 @@ var path = require("path");
|
|||||||
var sep = path.sep;
|
var sep = path.sep;
|
||||||
|
|
||||||
module.exports = function (data, api) {
|
module.exports = function (data, api) {
|
||||||
api.generateFileFromTemplateFile(`src${sep}plugin_api.h`, `src${sep}plugin_api.h`, data);
|
api.generateFileFromTemplateFile(`src${sep}plugin_api.h`, `plugin_api.h`, data);
|
||||||
};
|
};
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2024 Orastron Srl unipersonale
|
# Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,8 +18,23 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
SHELL := bash -o pipefail
|
||||||
|
|
||||||
|
TEMPLATE := cmd
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
|
COMMON_DIR ?= .
|
||||||
|
DATA_DIR ?= .
|
||||||
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
|
BUILD_BIN_DIR := build
|
||||||
|
BUILD_DATA_DIR := build
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-pre.mk
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
EXE_SUFFIX := .exe
|
EXE_SUFFIX := .exe
|
||||||
else
|
else
|
||||||
@ -29,26 +44,25 @@ else
|
|||||||
BINDIR := $(PREFIX)/bin
|
BINDIR := $(PREFIX)/bin
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
TINYWAV_DIR ?= ../tinywav
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
MIDI_PARSER_DIR ?= ../midi-parser
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
|
||||||
|
|
||||||
CC := gcc
|
CC := gcc
|
||||||
CXX := g++
|
CXX := g++
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include -fPIC $(CFLAGS) $(CFLAGS_EXTRA)
|
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
LDFLAGS :=
|
LDFLAGS :=
|
||||||
LDFLAGS_ALL := $(LDFLAGS) $(LDFLAGS_EXTRA)
|
LDFLAGS_ALL := $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS)
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include -fPIC $(CXXFLAGS) $(CXXFLAGS_EXTRA)
|
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PROGRAM := $(BUNDLE_NAME)$(EXE_SUFFIX)
|
PROGRAM := $(BUNDLE_NAME)$(EXE_SUFFIX)
|
||||||
@ -62,9 +76,19 @@ C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
|||||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
|
DIRS := build build/obj
|
||||||
|
|
||||||
ALL := build/$(PROGRAM)
|
ALL := build/$(PROGRAM)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/vars-extra.mk
|
STRIP_ALL := build/$(PROGRAM)
|
||||||
|
STRIP_PREREQS := $(STRIP_ALL)
|
||||||
|
|
||||||
|
PHONY := all clean strip
|
||||||
|
ifneq ($(OS), Windows_NT)
|
||||||
|
PHONY := $(PHONY) install
|
||||||
|
endif
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
@ -76,23 +100,24 @@ build/$(PROGRAM): $(C_OBJS) $(CXX_OBJS) build/obj/tinywav.o | build
|
|||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build build/obj:
|
$(DIRS):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
strip: $(STRIP_PREREQS)
|
||||||
.PHONY: all clean
|
strip build/$(PROGRAM)
|
||||||
else
|
|
||||||
|
ifneq ($(OS), Windows_NT)
|
||||||
install: all
|
install: all
|
||||||
mkdir -m 0755 -p $(BINDIR)
|
mkdir -m 0755 -p $(BINDIR)
|
||||||
install -m 0755 build/$(PROGRAM) $(BINDIR)
|
install -m 0755 build/$(PROGRAM) $(BINDIR)
|
||||||
|
|
||||||
.PHONY: all clean install
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-extra.mk
|
.PHONY: $(PHONY)
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/rules-extra.mk
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
@ -107,4 +132,6 @@ $(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$
|
|||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-secondexp-extra.mk
|
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
@ -20,18 +20,27 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.cmd_make?.cflags ?? ""}}
|
{{?(it.cmd_make?.commonDir || it.make?.commonDir)}}
|
||||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.cmd_make?.cxxflags ?? ""}}
|
|
||||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.cmd_make?.ldflags ?? ""}}
|
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.cmd_make?.cSrcs ?? ""}}
|
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.cmd_make?.cxxSrcs ?? ""}}
|
|
||||||
|
|
||||||
COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.cmd_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.cmd_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
TINYWAV_DIR := {{=it.cmd_make.tinywavDir}}
|
{{?(it.cmd_make?.apiDir || it.make?.apiDir)}}
|
||||||
MIDI_PARSER_DIR := {{=it.cmd_make.midiParserDir}}
|
API_DIR := {{=it.cmd_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.cmd_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
|
MKINC_DIR := {{=it.cmd_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
|
{{?it.make?.extra}}
|
||||||
|
{{=it.make.extra}}
|
||||||
|
{{?}}
|
||||||
|
{{?it.cmd_make?.extra}}
|
||||||
|
{{=it.cmd_make.extra}}
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -83,3 +83,7 @@ static struct {
|
|||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -162,6 +162,11 @@ float clampf(float x, float m, float M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
|
#ifdef STATE_DSP_CUSTOM
|
||||||
|
(void)plugin_state_load;
|
||||||
|
(void)plugin_state_save;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++)
|
for (size_t i = 0; i < PARAMETERS_N; i++)
|
||||||
param_values[i] = param_data[i].def;
|
param_values[i] = param_data[i].def;
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
#ifndef FATICA_H
|
|
||||||
#define FATICA_H
|
|
||||||
|
|
||||||
// API
|
|
||||||
|
|
||||||
// unit = 100-nanosecond starting from somewhen
|
|
||||||
unsigned long long fatica_time_process(void);
|
|
||||||
void fatica_cpu_meter(float *value, unsigned long long start, unsigned long long end, uint32_t sample_count, float sample_rate);
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
|
|
||||||
# include <windows.h>
|
|
||||||
|
|
||||||
static ULONGLONG filetime_to_ull(const FILETIME* ft) {
|
|
||||||
return (((ULONGLONG)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long long fatica_time_process(void) {
|
|
||||||
FILETIME creationTime, exitTime, kernelTime, userTime;
|
|
||||||
const DWORD threadId = GetCurrentThreadId();
|
|
||||||
const HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, threadId);
|
|
||||||
if (!GetThreadTimes(hThread, &creationTime, &exitTime, &kernelTime, &userTime))
|
|
||||||
return 0ull;
|
|
||||||
CloseHandle(hThread);
|
|
||||||
return (unsigned long long) (filetime_to_ull(&kernelTime) + filetime_to_ull(&userTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__linux__)
|
|
||||||
|
|
||||||
# ifndef _XOPEN_SOURCE
|
|
||||||
# if __STDC_VERSION__ >= 199901L
|
|
||||||
# define _XOPEN_SOURCE 600
|
|
||||||
# else
|
|
||||||
# define _XOPEN_SOURCE 500
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# include <time.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
|
|
||||||
unsigned long long fatica_time_process(void) {
|
|
||||||
struct timespec ts;
|
|
||||||
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0)
|
|
||||||
return 0ull;
|
|
||||||
return (unsigned long long) (ts.tv_sec * 1e7 + ts.tv_nsec / 1e2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <mach/mach.h>
|
|
||||||
# include <mach/thread_act.h>
|
|
||||||
|
|
||||||
unsigned long long fatica_time_process(void) {
|
|
||||||
thread_t thread = mach_thread_self();
|
|
||||||
thread_basic_info_data_t info;
|
|
||||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
|
||||||
if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count) != KERN_SUCCESS)
|
|
||||||
return 0ull;
|
|
||||||
return (info.user_time.seconds + info.system_time.seconds) * 1000
|
|
||||||
+ (info.user_time.microseconds + info.system_time.microseconds) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
# error "System not supported"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void fatica_cpu_meter(float *value, unsigned long long start, unsigned long long end, uint32_t sample_count, float sample_rate) {
|
|
||||||
const unsigned long long processTime100n = end - start;
|
|
||||||
const double processTimeMs = ((double) processTime100n) * 1.0e-4;
|
|
||||||
*value = *value * 0.99f + ((float) (processTimeMs * sample_count / (sample_rate * 1000))) * 0.01f;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FATICA_H
|
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,13 +18,23 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
SHELL := bash -o pipefail
|
||||||
|
|
||||||
|
TEMPLATE := daisy-seed
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
TARGET := $(BUNDLE_NAME)
|
COMMON_DIR ?= .
|
||||||
|
DATA_DIR ?= .
|
||||||
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
-include $(MKINC_DIR)/vars-pre.mk
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
LIBDAISY_DIR ?= ../libDaisy
|
||||||
|
|
||||||
|
TARGET := $(BUNDLE_NAME)
|
||||||
|
|
||||||
CPP_SOURCES := $(COMMON_DIR)/src/main.cpp $(CXX_SRCS_EXTRA)
|
CPP_SOURCES := $(COMMON_DIR)/src/main.cpp $(CXX_SRCS_EXTRA)
|
||||||
|
|
||||||
@ -34,8 +44,8 @@ include $(SYSTEM_FILES_DIR)/Makefile
|
|||||||
|
|
||||||
C_SOURCES += $(C_SRCS_EXTRA)
|
C_SOURCES += $(C_SRCS_EXTRA)
|
||||||
|
|
||||||
CFLAGS += -I$(DATA_DIR)/src -I$(PLUGIN_DIR) $(CFLAGS_EXTRA)
|
CFLAGS += -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(CFLAGS_EXTRA)
|
||||||
LDFLAGS += $(LDFLAGS_EXTRA)
|
LDFLAGS += $(LDFLAGS_EXTRA)
|
||||||
CXXFLAGS += -I$(DATA_DIR)/src -I$(PLUGIN_DIR) $(CXXFLAGS_EXTRA)
|
CXXFLAGS += -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(CXXFLAGS_EXTRA)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/extra.mk
|
-include $(COMMON_DIR)/extra.mk
|
||||||
|
@ -20,15 +20,25 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.daisy_seed_make?.cflags ?? ""}}
|
{{?(it.daisy_seed_make?.commonDir || it.make?.commonDir)}}
|
||||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.daisy_seed_make?.cxxflags ?? ""}}
|
|
||||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.daisy_seed_make?.ldflags ?? ""}}
|
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.daisy_seed_make?.cSrcs ?? ""}}
|
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.daisy_seed_make?.cxxSrcs ?? ""}}
|
|
||||||
|
|
||||||
COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.daisy_seed_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.daisy_seed_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.daisy_seed_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.daisy_seed_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.daisy_seed_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.daisy_seed_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.daisy_seed_make?.apiDir || it.make?.apiDir)}}
|
||||||
|
API_DIR := {{=it.daisy_seed_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.daisy_seed_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
|
MKINC_DIR := {{=it.daisy_seed_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
LIBDAISY_DIR := {{=it.daisy_seed_make.libdaisyDir}}
|
{{?it.make?.extra}}
|
||||||
|
{{=it.make.extra}}
|
||||||
|
{{?}}
|
||||||
|
{{?it.daisy_seed_make?.extra}}
|
||||||
|
{{=it.daisy_seed_make.extra}}
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -98,3 +98,7 @@ static int midi_cc_maps[NUM_PARAMETERS] = { {{~it.daisy_seed.midiCCMaps :p}}{{=p
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -150,6 +150,11 @@ static void AudioCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
#ifdef STATE_DSP_CUSTOM
|
||||||
|
(void)plugin_state_load;
|
||||||
|
(void)plugin_state_save;
|
||||||
|
#endif
|
||||||
|
|
||||||
hardware.Configure();
|
hardware.Configure();
|
||||||
hardware.Init();
|
hardware.Init();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2024 Orastron Srl unipersonale
|
# Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,41 +18,71 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
SHELL := bash -o pipefail
|
||||||
|
|
||||||
|
TEMPLATE := ios
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
COMMON_DIR ?= .
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
DATA_DIR ?= .
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
|
BUILD_BIN_DIR := build/gen/res
|
||||||
|
BUILD_DATA_DIR := build/gen/res
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-pre.mk
|
||||||
|
|
||||||
|
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||||
|
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS)
|
||||||
|
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fvisibility=hidden $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||||
|
|
||||||
|
LDFLAGS :=
|
||||||
|
LDFLAGS_ALL := $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||||
|
|
||||||
SOURCES := \
|
SOURCES := \
|
||||||
|
$(C_SRCS_EXTRA) \
|
||||||
|
$(M_SRCS_EXTRA) \
|
||||||
|
$(CXX_SRCS_EXTRA) \
|
||||||
|
$(SRCS_EXTRA) \
|
||||||
$(DATA_DIR)/src/data.h \
|
$(DATA_DIR)/src/data.h \
|
||||||
$(DATA_DIR)/src/index.html \
|
|
||||||
$(COMMON_DIR)/src/app.swift \
|
$(COMMON_DIR)/src/app.swift \
|
||||||
$(COMMON_DIR)/src/native.mm \
|
$(COMMON_DIR)/src/native.mm \
|
||||||
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
||||||
$(PLUGIN_DIR)/plugin.h \
|
$(PLUGIN_DIR)/plugin.h \
|
||||||
$(PLUGIN_DIR)/fatica.h \
|
$(API_DIR)/plugin_api.h
|
||||||
$(C_SRCS_EXTRA) \
|
|
||||||
$(CXX_SRCS_EXTRA) \
|
|
||||||
$(SRCS_EXTRA)
|
|
||||||
SOURCES_OUT := $(addprefix build/gen/src/, $(notdir $(SOURCES)))
|
SOURCES_OUT := $(addprefix build/gen/src/, $(notdir $(SOURCES)))
|
||||||
|
|
||||||
ALL = build/gen/$(BUNDLE_NAME).xcodeproj
|
RESOURCES := $(PLUGIN_DIR)/index.html
|
||||||
|
RESOURCES_OUT := $(addprefix build/gen/res/, $(notdir $(RESOURCES)))
|
||||||
|
|
||||||
-include $(COMMON_DIR)/vars-extra.mk
|
DIRS := build build/gen build/gen/src build/gen/res
|
||||||
|
|
||||||
|
ALL := build/gen/$(BUNDLE_NAME).xcodeproj
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
build/gen/$(BUNDLE_NAME).xcodeproj: $(SOURCES_OUT)
|
build/gen/$(BUNDLE_NAME).xcodeproj: $(SOURCES_OUT) $(RESOURCES_OUT) build/project_out.yml
|
||||||
xcodegen generate --spec project.yml -r build/gen -p build/gen
|
xcodegen generate --spec build/project_out.yml -r build/gen -p build/gen
|
||||||
|
|
||||||
build/gen/src:
|
build/project_out.yml: project.yml build/
|
||||||
|
sed -e 's|@CFLAGS_ALL@|$(CFLAGS_ALL)|g' \
|
||||||
|
-e 's|@CXXFLAGS_ALL@|$(CXXFLAGS_ALL)|g' \
|
||||||
|
-e 's|@LDFLAGS_ALL@|$(LDFLAGS_ALL)|g' $< > $@
|
||||||
|
|
||||||
|
$(DIRS):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-extra.mk
|
-include $(MKINC_DIR)/rules-extra.mk
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
@ -63,4 +93,9 @@ PERCENT := %
|
|||||||
$(SOURCES_OUT): build/gen/src/%: $$(filter $$(PERCENT)/%,$$(SOURCES)) | build/gen/src
|
$(SOURCES_OUT): build/gen/src/%: $$(filter $$(PERCENT)/%,$$(SOURCES)) | build/gen/src
|
||||||
cp -R $^ $@
|
cp -R $^ $@
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-secondexp-extra.mk
|
$(RESOURCES_OUT): build/gen/res/%: $$(filter $$(PERCENT)/%,$$(RESOURCES)) | build/gen/res
|
||||||
|
cp -R $^ $@
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
@ -30,13 +30,26 @@ targets:
|
|||||||
type: application
|
type: application
|
||||||
sources:
|
sources:
|
||||||
- path: src
|
- path: src
|
||||||
|
- path: res
|
||||||
|
type: folder
|
||||||
|
|
||||||
{{?it.ios_make.dependencies}}
|
{{?it.ios_make.dependencies}}
|
||||||
dependencies: {{~it.ios_make.dependencies :d}}
|
dependencies:
|
||||||
|
{{~it.ios_make.dependencies :d}}
|
||||||
- target: {{=d}}{{~}}
|
- target: {{=d}}{{~}}
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
base:
|
base:
|
||||||
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
||||||
|
|
||||||
|
{{?it.ios_make.development_team}}
|
||||||
|
CODE_SIGN_STYLE: Automatic
|
||||||
|
DEVELOPMENT_TEAM: {{=it.ios_make.development_team}}
|
||||||
|
{{?}}
|
||||||
|
OTHER_CFLAGS: "$(inherited) @CFLAGS_ALL@"
|
||||||
|
OTHER_CPLUSPLUSFLAGS: "$(inherited) @CXXFLAGS_ALL@"
|
||||||
|
OTHER_LDFLAGS: "$(inherited) @LDFLAGS_ALL@"
|
||||||
SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h
|
SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h
|
||||||
{{?it.ios_make.headerSearchPaths}}
|
{{?it.ios_make.headerSearchPaths}}
|
||||||
HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}}
|
HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}}
|
||||||
|
@ -20,10 +20,25 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.ios_make?.cSrcs ?? ""}}
|
{{?(it.ios_make?.commonDir || it.make?.commonDir)}}
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.ios_make?.cxxSrcs ?? ""}}
|
|
||||||
SRCS_EXTRA := {{=it.ios_make?.srcsExtra ?? ""}}
|
|
||||||
|
|
||||||
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.ios_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.ios_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.ios_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.ios_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.ios_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.ios_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.ios_make?.apiDir || it.make?.apiDir)}}
|
||||||
|
API_DIR := {{=it.ios_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.ios_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
|
MKINC_DIR := {{=it.ios_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
|
{{?it.make?.extra}}
|
||||||
|
{{=it.make.extra}}
|
||||||
|
{{?}}
|
||||||
|
{{?it.ios_make?.extra}}
|
||||||
|
{{=it.ios_make.extra}}
|
||||||
|
{{?}}
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import WebKit
|
@preconcurrency import WebKit
|
||||||
import AVFoundation
|
import AVFoundation
|
||||||
|
|
||||||
struct WebView: UIViewRepresentable {
|
struct WebView: UIViewRepresentable {
|
||||||
class Coordinator: NSObject, WKScriptMessageHandlerWithReply {
|
class Coordinator: NSObject, WKScriptMessageHandlerWithReply, WKNavigationDelegate {
|
||||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
|
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
|
||||||
guard let body = message.body as? [String : Any] else { return }
|
guard let body = message.body as? [String : Any] else { return }
|
||||||
guard let name = body["name"] as? String else { return }
|
guard let name = body["name"] as? String else { return }
|
||||||
@ -57,6 +57,15 @@ struct WebView: UIViewRepresentable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
||||||
|
if let url = navigationAction.request.url, navigationAction.navigationType == .linkActivated {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
decisionHandler(.cancel)
|
||||||
|
} else {
|
||||||
|
decisionHandler(.allow)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCoordinator() -> Coordinator {
|
func makeCoordinator() -> Coordinator {
|
||||||
@ -67,8 +76,10 @@ struct WebView: UIViewRepresentable {
|
|||||||
|
|
||||||
func makeUIView(context: Context) -> WKWebView {
|
func makeUIView(context: Context) -> WKWebView {
|
||||||
let configuration = WKWebViewConfiguration()
|
let configuration = WKWebViewConfiguration()
|
||||||
configuration.userContentController.addScriptMessageHandler(Coordinator(), contentWorld: .page, name: "listener")
|
configuration.userContentController.addScriptMessageHandler(Coordinator(), contentWorld: .page, name: "messageHandler")
|
||||||
|
configuration.setValue(true, forKey: "allowUniversalAccessFromFileURLs")
|
||||||
let webView = WKWebView(frame: .zero, configuration: configuration)
|
let webView = WKWebView(frame: .zero, configuration: configuration)
|
||||||
|
webView.navigationDelegate = context.coordinator
|
||||||
//webView.isInspectable = true
|
//webView.isInspectable = true
|
||||||
return webView
|
return webView
|
||||||
}
|
}
|
||||||
@ -81,8 +92,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let url = Bundle.main.url(forResource: "index", withExtension: "html")
|
let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "res")
|
||||||
WebView(url: url!)
|
WebView(url: url!).ignoresSafeArea().preferredColorScheme(.dark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -80,8 +80,8 @@ static struct {
|
|||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
|
||||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
|
||||||
{{?}}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
@ -21,13 +21,12 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||||
<title>{{=it.product.name}}</title>
|
<title>{{=it.product.name}}</title>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
function request(data) {
|
function request(data) {
|
||||||
return window.webkit.messageHandlers.listener.postMessage(data);
|
return window.webkit.messageHandlers.messageHandler.postMessage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function needAudioPermission() {
|
function needAudioPermission() {
|
||||||
@ -78,12 +77,11 @@ window.onload = async function () {
|
|||||||
topButtonElem = document.getElementById("topButton");
|
topButtonElem = document.getElementById("topButton");
|
||||||
var paramsElem = document.getElementById("params");
|
var paramsElem = document.getElementById("params");
|
||||||
|
|
||||||
for (var i = 0; i < data.buses.length; i++) {
|
for (var i = 0; i < data.buses.length; i++)
|
||||||
if (data.buses[i].type == "audio" && data.buses[i].direction == "input") {
|
if (data.buses[i].type == "audio" && data.buses[i].direction == "input") {
|
||||||
hasAudioPermission = !await needAudioPermission();
|
hasAudioPermission = !await needAudioPermission();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
||||||
topButtonElem.addEventListener("click", async function () {
|
topButtonElem.addEventListener("click", async function () {
|
||||||
@ -168,17 +166,17 @@ function gotAudioPermission() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#topButton {
|
#topButton {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
border: 0;
|
||||||
background-color: #04aa6d;
|
background-color: #04aa6d;
|
||||||
@ -187,15 +185,15 @@ function gotAudioPermission() {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.range {
|
.range {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<input id="topButton" type="button">
|
<input id="topButton" type="button">
|
||||||
<div id="params"></div>
|
<div id="params"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -25,47 +25,44 @@
|
|||||||
#include "plugin_api.h"
|
#include "plugin_api.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
# include <algorithm>
|
#include <algorithm>
|
||||||
#endif
|
#endif
|
||||||
#if PARAMETERS_N + NUM_MIDI_INPUTS > 0
|
#if PARAMETERS_N + NUM_MIDI_INPUTS > 0
|
||||||
# include <mutex>
|
#include <mutex>
|
||||||
#endif
|
#endif
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#define MINIAUDIO_IMPLEMENTATION
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
#define MA_NO_RUNTIME_LINKING
|
#define MA_NO_RUNTIME_LINKING
|
||||||
#include "miniaudio.h"
|
#include "miniaudio.h"
|
||||||
#define BLOCK_SIZE 32
|
#define BLOCK_SIZE 32
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
# include "fatica.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ma_device device;
|
static ma_device device;
|
||||||
static ma_device_config deviceConfig;
|
static ma_device_config deviceConfig;
|
||||||
char device_inited = 0;
|
char device_inited = 0;
|
||||||
static plugin instance;
|
static plugin instance;
|
||||||
static void *mem;
|
static void * mem;
|
||||||
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
||||||
float zero[BLOCK_SIZE];
|
float zero[BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_IN > 0
|
#if NUM_CHANNELS_IN > 0
|
||||||
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
float x_buf[NUM_CHANNELS_IN * BLOCK_SIZE];
|
||||||
float *x_in[NUM_CHANNELS_IN];
|
float * x_in[NUM_CHANNELS_IN];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_IN > 0
|
#if NUM_ALL_CHANNELS_IN > 0
|
||||||
const float *x[NUM_ALL_CHANNELS_IN];
|
const float * x[NUM_ALL_CHANNELS_IN];
|
||||||
#else
|
#else
|
||||||
const float **x;
|
const float ** x;
|
||||||
#endif
|
#endif
|
||||||
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
#if NUM_NON_OPT_CHANNELS_OUT > 0
|
||||||
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
float y_buf[NUM_NON_OPT_CHANNELS_OUT * BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_OUT > 0
|
||||||
float *y_out[NUM_CHANNELS_OUT];
|
float * y_out[NUM_CHANNELS_OUT];
|
||||||
#endif
|
#endif
|
||||||
#if NUM_ALL_CHANNELS_OUT > 0
|
#if NUM_ALL_CHANNELS_OUT > 0
|
||||||
float *y[NUM_ALL_CHANNELS_OUT];
|
float * y[NUM_ALL_CHANNELS_OUT];
|
||||||
#else
|
#else
|
||||||
float **y;
|
float ** y;
|
||||||
#endif
|
#endif
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
@ -81,18 +78,10 @@ MIDIPortRef midiPort = NULL;
|
|||||||
uint8_t midiBuffer[MIDIBUFFERLEN];
|
uint8_t midiBuffer[MIDIBUFFERLEN];
|
||||||
int midiBuffer_i = 0;
|
int midiBuffer_i = 0;
|
||||||
#endif
|
#endif
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
float cpu_meter = 0.f;
|
|
||||||
float sample_rate = 1.f;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
||||||
(void)pDevice;
|
(void)pDevice;
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
const unsigned long long processTimeStart = fatica_time_process();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -103,15 +92,8 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
if (mutex.try_lock()) {
|
if (mutex.try_lock()) {
|
||||||
# if PARAMETERS_N > 0
|
# if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||||
if (param_data[i].out) {
|
if (param_data[i].out)
|
||||||
# ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
if (i == PARAM_OUT_CPU_INDEX) {
|
|
||||||
param_values_prev[i] = param_values[i] = cpu_meter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
param_values_prev[i] = param_values[i] = plugin_get_parameter(&instance, i);
|
||||||
}
|
|
||||||
else if (param_values_prev[i] != param_values[i]) {
|
else if (param_values_prev[i] != param_values[i]) {
|
||||||
plugin_set_parameter(&instance, i, param_values[i]);
|
plugin_set_parameter(&instance, i, param_values[i]);
|
||||||
param_values_prev[i] = param_values[i];
|
param_values_prev[i] = param_values[i];
|
||||||
@ -170,11 +152,6 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
|
|||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
__asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr));
|
__asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
const unsigned long long processTimeEnd = fatica_time_process();
|
|
||||||
fatica_cpu_meter(&cpu_meter, processTimeStart, processTimeEnd, frameCount, sample_rate);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (NUM_MIDI_INPUTS > 0)
|
#if (NUM_MIDI_INPUTS > 0)
|
||||||
@ -187,6 +164,7 @@ void (^midiNotifyBlock)(const MIDINotification *message) = ^(const MIDINotificat
|
|||||||
};
|
};
|
||||||
|
|
||||||
void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^(const MIDIEventList *evtlist, void *srcConnRefCon) {
|
void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^(const MIDIEventList *evtlist, void *srcConnRefCon) {
|
||||||
|
(void)srcConnRefCon;
|
||||||
const MIDIEventPacket *p = evtlist->packet;
|
const MIDIEventPacket *p = evtlist->packet;
|
||||||
for (UInt32 i = 0; i < evtlist->numPackets; i++) {
|
for (UInt32 i = 0; i < evtlist->numPackets; i++) {
|
||||||
for (UInt32 j = 0; j < p->wordCount; j++) {
|
for (UInt32 j = 0; j < p->wordCount; j++) {
|
||||||
@ -213,6 +191,11 @@ void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^(
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
char audioStart() {
|
char audioStart() {
|
||||||
|
#ifdef STATE_DSP_CUSTOM
|
||||||
|
(void)plugin_state_load;
|
||||||
|
(void)plugin_state_save;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
||||||
# if NUM_CHANNELS_IN == 0
|
# if NUM_CHANNELS_IN == 0
|
||||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
@ -293,9 +276,6 @@ char audioStart() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
plugin_set_sample_rate(&instance, (float)device.sampleRate);
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
sample_rate = (float)device.sampleRate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t req = plugin_mem_req(&instance);
|
size_t req = plugin_mem_req(&instance);
|
||||||
if (req != 0) {
|
if (req != 0) {
|
||||||
|
@ -26,6 +26,5 @@ module.exports = function (data, api) {
|
|||||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||||
api.copyFile(`src${sep}native.mm`, `src${sep}native.mm`);
|
api.copyFile(`src${sep}native.mm`, `src${sep}native.mm`);
|
||||||
api.copyFile(`src${sep}app-Bridging-Header.h`, `src${sep}app-Bridging-Header.h`);
|
api.copyFile(`src${sep}app-Bridging-Header.h`, `src${sep}app-Bridging-Header.h`);
|
||||||
api.copyFile(`src${sep}app.swift`, `src${sep}app.swift`, data);
|
api.copyFile(`src${sep}app.swift`, `src${sep}app.swift`);
|
||||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2024 Orastron Srl unipersonale
|
# Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,13 +18,30 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
SHELL := bash -o pipefail
|
||||||
|
|
||||||
|
TEMPLATE := lv2
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
|
COMMON_DIR ?= .
|
||||||
|
DATA_DIR ?= .
|
||||||
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
|
BUNDLE_DIR := $(BUNDLE_NAME).lv2
|
||||||
|
|
||||||
|
BUILD_BIN_DIR := build/$(BUNDLE_DIR)
|
||||||
|
BUILD_DATA_DIR := build/$(BUNDLE_DIR)
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-pre.mk
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
DLL_SUFFIX := .dll
|
DLL_SUFFIX := .dll
|
||||||
UI_TYPE := WindowsUI
|
UI_TYPE := WindowsUI
|
||||||
LV2DIR := $(shell echo '$(COMMONPROGRAMFILES)' | sed 's:\\:/:g')/LV2
|
LV2DIR := $(subst \,/,$(COMMONPROGRAMFILES))/LV2
|
||||||
LV2DIR_USER := $(shell echo '$(APPDATA)' | sed 's:\\:/:g')/LV2
|
LV2DIR_USER := $(subst \,/,$(APPDATA))/LV2
|
||||||
CC := gcc
|
CC := gcc
|
||||||
CXX := g++
|
CXX := g++
|
||||||
else
|
else
|
||||||
@ -47,30 +64,21 @@ else
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) $(shell pkg-config --cflags lv2) -fPIC $(CFLAGS) $(CFLAGS_EXTRA)
|
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(shell pkg-config --cflags lv2) -fPIC -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
LDFLAGS :=
|
LDFLAGS :=
|
||||||
LDFLAGS_ALL := -shared $(shell pkg-config --libs lv2) $(LDFLAGS) $(LDFLAGS_EXTRA)
|
LDFLAGS_ALL := -shared $(shell pkg-config --libs lv2) $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS)
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -fPIC $(CXXFLAGS) $(CXXFLAGS_EXTRA)
|
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(shell pkg-config --cflags lv2) -fPIC -fvisibility=hidden $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
BUNDLE_DIR := $(BUNDLE_NAME).lv2
|
|
||||||
|
|
||||||
BUNDLE_DATA_PATH := build/$(BUNDLE_DIR)
|
|
||||||
BUNDLE_BIN_PATH := build/$(BUNDLE_DIR)
|
|
||||||
|
|
||||||
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||||
|
|
||||||
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
||||||
@ -82,9 +90,16 @@ M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
|||||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
|
DIRS := build build/$(BUNDLE_DIR) build/obj
|
||||||
|
|
||||||
ALL := build/$(BUNDLE_DIR)/manifest.ttl build/$(BUNDLE_DIR)/$(DLL_FILE)
|
ALL := build/$(BUNDLE_DIR)/manifest.ttl build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/vars-extra.mk
|
STRIP_ALL := build/$(BUNDLE_DIR)/$(DLL_FILE) build/$(BUNDLE_DIR)/manifest.ttl
|
||||||
|
STRIP_PREREQS := $(STRIP_ALL)
|
||||||
|
|
||||||
|
.PHONY: all clean strip install install-user
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
@ -99,43 +114,55 @@ build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDL
|
|||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build/$(BUNDLE_DIR) build/obj:
|
$(DIRS):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
|
strip: $(STRIP_PREREQS)
|
||||||
|
strip -Sx build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||||
|
#Reaper can't handle this
|
||||||
|
#rdfproc lv2_store parse build/$(BUNDLE_DIR)/manifest.ttl turtle || (rm lv2_store* && exit 1)
|
||||||
|
#rdfproc lv2_store serialize ntriples > build/$(BUNDLE_DIR)/manifest.ttl || (rm lv2_store* && exit 1)
|
||||||
|
#rm lv2_store*
|
||||||
|
#f=`cat build/$(BUNDLE_DIR)/manifest.ttl` && echo "$f" | sed '/^[[:space:]]**$/d' > build/$(BUNDLE_DIR)/manifest.ttl
|
||||||
|
$(eval TMP := $(shell mktemp /tmp/index.XXXXXX))
|
||||||
|
sed '/^[[:space:]]*$$/d' build/$(BUNDLE_DIR)/manifest.ttl > $(TMP) || (rm $(TMP) && exit 1)
|
||||||
|
cp $(TMP) build/$(BUNDLE_DIR)/manifest.ttl || (rm $(TMP) && exit 1)
|
||||||
|
rm $(TMP)
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
d=`echo $$d | sed 's:^build/::'` ; \
|
||||||
echo mkdir -m 0755 -p "$(LV2DIR)/$$d"; \
|
echo mkdir -m 0755 -p "$(LV2DIR)/$$d"; \
|
||||||
mkdir -m 0755 -p "$(LV2DIR)/$$d"; \
|
mkdir -m 0755 -p "$(LV2DIR)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||||
d=`echo $$f | sed 's:^build/::'` ; \
|
d=`echo $$f | sed 's:^build/::'` ; \
|
||||||
d=`dirname $$d`; \
|
d=`dirname $$d`; \
|
||||||
echo install -m $$m $$f "$(LV2DIR)/$$d"; \
|
echo install -m $$m $$f "$(LV2DIR)/$$d"; \
|
||||||
install -m $$m $$f "$(LV2DIR)/$$d"; \
|
install -m $$m $$f "$(LV2DIR)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install-user: all
|
install-user: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
d=`echo $$d | sed 's:^build/::'` ; \
|
||||||
echo mkdir -m 0755 -p "$(LV2DIR_USER)/$$d"; \
|
echo mkdir -m 0755 -p "$(LV2DIR_USER)/$$d"; \
|
||||||
mkdir -m 0755 -p "$(LV2DIR_USER)/$$d"; \
|
mkdir -m 0755 -p "$(LV2DIR_USER)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||||
d=`echo $$f | sed 's:^build/::'` ; \
|
d=`echo $$f | sed 's:^build/::'` ; \
|
||||||
d=`dirname $$d`; \
|
d=`dirname $$d`; \
|
||||||
echo install -m $$m $$f "$(LV2DIR_USER)/$$d"; \
|
echo install -m $$m $$f "$(LV2DIR_USER)/$$d"; \
|
||||||
install -m $$m $$f "$(LV2DIR_USER)/$$d"; \
|
install -m $$m $$f "$(LV2DIR_USER)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-extra.mk
|
-include $(MKINC_DIR)/rules-extra.mk
|
||||||
|
|
||||||
.PHONY: all clean install install-user
|
.PHONY: $(PHONY)
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
@ -150,4 +177,6 @@ $(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$
|
|||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-secondexp-extra.mk
|
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
@ -20,15 +20,25 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
|
{{?(it.lv2_make?.commonDir || it.make?.commonDir)}}
|
||||||
COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.lv2_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.lv2_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.lv2_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.lv2_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.lv2_make?.apiDir || it.make?.apiDir)}}
|
||||||
|
API_DIR := {{=it.lv2_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.lv2_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
|
MKINC_DIR := {{=it.lv2_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.lv2_make?.cSrcs ?? ""}}
|
{{?it.make?.extra}}
|
||||||
M_SRCS_EXTRA := {{=it.make?.mSrcs ?? ""}} {{=it.lv2_make?.mSrcs ?? ""}}
|
{{=it.make.extra}}
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.lv2_make?.cxxSrcs ?? ""}}
|
{{?}}
|
||||||
|
{{?it.lv2_make?.extra}}
|
||||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.lv2_make?.cflags ?? ""}}
|
{{=it.lv2_make.extra}}
|
||||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.lv2_make?.cxxflags ?? ""}}
|
{{?}}
|
||||||
|
|
||||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.lv2_make?.ldflags ?? ""}}
|
|
||||||
|
@ -15,18 +15,26 @@
|
|||||||
doap:maintainer [
|
doap:maintainer [
|
||||||
a foaf:Organization ;
|
a foaf:Organization ;
|
||||||
foaf:name "{{=it.company.name}}" ;
|
foaf:name "{{=it.company.name}}" ;
|
||||||
foaf:mbox "{{=it.company.email}}" ;
|
foaf:mbox <mailto:{{=it.company.email}}> ;
|
||||||
rdfs:seeAlso {{=it.tibia.lv2.ttlURI(it.company.url)}}
|
rdfs:seeAlso {{=it.tibia.lv2.ttlURI(it.company.url)}}
|
||||||
] ;
|
] ;
|
||||||
lv2:minorVersion {{=/^([0-9]+)\./.exec(it.lv2.version)[1]}} ;
|
lv2:minorVersion {{=/^([0-9]+)\./.exec(it.lv2.version)[1]}} ;
|
||||||
lv2:microVersion {{=/^[0-9]+\.([0-9]+)/.exec(it.lv2.version)[1]}} ;
|
lv2:microVersion {{=/^[0-9]+\.([0-9]+)/.exec(it.lv2.version)[1]}} ;
|
||||||
{{?it.tibia.lv2.ports.find(p => p.type == "midi")}}
|
{{?(it.tibia.lv2.ports.find(p => p.type == "midi" && !p.optional))}}
|
||||||
lv2:requiredFeature urid:map ;
|
lv2:requiredFeature urid:map ;
|
||||||
lv2:optionalFeature log:log ;
|
{{??}}
|
||||||
|
lv2:optionalFeature urid:map ;
|
||||||
{{?}}
|
{{?}}
|
||||||
|
lv2:optionalFeature log:log ;
|
||||||
lv2:optionalFeature lv2:hardRTCapable ;
|
lv2:optionalFeature lv2:hardRTCapable ;
|
||||||
{{?it.lv2.ui}}
|
{{?(it.product.state && it.product.state.dspCustom)}}
|
||||||
|
lv2:optionalFeature state:threadSafeRestore ;
|
||||||
|
{{?}}
|
||||||
|
{{?it.product.ui}}
|
||||||
ui:ui {{=it.tibia.lv2.ttlURI(it.lv2.ui.uri)}} ;
|
ui:ui {{=it.tibia.lv2.ttlURI(it.lv2.ui.uri)}} ;
|
||||||
|
{{?}}
|
||||||
|
{{?(it.product.state && it.product.state.dspCustom)}}
|
||||||
|
lv2:extensionData state:interface ;
|
||||||
{{?}}
|
{{?}}
|
||||||
lv2:port [
|
lv2:port [
|
||||||
{{~it.tibia.lv2.ports :p:i}}
|
{{~it.tibia.lv2.ports :p:i}}
|
||||||
@ -121,7 +129,7 @@
|
|||||||
{{?}}
|
{{?}}
|
||||||
{{~}}
|
{{~}}
|
||||||
|
|
||||||
{{?it.lv2.ui}}
|
{{?it.product.ui}}
|
||||||
{{=it.tibia.lv2.ttlURI(it.lv2.ui.uri)}}
|
{{=it.tibia.lv2.ttlURI(it.lv2.ui.uri)}}
|
||||||
a ui:@UI_TYPE@ ;
|
a ui:@UI_TYPE@ ;
|
||||||
ui:binary <{{=it.product.bundleName}}@DLL_SUFFIX@> ;
|
ui:binary <{{=it.product.bundleName}}@DLL_SUFFIX@> ;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -27,6 +27,10 @@
|
|||||||
#define DATA_PRODUCT_CONTROL_INPUTS_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
#define DATA_PRODUCT_CONTROL_INPUTS_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
||||||
#define DATA_PRODUCT_CONTROL_OUTPUTS_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
#define DATA_PRODUCT_CONTROL_OUTPUTS_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
||||||
|
|
||||||
|
{{?it.product.buses.find(x => x.type == "midi" && !x.optional)}}
|
||||||
|
#define DATA_PRODUCT_MIDI_REQUIRED
|
||||||
|
{{?}}
|
||||||
|
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
static uint32_t midi_in_index[DATA_PRODUCT_MIDI_INPUTS_N] = {
|
static uint32_t midi_in_index[DATA_PRODUCT_MIDI_INPUTS_N] = {
|
||||||
{{~it.tibia.lv2.ports.filter(x => x.type == "midi" && x.direction == "input") :p}}{{=p.busIndex}}, {{~}}
|
{{~it.tibia.lv2.ports.filter(x => x.type == "midi" && x.direction == "input") :p}}{{=p.busIndex}}, {{~}}
|
||||||
@ -63,19 +67,22 @@ static struct {
|
|||||||
static uint32_t param_out_index[DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
|
static uint32_t param_out_index[DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
|
||||||
{{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "output") :p}}{{=p.paramIndex}}, {{~}}
|
{{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "output") :p}}{{=p.paramIndex}}, {{~}}
|
||||||
};
|
};
|
||||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
|
||||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
|
||||||
{{?}}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{{?it.lv2.ui}}
|
{{?it.product.ui}}
|
||||||
#define DATA_UI
|
#define DATA_UI
|
||||||
#define DATA_LV2_UI_URI "{{=it.tibia.CGetUTF8StringLiteral(it.tibia.lv2.expandURI(it.lv2.ui.uri))}}"
|
#define DATA_LV2_UI_URI "{{=it.tibia.CGetUTF8StringLiteral(it.tibia.lv2.expandURI(it.lv2.ui.uri))}}"
|
||||||
#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}}
|
#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
|
{{?(it.product.ui || (it.product.state && it.product.state.dspCustom))}}
|
||||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
static uint32_t index_to_param[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
|
static uint32_t index_to_param[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
|
||||||
{{~it.tibia.lv2.ports.filter(x => x.type == "control").map((e, i) => ({ i: i, pi: e.paramIndex })).sort((a, b) => a.pi - b.pi) :p}}{{=p.i + it.tibia.lv2.ports.filter(x => x.type != "control").length}}, {{~}}
|
{{~it.tibia.lv2.ports.filter(x => x.type == "control").map((e, i) => ({ i: i, pi: e.paramIndex })).sort((a, b) => a.pi - b.pi) :p}}{{=p.i + it.tibia.lv2.ports.filter(x => x.type != "control").length}}, {{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define DATA_STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -31,18 +31,23 @@
|
|||||||
#endif
|
#endif
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
#include "lv2/core/lv2.h"
|
#include <lv2/core/lv2.h>
|
||||||
#include "lv2/core/lv2_util.h"
|
#include <lv2/core/lv2_util.h>
|
||||||
#include "lv2/log/log.h"
|
#include <lv2/log/log.h>
|
||||||
#include "lv2/log/logger.h"
|
#include <lv2/log/logger.h>
|
||||||
#include "lv2/urid/urid.h"
|
#include <lv2/urid/urid.h>
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if (DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0) || defined(DATA_STATE_DSP_CUSTOM)
|
||||||
# include "lv2/atom/util.h"
|
# include <lv2/atom/atom.h>
|
||||||
# include "lv2/atom/atom.h"
|
# if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
# include "lv2/midi/midi.h"
|
# include <lv2/atom/util.h>
|
||||||
|
# include <lv2/midi/midi.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef DATA_UI
|
#ifdef DATA_UI
|
||||||
# include "lv2/ui/ui.h"
|
# include <lv2/ui/ui.h>
|
||||||
|
#endif
|
||||||
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
# include <lv2/state/state.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -52,10 +57,29 @@
|
|||||||
# include <pmmintrin.h>
|
# include <pmmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
#if (DATA_PRODUCT_CONTROL_INPUTS_N > 0) && defined(DATA_STATE_DSP_CUSTOM)
|
||||||
# include "fatica.h"
|
# ifdef __cplusplus
|
||||||
|
# include <atomic>
|
||||||
|
# else
|
||||||
|
# include <stdatomic.h>
|
||||||
|
# endif
|
||||||
|
# if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
# include <processthreadsapi.h>
|
||||||
|
# define yield SwitchToThread
|
||||||
|
# else
|
||||||
|
# include <sched.h>
|
||||||
|
# define yield sched_yield
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CONTROL_INPUT_INDEX_OFFSET ( \
|
||||||
|
DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N \
|
||||||
|
+ DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N \
|
||||||
|
+ DATA_PRODUCT_MIDI_INPUTS_N \
|
||||||
|
+ DATA_PRODUCT_MIDI_OUTPUTS_N )
|
||||||
|
#define CONTROL_OUTPUT_INDEX_OFFSET (CONTROL_INPUT_INDEX_OFFSET + DATA_PRODUCT_CONTROL_INPUTS_N)
|
||||||
|
|
||||||
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
static inline float clampf(float x, float m, float M) {
|
static inline float clampf(float x, float m, float M) {
|
||||||
return x < m ? m : (x > M ? M : x);
|
return x < m ? m : (x > M ? M : x);
|
||||||
}
|
}
|
||||||
@ -69,37 +93,52 @@ static float adjust_param(size_t index, float value) {
|
|||||||
value = (int32_t)(value + (value >= 0.f ? 0.5f : -0.5f));
|
value = (int32_t)(value + (value >= 0.f ? 0.5f : -0.5f));
|
||||||
return clampf(value, param_data[index].min, param_data[index].max);
|
return clampf(value, param_data[index].min, param_data[index].max);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plugin p;
|
plugin p;
|
||||||
|
float sample_rate;
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||||
float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
const LV2_Atom_Sequence *x_midi[DATA_PRODUCT_MIDI_INPUTS_N];
|
const LV2_Atom_Sequence * x_midi[DATA_PRODUCT_MIDI_INPUTS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
LV2_Atom_Sequence *y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N];
|
LV2_Atom_Sequence * y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N];
|
||||||
#endif
|
#endif
|
||||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||||
float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N];
|
float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||||
|
# ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
float params_sync[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||||
|
# ifdef __cplusplus
|
||||||
|
std::atomic_flag sync_lock_flag;
|
||||||
|
# else
|
||||||
|
atomic_flag sync_lock_flag;
|
||||||
|
# endif
|
||||||
|
char synced;
|
||||||
|
char loaded;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
void *mem;
|
void * mem;
|
||||||
char *bundle_path;
|
char * bundle_path;
|
||||||
LV2_Log_Logger logger;
|
LV2_Log_Logger logger;
|
||||||
LV2_URID_Map *map;
|
LV2_URID_Map * map;
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
LV2_URID uri_midi_MidiEvent;
|
LV2_URID uri_midi_MidiEvent;
|
||||||
#endif
|
#endif
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
float cpu_meter;
|
LV2_URID uri_atom_Chunk;
|
||||||
float sample_rate;
|
LV2_URID uri_state_data;
|
||||||
|
plugin_state_callbacks state_cbs;
|
||||||
|
LV2_State_Store_Function state_store;
|
||||||
|
LV2_State_Handle state_handle;
|
||||||
#endif
|
#endif
|
||||||
} plugin_instance;
|
} plugin_instance;
|
||||||
|
|
||||||
@ -108,11 +147,53 @@ static const char * get_bundle_path_cb(void *handle) {
|
|||||||
return instance->bundle_path;
|
return instance->bundle_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
static void state_lock_cb(void *handle) {
|
||||||
|
plugin_instance * i = (plugin_instance *)handle;
|
||||||
|
# ifdef __cplusplus
|
||||||
|
while (i->sync_lock_flag.test_and_set())
|
||||||
|
# else
|
||||||
|
while (atomic_flag_test_and_set(&i->sync_lock_flag))
|
||||||
|
# endif
|
||||||
|
yield();
|
||||||
|
i->synced = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void state_unlock_cb(void *handle) {
|
||||||
|
plugin_instance * i = (plugin_instance *)handle;
|
||||||
|
# ifdef __cplusplus
|
||||||
|
i->sync_lock_flag.clear();
|
||||||
|
# else
|
||||||
|
atomic_flag_clear(&i->sync_lock_flag);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int state_write_cb(void *handle, const char *data, size_t length) {
|
||||||
|
plugin_instance * i = (plugin_instance *)handle;
|
||||||
|
return i->state_store(i->state_handle, i->uri_state_data, data, length, i->uri_atom_Chunk, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
|
static void state_set_parameter_cb(void *handle, size_t index, float value) {
|
||||||
|
plugin_instance * i = (plugin_instance *)handle;
|
||||||
|
size_t idx = index_to_param[index] - CONTROL_INPUT_INDEX_OFFSET;
|
||||||
|
value = adjust_param(idx, value);
|
||||||
|
i->params_sync[idx] = value;
|
||||||
|
i->loaded = 1;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double sample_rate, const char * bundle_path, const LV2_Feature * const * features) {
|
static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double sample_rate, const char * bundle_path, const LV2_Feature * const * features) {
|
||||||
(void)descriptor;
|
(void)descriptor;
|
||||||
(void)bundle_path;
|
(void)bundle_path;
|
||||||
|
|
||||||
plugin_instance *instance = malloc(sizeof(plugin_instance));
|
// make C++ compilers happy
|
||||||
|
const char * missing;
|
||||||
|
plugin_callbacks cbs;
|
||||||
|
size_t req;
|
||||||
|
|
||||||
|
plugin_instance *instance = (plugin_instance *)malloc(sizeof(plugin_instance));
|
||||||
if (instance == NULL)
|
if (instance == NULL)
|
||||||
goto err_instance;
|
goto err_instance;
|
||||||
|
|
||||||
@ -121,7 +202,7 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
|||||||
goto err_bundle_path;
|
goto err_bundle_path;
|
||||||
|
|
||||||
// from https://lv2plug.in/book
|
// from https://lv2plug.in/book
|
||||||
const char* missing = lv2_features_query(features,
|
missing = lv2_features_query(features,
|
||||||
LV2_LOG__log, &instance->logger.log, false,
|
LV2_LOG__log, &instance->logger.log, false,
|
||||||
LV2_URID__map, &instance->map, true,
|
LV2_URID__map, &instance->map, true,
|
||||||
NULL);
|
NULL);
|
||||||
@ -129,23 +210,31 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
|||||||
lv2_log_logger_set_map(&instance->logger, instance->map);
|
lv2_log_logger_set_map(&instance->logger, instance->map);
|
||||||
if (missing) {
|
if (missing) {
|
||||||
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
|
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
|
||||||
|
#ifdef DATA_PRODUCT_MIDI_REQUIRED
|
||||||
goto err_urid;
|
goto err_urid;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
|
if (instance->map)
|
||||||
instance->uri_midi_MidiEvent = instance->map->map(instance->map->handle, LV2_MIDI__MidiEvent);
|
instance->uri_midi_MidiEvent = instance->map->map(instance->map->handle, LV2_MIDI__MidiEvent);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
if (instance->map) {
|
||||||
|
instance->uri_atom_Chunk = instance->map->map(instance->map->handle, LV2_ATOM__Chunk);
|
||||||
|
instance->uri_state_data = instance->map->map(instance->map->handle, DATA_LV2_URI "#state_data");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
cbs.handle = (void *)instance;
|
||||||
/* .handle = */ (void *)instance,
|
cbs.format = "lv2";
|
||||||
/* .format = */ "lv2",
|
cbs.get_bindir = get_bundle_path_cb;
|
||||||
/* .get_bindir = */ get_bundle_path_cb,
|
cbs.get_datadir = get_bundle_path_cb;
|
||||||
/* .get_datadir = */ get_bundle_path_cb
|
|
||||||
};
|
|
||||||
plugin_init(&instance->p, &cbs);
|
plugin_init(&instance->p, &cbs);
|
||||||
|
|
||||||
plugin_set_sample_rate(&instance->p, sample_rate);
|
instance->sample_rate = (float)sample_rate;
|
||||||
size_t req = plugin_mem_req(&instance->p);
|
plugin_set_sample_rate(&instance->p, instance->sample_rate);
|
||||||
|
req = plugin_mem_req(&instance->p);
|
||||||
if (req != 0) {
|
if (req != 0) {
|
||||||
instance->mem = malloc(req);
|
instance->mem = malloc(req);
|
||||||
if (instance->mem == NULL) {
|
if (instance->mem == NULL) {
|
||||||
@ -176,16 +265,14 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
|||||||
for (uint32_t i = 0; i < DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N; i++)
|
for (uint32_t i = 0; i < DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N; i++)
|
||||||
instance->c[i] = NULL;
|
instance->c[i] = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
instance->cpu_meter = 0.f;
|
|
||||||
instance->sample_rate = sample_rate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
|
|
||||||
err_mem:
|
err_mem:
|
||||||
plugin_fini(&instance->p);
|
plugin_fini(&instance->p);
|
||||||
|
#ifdef DATA_PRODUCT_MIDI_REQUIRED
|
||||||
err_urid:
|
err_urid:
|
||||||
|
#endif
|
||||||
free(instance->bundle_path);
|
free(instance->bundle_path);
|
||||||
err_bundle_path:
|
err_bundle_path:
|
||||||
free(instance);
|
free(instance);
|
||||||
@ -197,34 +284,34 @@ static void connect_port(LV2_Handle instance, uint32_t port, void * data_locatio
|
|||||||
plugin_instance * i = (plugin_instance *)instance;
|
plugin_instance * i = (plugin_instance *)instance;
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
if (port < DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N) {
|
if (port < DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N) {
|
||||||
i->x[port] = data_location;
|
i->x[port] = (const float *)data_location;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
port -= DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N;
|
port -= DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N;
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||||
if (port < DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N) {
|
if (port < DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N) {
|
||||||
i->y[port] = data_location;
|
i->y[port] = (float *)data_location;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N;
|
port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N;
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
if (port < DATA_PRODUCT_MIDI_INPUTS_N) {
|
if (port < DATA_PRODUCT_MIDI_INPUTS_N) {
|
||||||
i->x_midi[port] = data_location;
|
i->x_midi[port] = (const LV2_Atom_Sequence *)data_location;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
port -= DATA_PRODUCT_MIDI_INPUTS_N;
|
port -= DATA_PRODUCT_MIDI_INPUTS_N;
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
if (port < DATA_PRODUCT_MIDI_OUTPUTS_N) {
|
if (port < DATA_PRODUCT_MIDI_OUTPUTS_N) {
|
||||||
i->y_midi[port] = data_location;
|
i->y_midi[port] = (LV2_Atom_Sequence *)data_location;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
port -= DATA_PRODUCT_MIDI_OUTPUTS_N;
|
port -= DATA_PRODUCT_MIDI_OUTPUTS_N;
|
||||||
#endif
|
#endif
|
||||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||||
i->c[port] = data_location;
|
i->c[port] = (float *)data_location;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +322,19 @@ static void activate(LV2_Handle instance) {
|
|||||||
i->params[j] = i->c[j] != NULL ? *i->c[j] : param_data[j].def;
|
i->params[j] = i->c[j] != NULL ? *i->c[j] : param_data[j].def;
|
||||||
plugin_set_parameter(&i->p, param_data[j].index, i->params[j]);
|
plugin_set_parameter(&i->p, param_data[j].index, i->params[j]);
|
||||||
}
|
}
|
||||||
|
# ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++)
|
||||||
|
i->params_sync[j] = i->params[j];
|
||||||
|
# ifdef __cplusplus
|
||||||
|
i->sync_lock_flag.clear();
|
||||||
|
# else
|
||||||
|
// why is this not correct?
|
||||||
|
// i->sync_lock_flag = ATOMIC_FLAG_INIT;
|
||||||
|
atomic_flag_clear(&i->sync_lock_flag);
|
||||||
|
# endif
|
||||||
|
i->synced = 1;
|
||||||
|
i->loaded = 0;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
plugin_reset(&i->p);
|
plugin_reset(&i->p);
|
||||||
}
|
}
|
||||||
@ -242,10 +342,6 @@ static void activate(LV2_Handle instance) {
|
|||||||
static void run(LV2_Handle instance, uint32_t sample_count) {
|
static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||||
plugin_instance * i = (plugin_instance *)instance;
|
plugin_instance * i = (plugin_instance *)instance;
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
const unsigned long long processTimeStart = fatica_time_process();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
uint64_t fpcr;
|
uint64_t fpcr;
|
||||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||||
@ -259,19 +355,62 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
|
# ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
# ifdef __cplusplus
|
||||||
|
_Bool locked = !i->sync_lock_flag.test_and_set();
|
||||||
|
# else
|
||||||
|
_Bool locked = !atomic_flag_test_and_set(&i->sync_lock_flag);
|
||||||
|
# endif
|
||||||
|
if (locked) {
|
||||||
|
if (!i->synced) {
|
||||||
|
if (i->loaded) {
|
||||||
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
||||||
|
i->params[j] = i->params_sync[j];
|
||||||
|
plugin_set_parameter(&i->p, param_data[j].index, i->params[j]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++)
|
||||||
|
if (i->params[j] != i->params_sync[j]) {
|
||||||
|
i->params_sync[j] = i->params[j];
|
||||||
|
plugin_set_parameter(&i->p, param_data[j].index, i->params[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i->synced = 1;
|
||||||
|
i->loaded = 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
||||||
if (i->c[j] == NULL)
|
if (i->c[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
float v = adjust_param(j, *i->c[j]);
|
float v = adjust_param(j, *i->c[j]);
|
||||||
if (v != i->params[j]) {
|
if (v != i->params[j]) {
|
||||||
i->params[j] = v;
|
i->params[j] = v;
|
||||||
|
# ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
if (locked) {
|
||||||
|
i->params_sync[j] = i->params[j];
|
||||||
|
# endif
|
||||||
plugin_set_parameter(&i->p, param_data[j].index, v);
|
plugin_set_parameter(&i->p, param_data[j].index, v);
|
||||||
|
# ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
}
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
if (locked)
|
||||||
|
# ifdef __cplusplus
|
||||||
|
i->sync_lock_flag.clear();
|
||||||
|
# else
|
||||||
|
atomic_flag_clear(&i->sync_lock_flag);
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// from https://lv2plug.in/book
|
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
|
// from https://lv2plug.in/book
|
||||||
|
if (i->map)
|
||||||
for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) {
|
for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) {
|
||||||
if (i->x_midi[j] == NULL)
|
if (i->x_midi[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
@ -300,16 +439,9 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
#if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) {
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) {
|
||||||
uint32_t k = param_out_index[j];
|
uint32_t k = param_out_index[j];
|
||||||
if (i->c[k] != NULL) {
|
if (i->c[k] != NULL)
|
||||||
# ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
if (k == PARAM_OUT_CPU_INDEX) {
|
|
||||||
*i->c[k] = i->cpu_meter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
*i->c[k] = plugin_get_parameter(&i->p, k);
|
*i->c[k] = plugin_get_parameter(&i->p, k);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
(void)plugin_get_parameter;
|
(void)plugin_get_parameter;
|
||||||
#endif
|
#endif
|
||||||
@ -320,12 +452,6 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PARAM_OUT_CPU_INDEX
|
|
||||||
const unsigned long long processTimeEnd = fatica_time_process();
|
|
||||||
fatica_cpu_meter(&i->cpu_meter, processTimeStart, processTimeEnd, sample_count, i->sample_rate);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(LV2_Handle instance) {
|
static void cleanup(LV2_Handle instance) {
|
||||||
@ -337,6 +463,66 @@ static void cleanup(LV2_Handle instance) {
|
|||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature * const * features) {
|
||||||
|
(void)flags;
|
||||||
|
(void)features;
|
||||||
|
|
||||||
|
plugin_instance * i = (plugin_instance *)instance;
|
||||||
|
if (!i->map) {
|
||||||
|
lv2_log_error(&i->logger, "Host is trying to store state but didn't provide URID map\n");
|
||||||
|
return LV2_STATE_ERR_UNKNOWN; // evidently buggy host, we don't have an errcode for it, LV2_STATE_ERR_NO_FEATURE has a different meaning
|
||||||
|
}
|
||||||
|
i->state_store = store;
|
||||||
|
i->state_handle = handle;
|
||||||
|
plugin_state_callbacks cbs = {
|
||||||
|
/* .handle = */ (void *)i,
|
||||||
|
/* .lock = */ state_lock_cb,
|
||||||
|
/* .unlock = */ state_unlock_cb,
|
||||||
|
/* .write = */ state_write_cb,
|
||||||
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
|
/* .set_parameter = */ NULL
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
return plugin_state_save(&i->p, &cbs, i->sample_rate) == 0 ? LV2_STATE_SUCCESS : LV2_STATE_ERR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature * const * features) {
|
||||||
|
(void)flags;
|
||||||
|
(void)features;
|
||||||
|
|
||||||
|
plugin_instance * i = (plugin_instance *)instance;
|
||||||
|
if (!i->map) {
|
||||||
|
lv2_log_error(&i->logger, "Host is trying to restore state but didn't provide URID map\n");
|
||||||
|
return LV2_STATE_ERR_UNKNOWN; // evidently buggy host, we don't have an errcode for it, LV2_STATE_ERR_NO_FEATURE has a different meaning
|
||||||
|
}
|
||||||
|
size_t length;
|
||||||
|
uint32_t type, xflags; // jalv 1.6.6 crashes using NULL as per spec, so we have these two
|
||||||
|
const char * data = (const char *)retrieve(handle, i->uri_state_data, &length, &type, &xflags);
|
||||||
|
if (data == NULL) {
|
||||||
|
lv2_log_error(&i->logger, "Cannot restore state since property <%s> could not be retrieved\n", DATA_LV2_URI "#state_data");
|
||||||
|
return LV2_STATE_ERR_NO_PROPERTY;
|
||||||
|
}
|
||||||
|
plugin_state_callbacks cbs = {
|
||||||
|
/* .handle = */ (void *)i,
|
||||||
|
/* .lock = */ state_lock_cb,
|
||||||
|
/* .unlock = */ state_unlock_cb,
|
||||||
|
/* .write = */ NULL,
|
||||||
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
|
/* .set_parameter = */ state_set_parameter_cb
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
return plugin_state_load(&cbs, i->sample_rate, data, length) == 0 ? LV2_STATE_SUCCESS : LV2_STATE_ERR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const void * extension_data(const char * uri) {
|
||||||
|
static const LV2_State_Interface state = { state_save, state_restore };
|
||||||
|
if (!strcmp(uri, LV2_STATE__interface))
|
||||||
|
return &state;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const LV2_Descriptor descriptor = {
|
static const LV2_Descriptor descriptor = {
|
||||||
/* .URI = */ DATA_LV2_URI,
|
/* .URI = */ DATA_LV2_URI,
|
||||||
/* .instantiate = */ instantiate,
|
/* .instantiate = */ instantiate,
|
||||||
@ -345,7 +531,11 @@ static const LV2_Descriptor descriptor = {
|
|||||||
/* .run = */ run,
|
/* .run = */ run,
|
||||||
/* .deactivate = */ NULL,
|
/* .deactivate = */ NULL,
|
||||||
/* .cleanup = */ cleanup,
|
/* .cleanup = */ cleanup,
|
||||||
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
/* .extension_data = */ extension_data
|
||||||
|
#else
|
||||||
/* .extension_data = */ NULL
|
/* .extension_data = */ NULL
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
||||||
@ -354,8 +544,8 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
|||||||
|
|
||||||
#ifdef DATA_UI
|
#ifdef DATA_UI
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plugin_ui *ui;
|
plugin_ui * ui;
|
||||||
char *bundle_path;
|
char * bundle_path;
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
LV2UI_Write_Function write;
|
LV2UI_Write_Function write;
|
||||||
LV2UI_Controller controller;
|
LV2UI_Controller controller;
|
||||||
@ -364,24 +554,19 @@ typedef struct {
|
|||||||
# endif
|
# endif
|
||||||
} ui_instance;
|
} ui_instance;
|
||||||
|
|
||||||
# define CONTROL_INPUT_INDEX_OFFSET ( \
|
|
||||||
DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N \
|
|
||||||
+ DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N \
|
|
||||||
+ DATA_PRODUCT_MIDI_INPUTS_N \
|
|
||||||
+ DATA_PRODUCT_MIDI_OUTPUTS_N )
|
|
||||||
# define CONTROL_OUTPUT_INDEX_OFFSET (CONTROL_INPUT_INDEX_OFFSET + DATA_PRODUCT_CONTROL_INPUTS_N)
|
|
||||||
|
|
||||||
static const char * ui_get_bundle_path_cb(void *handle) {
|
static const char * ui_get_bundle_path_cb(void *handle) {
|
||||||
ui_instance *instance = (ui_instance *)handle;
|
ui_instance *instance = (ui_instance *)handle;
|
||||||
return instance->bundle_path;
|
return instance->bundle_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
static void ui_set_parameter_begin_cb(void *handle, size_t index) {
|
static void ui_set_parameter_begin_cb(void *handle, size_t index, float value) {
|
||||||
ui_instance *instance = (ui_instance *)handle;
|
ui_instance *instance = (ui_instance *)handle;
|
||||||
if (instance->has_touch) {
|
if (instance->has_touch) {
|
||||||
index = index_to_param[index];
|
index = index_to_param[index];
|
||||||
instance->touch.touch(instance->touch.handle, index, true);
|
instance->touch.touch(instance->touch.handle, index, true);
|
||||||
|
value = adjust_param(index - CONTROL_INPUT_INDEX_OFFSET, value);
|
||||||
|
instance->write(instance->controller, index, sizeof(float), 0, &value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,10 +577,12 @@ static void ui_set_parameter_cb(void *handle, size_t index, float value) {
|
|||||||
instance->write(instance->controller, index, sizeof(float), 0, &value);
|
instance->write(instance->controller, index, sizeof(float), 0, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ui_set_parameter_end_cb(void *handle, size_t index) {
|
static void ui_set_parameter_end_cb(void *handle, size_t index, float value) {
|
||||||
ui_instance *instance = (ui_instance *)handle;
|
ui_instance *instance = (ui_instance *)handle;
|
||||||
if (instance->has_touch) {
|
if (instance->has_touch) {
|
||||||
index = index_to_param[index];
|
index = index_to_param[index];
|
||||||
|
value = adjust_param(index - CONTROL_INPUT_INDEX_OFFSET, value);
|
||||||
|
instance->write(instance->controller, index, sizeof(float), 0, &value);
|
||||||
instance->touch.touch(instance->touch.handle, index, false);
|
instance->touch.touch(instance->touch.handle, index, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +592,12 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
|
|||||||
(void)descriptor;
|
(void)descriptor;
|
||||||
(void)plugin_uri;
|
(void)plugin_uri;
|
||||||
|
|
||||||
ui_instance *instance = malloc(sizeof(ui_instance));
|
// make C++ compilers happy
|
||||||
|
char has_parent;
|
||||||
|
void *parent;
|
||||||
|
plugin_ui_callbacks cbs;
|
||||||
|
|
||||||
|
ui_instance *instance = (ui_instance *)malloc(sizeof(ui_instance));
|
||||||
if (instance == NULL)
|
if (instance == NULL)
|
||||||
goto err_instance;
|
goto err_instance;
|
||||||
|
|
||||||
@ -413,35 +605,33 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
|
|||||||
if (instance->bundle_path == NULL)
|
if (instance->bundle_path == NULL)
|
||||||
goto err_bundle_path;
|
goto err_bundle_path;
|
||||||
|
|
||||||
char has_parent = 0;
|
has_parent = 0;
|
||||||
void *parent = NULL;
|
parent = NULL;
|
||||||
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
instance->has_touch = 0;
|
instance->has_touch = 0;
|
||||||
|
# endif
|
||||||
for (size_t i = 0; features[i] != NULL; i++) {
|
for (size_t i = 0; features[i] != NULL; i++) {
|
||||||
if (!strcmp(features[i]->URI, LV2_UI__parent)) {
|
if (!strcmp(features[i]->URI, LV2_UI__parent)) {
|
||||||
has_parent = 1;
|
has_parent = 1;
|
||||||
parent = features[i]->data;
|
parent = features[i]->data;
|
||||||
}
|
}
|
||||||
if (!strcmp(features[i]->URI, LV2_UI__touch)) {
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
|
else if (!strcmp(features[i]->URI, LV2_UI__touch)) {
|
||||||
instance->has_touch = 1;
|
instance->has_touch = 1;
|
||||||
instance->touch = *((LV2UI_Touch *)features[i]->data);
|
instance->touch = *((LV2UI_Touch *)features[i]->data);
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_ui_callbacks cbs = {
|
cbs.handle = (void *)instance;
|
||||||
/* .handle = */ (void *)instance,
|
cbs.format = "lv2";
|
||||||
/* .format = */ "lv2",
|
cbs.get_bindir = ui_get_bundle_path_cb;
|
||||||
/* .get_bindir = */ ui_get_bundle_path_cb,
|
cbs.get_datadir = ui_get_bundle_path_cb;
|
||||||
/* .get_datadir = */ ui_get_bundle_path_cb,
|
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
/* .set_parameter_begin = */ ui_set_parameter_begin_cb,
|
cbs.set_parameter_begin = ui_set_parameter_begin_cb;
|
||||||
/* .set_parameter = */ ui_set_parameter_cb,
|
cbs.set_parameter = ui_set_parameter_cb;
|
||||||
/* .set_parameter_end = */ ui_set_parameter_end_cb
|
cbs.set_parameter_end = ui_set_parameter_end_cb;
|
||||||
# else
|
|
||||||
/* .set_parameter_begin = */ NULL,
|
|
||||||
/* .set_parameter = */ NULL,
|
|
||||||
/* .set_parameter_end = */ NULL
|
|
||||||
# endif
|
# endif
|
||||||
};
|
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
instance->write = write_function;
|
instance->write = write_function;
|
||||||
instance->controller = controller;
|
instance->controller = controller;
|
||||||
@ -478,11 +668,18 @@ static void ui_port_event(LV2UI_Handle handle, uint32_t port_index, uint32_t buf
|
|||||||
(void)format;
|
(void)format;
|
||||||
|
|
||||||
ui_instance *instance = (ui_instance *)handle;
|
ui_instance *instance = (ui_instance *)handle;
|
||||||
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
if (port_index < CONTROL_OUTPUT_INDEX_OFFSET) {
|
if (port_index < CONTROL_OUTPUT_INDEX_OFFSET) {
|
||||||
size_t index = port_index - CONTROL_INPUT_INDEX_OFFSET;
|
size_t index = port_index - CONTROL_INPUT_INDEX_OFFSET;
|
||||||
plugin_ui_set_parameter(instance->ui, param_data[index].index, adjust_param(index, *((float *)buffer)));
|
plugin_ui_set_parameter(instance->ui, param_data[index].index, adjust_param(index, *((float *)buffer)));
|
||||||
} else
|
}
|
||||||
|
# endif
|
||||||
|
# if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||||
|
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
|
else
|
||||||
|
# endif
|
||||||
plugin_ui_set_parameter(instance->ui, param_out_index[port_index - CONTROL_OUTPUT_INDEX_OFFSET], *((float *)buffer));
|
plugin_ui_set_parameter(instance->ui, param_out_index[port_index - CONTROL_OUTPUT_INDEX_OFFSET], *((float *)buffer));
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -34,6 +34,7 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
||||||
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
||||||
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
|
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
|
||||||
|
{ id: "state", uri: "http://lv2plug.in/ns/extensions/state#" },
|
||||||
{ id: "ui", uri: "http://lv2plug.in/ns/extensions/ui#" },
|
{ id: "ui", uri: "http://lv2plug.in/ns/extensions/ui#" },
|
||||||
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
|
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
|
||||||
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
|
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
|
||||||
@ -67,7 +68,12 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
ports: [],
|
ports: [],
|
||||||
|
|
||||||
ttlURI: function (uri) {
|
ttlURI: function (uri) {
|
||||||
return uri.charAt(0) == "@" ? uri.substring(1) : "<" + uri + ">";
|
if (uri.charAt(0) == "@") {
|
||||||
|
if (uri.indexOf("#") == -1)
|
||||||
|
return uri.substring(1);
|
||||||
|
uri = data.tibia.lv2.expandURI(uri);
|
||||||
|
}
|
||||||
|
return "<" + uri + ">";
|
||||||
},
|
},
|
||||||
|
|
||||||
expandURI: function (uri) {
|
expandURI: function (uri) {
|
||||||
@ -122,5 +128,4 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
api.generateFileFromTemplateFile(`data${sep}manifest.ttl.in`, `data${sep}manifest.ttl.in`, data);
|
api.generateFileFromTemplateFile(`data${sep}manifest.ttl.in`, `data${sep}manifest.ttl.in`, data);
|
||||||
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,74 +18,85 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
TEMPLATE := vst3
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
|
COMMON_DIR ?= .
|
||||||
|
DATA_DIR ?= .
|
||||||
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
|
BUNDLE_DIR := $(BUNDLE_NAME).vst3
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
DLL_SUFFIX := .vst3
|
DLL_SUFFIX := .vst3
|
||||||
PLATFORM := x86_64-win
|
VST3DIR := $(subst \,/,$(COMMONPROGRAMFILES))/VST3
|
||||||
VST3DIR := $(shell echo '$(COMMONPROGRAMFILES)' | sed 's:\\:/:g')/VST3
|
VST3DIR_USER := $(subst \,/,$(LOCALAPPDATA))/Programs/Common/VST3
|
||||||
VST3DIR_USER := $(shell echo '$(LOCALAPPDATA)' | sed 's:\\:/:g')/Programs/Common/VST3
|
|
||||||
CC := gcc
|
CC := gcc
|
||||||
CXX := g++
|
CXX := g++
|
||||||
|
MACHINE := $(shell $(CC) -dumpmachine | sed 's:-.*::g')
|
||||||
|
ifeq ($(MACHINE), x86_64)
|
||||||
|
VST3_PLATFORM := x86_64-win
|
||||||
|
endif
|
||||||
|
ifeq ($(MACHINE), aarch64)
|
||||||
|
VST3_PLATFORM := arm64-win
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
DLL_SUFFIX :=
|
DLL_SUFFIX :=
|
||||||
PLATFORM := MacOS
|
|
||||||
VST3DIR := /Library/Audio/Plug-Ins/VST3
|
VST3DIR := /Library/Audio/Plug-Ins/VST3
|
||||||
VST3DIR_USER := $(HOME)/Library/Audio/Plug-Ins/VST3
|
VST3DIR_USER := $(HOME)/Library/Audio/Plug-Ins/VST3
|
||||||
CC := clang
|
CC := clang
|
||||||
CXX := clang++
|
CXX := clang++
|
||||||
|
VST3_PLATFORM := MacOS
|
||||||
else
|
else
|
||||||
DLL_SUFFIX := .so
|
DLL_SUFFIX := .so
|
||||||
PLATFORM := $(shell uname -m)-linux
|
|
||||||
VST3DIR := /usr/local/lib/vst3
|
VST3DIR := /usr/local/lib/vst3
|
||||||
VST3DIR_USER := $(HOME)/.vst3
|
VST3DIR_USER := $(HOME)/.vst3
|
||||||
CC := gcc
|
CC := gcc
|
||||||
CXX := g++
|
CXX := g++
|
||||||
|
VST3_PLATFORM := $(shell uname -m)-linux
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
DLL_DIR := Contents/$(VST3_PLATFORM)
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
BUILD_BIN_DIR := build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
BUILD_DATA_DIR := build/$(BUNDLE_DIR)/Contents/Resources
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
|
||||||
|
-include $(MKINC_DIR)/vars-pre.mk
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -fPIC $(CFLAGS) $(CFLAGS_EXTRA)
|
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
LDFLAGS :=
|
LDFLAGS :=
|
||||||
LDFLAGS_ALL := -shared -lm $(LDFLAGS) $(LDFLAGS_EXTRA)
|
LDFLAGS_ALL := -shared -lm $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS)
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -fPIC $(CXXFLAGS) $(CXXFLAGS_EXTRA)
|
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
||||||
ifeq ($(HAS_UI), yes)
|
ifeq ($(HAS_UI), yes)
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,-framework,Foundation -Wl,-framework,Cocoa -Wl,-framework,Corevideo
|
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,-framework,Foundation -Wl,-framework,Cocoa -Wl,-framework,Corevideo
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Linux)
|
ifeq ($(UNAME_S), Linux)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -D_GNU_SOURCE
|
CFLAGS_ALL := $(CFLAGS_ALL) -D_GNU_SOURCE
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -ldl
|
|
||||||
ifeq ($(HAS_UI), yes)
|
ifeq ($(HAS_UI), yes)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) $(shell pkg-config --cflags x11)
|
CFLAGS_ALL := $(CFLAGS_ALL) $(shell pkg-config --cflags x11)
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) $(shell pkg-config --libs x11)
|
LDFLAGS_ALL := $(LDFLAGS_ALL) $(shell pkg-config --libs x11)
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) $(shell pkg-config --cflags x11)
|
CXXFLAGS_ALL := $(CXXFLAGS_ALL) $(shell pkg-config --cflags x11)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
BUNDLE_DIR := $(BUNDLE_NAME).vst3
|
|
||||||
|
|
||||||
DLL_DIR := Contents/$(PLATFORM)
|
|
||||||
DLL_FILE := $(DLL_DIR)/$(BUNDLE_NAME)$(DLL_SUFFIX)
|
DLL_FILE := $(DLL_DIR)/$(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||||
|
|
||||||
BUNDLE_DATA_PATH := build/$(BUNDLE_DIR)/Contents/Resources
|
|
||||||
BUNDLE_BIN_PATH := build/$(BUNDLE_DIR)/$(DLL_DIR)
|
|
||||||
|
|
||||||
C_SRCS := $(COMMON_DIR)/src/vst3.c $(C_SRCS_EXTRA)
|
C_SRCS := $(COMMON_DIR)/src/vst3.c $(C_SRCS_EXTRA)
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
|
|
||||||
@ -95,13 +106,19 @@ M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
|||||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
ALL := build/$(BUNDLE_DIR)/$(DLL_FILE)
|
DIRS := build build/obj build/$(BUNDLE_DIR) build/$(BUNDLE_DIR)/Contents build/$(BUNDLE_DIR)/Contents/Resources build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||||
|
|
||||||
|
ALL := build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
ALL := $(ALL) build/$(BUNDLE_DIR)/Contents/Info.plist build/$(BUNDLE_DIR)/Contents/PkgInfo
|
ALL := $(ALL) build/$(BUNDLE_DIR)/Contents/Info.plist build/$(BUNDLE_DIR)/Contents/PkgInfo
|
||||||
endif
|
endif
|
||||||
|
|
||||||
-include $(COMMON_DIR)/vars-extra.mk
|
STRIP_ALL := build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||||
|
STRIP_PREREQS := $(STRIP_ALL)
|
||||||
|
|
||||||
|
PHONY := all clean strip install install-user
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
@ -121,46 +138,46 @@ build/$(BUNDLE_DIR)/Contents/%: $(COMMON_DIR)/data/% | build/$(BUNDLE_DIR)/Conte
|
|||||||
cp $^ $@
|
cp $^ $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build/$(BUNDLE_DIR)/Contents build/$(BUNDLE_DIR)/$(DLL_DIR) build/obj:
|
$(DIRS):
|
||||||
mkdir -p $@
|
|
||||||
|
|
||||||
${BUNDLE_DATA_PATH}:
|
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
|
strip: $(STRIP_PREREQS)
|
||||||
|
strip -Sx build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
d=`echo $$d | sed 's:^build/::'` ; \
|
||||||
echo mkdir -m 0755 -p "$(VST3DIR)/$$d"; \
|
echo mkdir -m 0755 -p "$(VST3DIR)/$$d"; \
|
||||||
mkdir -m 0755 -p "$(VST3DIR)/$$d"; \
|
mkdir -m 0755 -p "$(VST3DIR)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||||
d=`echo $$f | sed 's:^build/::'` ; \
|
d=`echo $$f | sed 's:^build/::'` ; \
|
||||||
d=`dirname $$d`; \
|
d=`dirname $$d`; \
|
||||||
echo install -m $$m $$f "$(VST3DIR)/$$d"; \
|
echo install -m $$m $$f "$(VST3DIR)/$$d"; \
|
||||||
install -m $$m $$f "$(VST3DIR)/$$d"; \
|
install -m $$m $$f "$(VST3DIR)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install-user: all
|
install-user: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
d=`echo $$d | sed 's:^build/::'` ; \
|
||||||
echo mkdir -m 0755 -p "$(VST3DIR_USER)/$$d"; \
|
echo mkdir -m 0755 -p "$(VST3DIR_USER)/$$d"; \
|
||||||
mkdir -m 0755 -p "$(VST3DIR_USER)/$$d"; \
|
mkdir -m 0755 -p "$(VST3DIR_USER)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||||
d=`echo $$f | sed 's:^build/::'` ; \
|
d=`echo $$f | sed 's:^build/::'` ; \
|
||||||
d=`dirname $$d`; \
|
d=`dirname $$d`; \
|
||||||
echo install -m $$m $$f "$(VST3DIR_USER)/$$d"; \
|
echo install -m $$m $$f "$(VST3DIR_USER)/$$d"; \
|
||||||
install -m $$m $$f "$(VST3DIR_USER)/$$d"; \
|
install -m $$m $$f "$(VST3DIR_USER)/$$d" || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-extra.mk
|
-include $(MKINC_DIR)/rules-extra.mk
|
||||||
|
|
||||||
.PHONY: all clean install install-user
|
.PHONY: $(PHONY)
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
@ -175,4 +192,6 @@ $(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$
|
|||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-secondexp-extra.mk
|
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -20,17 +20,28 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
|
{{?(it.vst3_make?.commonDir || it.make?.commonDir)}}
|
||||||
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.vst3_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.vst3_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.vst3_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.vst3_make?.cSrcs ?? ""}}
|
{{?(it.vst3_make?.apiDir || it.make?.apiDir)}}
|
||||||
M_SRCS_EXTRA := {{=it.make?.mSrcs ?? ""}} {{=it.vst3_make?.mSrcs ?? ""}}
|
API_DIR := {{=it.vst3_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.vst3_make?.cxxSrcs ?? ""}}
|
{{?}}
|
||||||
|
{{?(it.vst3_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.vst3_make?.cflags ?? ""}}
|
MKINC_DIR := {{=it.vst3_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.vst3_make?.cxxflags ?? ""}}
|
{{?}}
|
||||||
|
|
||||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.vst3_make?.ldflags ?? ""}}
|
|
||||||
|
|
||||||
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
||||||
|
HAS_PARAMETER_IN := {{=it.product.parameters.filter(x => x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
|
{{?it.make?.extra}}
|
||||||
|
{{=it.make.extra}}
|
||||||
|
{{?}}
|
||||||
|
{{?it.vst3_make?.extra}}
|
||||||
|
{{=it.vst3_make.extra}}
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -28,8 +28,8 @@
|
|||||||
static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||||
static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||||
|
|
||||||
#define DATA_VST3_SDK_VERSION "VST 3.7.9"
|
#define DATA_VST3_SDK_VERSION "VST 3.7.13"
|
||||||
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.9") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.13") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||||
|
|
||||||
static Steinberg_char16 dataVST3ControllerNameW[64] = { {{~Array.from(it.product.name + " Controller").slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
static Steinberg_char16 dataVST3ControllerNameW[64] = { {{~Array.from(it.product.name + " Controller").slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||||
|
|
||||||
@ -123,13 +123,15 @@ static uint32_t midiInIndex[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
||||||
|
#define DATA_PRODUCT_PARAMETERS_IN_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
||||||
|
#define DATA_PRODUCT_PARAMETERS_OUT_N {{=it.product.parameters.filter(x => !x.isLatency && x.direction == "output").length}}
|
||||||
|
|
||||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||||
{
|
{
|
||||||
{{?p.isBypass}}
|
{{?p.isBypass}}
|
||||||
/* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.sdbm("bypass ") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
@ -138,7 +140,7 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
/* .unitId = */ 0,
|
/* .unitId = */ 0,
|
||||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||||
{{??}}
|
{{??}}
|
||||||
/* .id = */ {{=(it.tibia.vst3.sdbm(p.name) & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.sdbm(p.id) & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
@ -151,9 +153,9 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
{{~}}
|
{{~}}
|
||||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}}
|
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}}
|
||||||
{
|
{
|
||||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.sdbm(b.id + " channel pressure") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(b.name + " Channel Pressure") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(b.name + " Channel Pressure").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
/* .stepCount = */ 0,
|
/* .stepCount = */ 0,
|
||||||
/* .defaultNormalizedValue = */ 0.0,
|
/* .defaultNormalizedValue = */ 0.0,
|
||||||
@ -161,9 +163,9 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.sdbm(b.id + " pitch bend") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(b.name + " Pitch Bend").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
/* .stepCount = */ 0,
|
/* .stepCount = */ 0,
|
||||||
/* .defaultNormalizedValue = */ 0.5,
|
/* .defaultNormalizedValue = */ 0.5,
|
||||||
@ -171,9 +173,9 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.sdbm(b.id + " mod wheel") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(b.name + " Mod Wheel").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
/* .stepCount = */ 0,
|
/* .stepCount = */ 0,
|
||||||
/* .defaultNormalizedValue = */ 0.0,
|
/* .defaultNormalizedValue = */ 0.0,
|
||||||
@ -190,7 +192,7 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
# define DATA_PARAM_INTEGER (1<<2)
|
# define DATA_PARAM_INTEGER (1<<2)
|
||||||
# define DATA_PARAM_MAP_LOG (1<<3)
|
# define DATA_PARAM_MAP_LOG (1<<3)
|
||||||
|
|
||||||
static struct {
|
typedef struct {
|
||||||
size_t index;
|
size_t index;
|
||||||
double min;
|
double min;
|
||||||
double max;
|
double max;
|
||||||
@ -198,8 +200,11 @@ static struct {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
double mapK;
|
double mapK;
|
||||||
// scalePoints?
|
// scalePoints?
|
||||||
} parameterData[DATA_PRODUCT_PARAMETERS_N] = {
|
} ParameterData;
|
||||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
|
||||||
|
# if DATA_PRODUCT_PARAMETERS_IN_N > 0
|
||||||
|
static ParameterData parameterInData[DATA_PRODUCT_PARAMETERS_IN_N] = {
|
||||||
|
{{~it.product.parameters.filter(x => x.direction == "input") :p:i}}
|
||||||
{
|
{
|
||||||
/* .index = */ {{=p.paramIndex}},
|
/* .index = */ {{=p.paramIndex}},
|
||||||
/* .min = */ {{=p.minimum.toExponential()}},
|
/* .min = */ {{=p.minimum.toExponential()}},
|
||||||
@ -210,10 +215,30 @@ static struct {
|
|||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
{{?it.product.parameters.find(x => x.direction == "output" && x.isCpumeter)}}
|
# if DATA_PRODUCT_PARAMETERS_OUT_N > 0
|
||||||
# define PARAM_OUT_CPU_INDEX {{=it.product.parameters.indexOf(it.product.parameters.find(x => x.direction == "output" && x.isCpumeter))}}
|
static ParameterData parameterOutData[DATA_PRODUCT_PARAMETERS_OUT_N] = {
|
||||||
{{?}}
|
{{~it.product.parameters.filter(x => !x.isLatency && x.direction == "output") :p:i}}
|
||||||
|
{
|
||||||
|
/* .index = */ {{=p.paramIndex}},
|
||||||
|
/* .min = */ {{=p.minimum.toExponential()}},
|
||||||
|
/* .max = */ {{=p.maximum.toExponential()}},
|
||||||
|
/* .def = */ {{=p.defaultValue.toExponential()}},
|
||||||
|
/* .flags = */ 0{{?p.toggled}} | DATA_PARAM_TOGGLED{{?}}{{?p.integer}} | DATA_PARAM_INTEGER{{?}}{{?p.map == "logarithmic"}} | DATA_PARAM_MAP_LOG{{?}},
|
||||||
|
/* .mapK = */ {{?p.map == "logarithmic"}}{{=Number(2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))).toExponential()}}{{??}}0.0{{?}}
|
||||||
|
},
|
||||||
|
{{~}}
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t parameterOutDataToInfoIndex[DATA_PRODUCT_PARAMETERS_OUT_N] = {
|
||||||
|
{{=it.product.parameters.filter(x => !x.isLatency && x.direction == "output").map(x => x.paramInfoIndex).join(", ")}}
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static size_t parameterInfoToDataIndex[DATA_PRODUCT_PARAMETERS_N] = {
|
||||||
|
{{=it.product.parameters.filter(x => !x.isLatency).map(x => x.paramDataIndex).join(", ")}}
|
||||||
|
};
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@ -227,3 +252,18 @@ static struct {
|
|||||||
#define DATA_UI
|
#define DATA_UI
|
||||||
#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}}
|
#define DATA_UI_USER_RESIZABLE {{=it.product.ui.userResizable ? 1 : 0}}
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parameter indices/ids:
|
||||||
|
*
|
||||||
|
* parameterInfo.id: hash of parameter id (+ extra sometimes), univocally identifies parameter across plugin versions (a la lv2:symbol)
|
||||||
|
* parameterGetIndexById(): returns parameterInfo array index based on id (parameterInfo.id)
|
||||||
|
* parameterInfoToDataIndex: maps parameterInfo array indices to parameter(In/Out)Data indices
|
||||||
|
* parameterOutDataToInfoIndex: maps parameterOutData indices to parameterInfo array indices
|
||||||
|
* parameter(In/Out)Data.index/p.paramIndex: Tibia parameter index, as used in plugin.h
|
||||||
|
* latency out parameter is never added to parameterInfo and parameter(In/Out)Data (specially handled)
|
||||||
|
*/
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define DATA_STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -49,23 +49,28 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
"pc": "%",
|
"pc": "%",
|
||||||
"s": "s",
|
"s": "s",
|
||||||
"semitone12TET": "semi"
|
"semitone12TET": "semi"
|
||||||
},
|
|
||||||
|
|
||||||
sdbm: function (s) {
|
|
||||||
var hash = 0;
|
|
||||||
for (var i = 0; i < s.length; i++)
|
|
||||||
hash = s.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
|
|
||||||
return hash >>> 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var i = 0; i < data.product.parameters.length; i++)
|
var inIdx = 0;
|
||||||
|
var outIdx = 0;
|
||||||
|
for (var i = 0; i < data.product.parameters.length; i++) {
|
||||||
data.product.parameters[i].paramIndex = i;
|
data.product.parameters[i].paramIndex = i;
|
||||||
|
if (data.product.parameters[i].isLatency)
|
||||||
|
continue;
|
||||||
|
data.product.parameters[i].paramInfoIndex = inIdx + outIdx;
|
||||||
|
if (data.product.parameters[i].direction == "input") {
|
||||||
|
data.product.parameters[i].paramDataIndex = inIdx;
|
||||||
|
inIdx++;
|
||||||
|
} else {
|
||||||
|
data.product.parameters[i].paramDataIndex = outIdx;
|
||||||
|
outIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.copyFile(`data${sep}PkgInfo`, `data${sep}PkgInfo`);
|
api.copyFile(`data${sep}PkgInfo`, `data${sep}PkgInfo`);
|
||||||
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
||||||
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||||
api.copyFile(`..${sep}common${sep}fatica.h`, `src${sep}fatica.h`);
|
|
||||||
};
|
};
|
||||||
|
33
templates/web-demo/rules-extra-web-demo.mk
Normal file
33
templates/web-demo/rules-extra-web-demo.mk
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#
|
||||||
|
# Tibia
|
||||||
|
#
|
||||||
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
|
#
|
||||||
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 3 of the License.
|
||||||
|
#
|
||||||
|
# Tibia is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Tibia. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File author: Stefano D'Angelo
|
||||||
|
#
|
||||||
|
|
||||||
|
build/web/index.html: $(DATA_DIR)/src/index.html | build/web
|
||||||
|
cp $^ $@
|
||||||
|
|
||||||
|
build/web/key.pem: build/web/cert.pem
|
||||||
|
|
||||||
|
build/web/cert.pem: | build
|
||||||
|
openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" 2>/dev/null
|
||||||
|
|
||||||
|
strip-web-demo: build/web/index.html
|
||||||
|
$(eval TMP := $(shell mktemp /tmp/index.XXXXXX))
|
||||||
|
html-minifier --collapse-whitespace --remove-comments --remove-redundant-attributes --remove-script-type-attributes --minify-css true --minify-js true build/web/index.html > $(TMP) || (rm $(TMP) && exit 1)
|
||||||
|
cp $(TMP) build/web/index.html || (rm $(TMP) && exit 1)
|
||||||
|
rm $(TMP)
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Tibia
|
Tibia
|
||||||
|
|
||||||
Copyright (C) 2022-2024 Orastron Srl unipersonale
|
Copyright (C) 2022-2025 Orastron Srl unipersonale
|
||||||
|
|
||||||
Tibia is free software: you can redistribute it and/or modify
|
Tibia is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -75,12 +75,12 @@ var Player = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function map(index, value) {
|
function map(index, value) {
|
||||||
var p = demo.Module.data.product.parameters[index];
|
var p = demo.Module.parameters[index];
|
||||||
return p.map == "logarithmic" ? p.minimum * Math.exp((2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))) * value) : p.minimum + (p.maximum - p.minimum) * value;
|
return p.map == "logarithmic" ? p.minimum * Math.exp((2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))) * value) : p.minimum + (p.maximum - p.minimum) * value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmap(index, value) {
|
function unmap(index, value) {
|
||||||
var p = demo.Module.data.product.parameters[index];
|
var p = demo.Module.parameters[index];
|
||||||
return p.map == "logarithmic" ? Math.log(value / p.minimum) / (2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))) : (value - p.minimum) / (p.maximum - p.minimum);
|
return p.map == "logarithmic" ? Math.log(value / p.minimum) / (2.0 * Math.log(Math.sqrt(p.maximum * p.minimum) / Math.abs(p.minimum))) : (value - p.minimum) / (p.maximum - p.minimum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ var units = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function displayValue(elem, index, value) {
|
function displayValue(elem, index, value) {
|
||||||
var param = demo.Module.data.product.parameters[index];
|
var param = demo.Module.parameters[index];
|
||||||
var unit = param.unit;
|
var unit = param.unit;
|
||||||
if (param.integer)
|
if (param.integer)
|
||||||
value = Math.round(value);
|
value = Math.round(value);
|
||||||
@ -132,9 +132,9 @@ window.addEventListener("load", function (e) {
|
|||||||
var playPause = document.getElementById("playPause");
|
var playPause = document.getElementById("playPause");
|
||||||
var controls = document.getElementById("controls");
|
var controls = document.getElementById("controls");
|
||||||
|
|
||||||
audioInputIndex = demo.Module.data.product.buses.filter(x => x.type == "audio" && x.direction == "input").findIndex(x => !x.cv && !x.sidechain);
|
audioInputIndex = demo.Module.buses.filter(x => x.type == "audio" && x.direction == "input").findIndex(x => !x.cv && !x.sidechain);
|
||||||
audioOutputIndex = demo.Module.data.product.buses.filter(x => x.type == "audio" && x.direction == "output").findIndex(x => !x.cv && !x.sidechain);
|
audioOutputIndex = demo.Module.buses.filter(x => x.type == "audio" && x.direction == "output").findIndex(x => !x.cv && !x.sidechain);
|
||||||
hasMidiInput = demo.Module.data.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0;
|
hasMidiInput = demo.Module.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0;
|
||||||
|
|
||||||
if (hasMidiInput && !navigator.requestMIDIAccess)
|
if (hasMidiInput && !navigator.requestMIDIAccess)
|
||||||
alert("Your browser doesn't support the Web MIDI API");
|
alert("Your browser doesn't support the Web MIDI API");
|
||||||
@ -145,7 +145,7 @@ window.addEventListener("load", function (e) {
|
|||||||
file.value = "";
|
file.value = "";
|
||||||
playPause.disabled = true;
|
playPause.disabled = true;
|
||||||
|
|
||||||
var parameters = demo.Module.data.product.parameters;
|
var parameters = demo.Module.parameters;
|
||||||
for (var i = 0; i < parameters.length; i++) {
|
for (var i = 0; i < parameters.length; i++) {
|
||||||
var div = document.createElement("div");
|
var div = document.createElement("div");
|
||||||
|
|
||||||
@ -241,8 +241,8 @@ window.addEventListener("load", function (e) {
|
|||||||
if ((e.data[0] & 0xf0) == 0xf0)
|
if ((e.data[0] & 0xf0) == 0xf0)
|
||||||
return;
|
return;
|
||||||
var msg = { type: "midi", data: e.data };
|
var msg = { type: "midi", data: e.data };
|
||||||
for (var i = 0; i < demo.Module.data.product.buses.length; i++) {
|
for (var i = 0; i < demo.Module.buses.length; i++) {
|
||||||
var b = demo.Module.data.product.buses[i];
|
var b = demo.Module.buses[i];
|
||||||
if (b.type != "midi" || b.direction != "input")
|
if (b.type != "midi" || b.direction != "input")
|
||||||
continue;
|
continue;
|
||||||
msg.index = i;
|
msg.index = i;
|
||||||
|
@ -23,6 +23,6 @@ var sep = path.sep;
|
|||||||
|
|
||||||
module.exports = function (data, api) {
|
module.exports = function (data, api) {
|
||||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||||
api.copyFile(`vars-extra.mk`, `vars-extra.mk`);
|
api.copyFile(`vars-extra-web-demo.mk`, `vars-extra-web-demo.mk`);
|
||||||
api.copyFile(`rules-extra.mk`, `rules-extra.mk`);
|
api.copyFile(`rules-extra-web-demo.mk`, `rules-extra-web-demo.mk`);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,10 +18,8 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
build/web/index.html: ${DATA_DIR}/src/index.html | build/web
|
ALL := $(ALL) build/web/index.html build/web/cert.pem build/web/key.pem
|
||||||
cp $^ $@
|
|
||||||
|
|
||||||
build/web/key.pem: build/web/cert.pem
|
STRIP_ALL := $(STRIP_ALL) build/web/index.html
|
||||||
|
STRIP_PREREQS := $(STRIP_PREREQS) strip-web-demo
|
||||||
build/web/cert.pem: | build
|
PHONY := $(PHONY) strip-web-demo
|
||||||
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 2>/dev/null
|
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,17 +18,28 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
|
SHELL := bash -o pipefail
|
||||||
|
|
||||||
|
TEMPLATE := web
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
COMMON_DIR ?= .
|
||||||
DATA_DIR := $(or $(DATA_DIR),.)
|
DATA_DIR ?= .
|
||||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
PLUGIN_DIR ?= src
|
||||||
|
API_DIR ?= $(PLUGIN_DIR)
|
||||||
|
MKINC_DIR ?= $(COMMON_DIR)
|
||||||
|
|
||||||
|
BUILD_BIN_DIR := build/web
|
||||||
|
BUILD_DATA_DIR := build/web
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-pre.mk
|
||||||
|
|
||||||
CC := clang
|
CC := clang
|
||||||
CXX := clang++
|
CXX := clang++
|
||||||
|
|
||||||
CFLAGS := -Ofast -Wall -Wpedantic -Wextra
|
CFLAGS := -Ofast -Wall -Wpedantic -Wextra
|
||||||
CFLAGS_ALL := -I$(COMMON_DIR)/src -I$(DATA_DIR)/src -I$(PLUGIN_DIR) --target=wasm32 -flto -fvisibility=hidden $(CFLAGS) $(CFLAGS_EXTRA)
|
CFLAGS_ALL := -I$(COMMON_DIR)/src -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) --target=wasm32 -flto -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
LDFLAGS_ALL := \
|
LDFLAGS_ALL := \
|
||||||
-Wl,--allow-undefined \
|
-Wl,--allow-undefined \
|
||||||
@ -56,28 +67,32 @@ LDFLAGS_ALL := \
|
|||||||
ifeq ($(HAS_MIDI_IN), yes)
|
ifeq ($(HAS_MIDI_IN), yes)
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,--export=processor_midi_msg_in
|
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,--export=processor_midi_msg_in
|
||||||
endif
|
endif
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) $(LDFLAGS) $(LDFLAGS_EXTRA)
|
LDFLAGS_ALL := $(LDFLAGS_ALL) $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS)
|
||||||
CXXFLAGS_ALL := -I$(COMMON_DIR)/src -I$(DATA_DIR)/src -I$(PLUGIN_DIR) --target=wasm32 -flto -fvisibility=hidden $(CXXFLAGS) $(CXXFLAGS_EXTRA)
|
CXXFLAGS_ALL := -I$(COMMON_DIR)/src -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) --target=wasm32 -flto -fvisibility=hidden $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||||
|
|
||||||
C_SRCS := $(COMMON_DIR)/src/processor.c $(COMMON_DIR)/src/walloc.c $(COMMON_DIR)/src/string.c
|
C_SRCS := $(COMMON_DIR)/src/processor.c $(COMMON_DIR)/src/walloc.c $(COMMON_DIR)/src/string.c
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
|
|
||||||
ifeq ($(CXX_SRCS_EXTRA),)
|
ifeq ($(CXX_SRCS_EXTRA),)
|
||||||
CXX_SRCS :=
|
CXX_SRCS :=
|
||||||
CXX_OBJS :=
|
CXX_OBJS :=
|
||||||
else
|
else
|
||||||
CXX_SRCS := $(COMMON_DIR)/src/new.cpp $(CXX_SRCS_EXTRA)
|
CXX_SRCS := $(COMMON_DIR)/src/new.cpp $(CXX_SRCS_EXTRA)
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
BUNDLE_DATA_PATH := build/web
|
DIRS := build build/obj build/web build/web/$(BUNDLE_NAME)
|
||||||
BUNDLE_BIN_PATH := build/web
|
|
||||||
|
|
||||||
ALL := build/web/$(BUNDLE_NAME)/module.wasm build/web/$(BUNDLE_NAME)/processor.js build/web/$(BUNDLE_NAME)/module.js
|
ALL := build/web/$(BUNDLE_NAME)/module.wasm build/web/$(BUNDLE_NAME)/processor.js build/web/$(BUNDLE_NAME)/module.js
|
||||||
|
|
||||||
-include $(COMMON_DIR)/vars-extra.mk
|
STRIP_ALL := build/web/$(BUNDLE_NAME)/module.wasm build/web/$(BUNDLE_NAME)/processor.js build/web/$(BUNDLE_NAME)/module.js
|
||||||
|
STRIP_PREREQS := $(STRIP_ALL)
|
||||||
|
|
||||||
|
PHONY := all clean strip
|
||||||
|
|
||||||
|
-include $(MKINC_DIR)/vars-extra.mk
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
@ -89,21 +104,27 @@ build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) $(CXX_OBJS) | build/web/$(BUNDLE
|
|||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build/web/$(BUNDLE_NAME)/processor.js: $(DATA_DIR)/res/processor.js | build/web/$(BUNDLE_NAME)
|
build/web/$(BUNDLE_NAME)/processor.js: $(DATA_DIR)/src/processor.js | build/web/$(BUNDLE_NAME)
|
||||||
cp $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
build/web/$(BUNDLE_NAME)/module.js: $(DATA_DIR)/res/module.js | build/web/$(BUNDLE_NAME)
|
build/web/$(BUNDLE_NAME)/module.js: $(DATA_DIR)/src/module.js | build/web/$(BUNDLE_NAME)
|
||||||
cp $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
build/obj build/web build/web/$(BUNDLE_NAME):
|
$(DIRS):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-extra.mk
|
strip: $(STRIP_PREREQS)
|
||||||
|
#already stripped
|
||||||
|
#wasm-strip build/web/$(BUNDLE_NAME)/module.wasm
|
||||||
|
uglifyjs -c pure_funcs -m reserved build/web/$(BUNDLE_NAME)/module.js -o build/web/$(BUNDLE_NAME)/module.js
|
||||||
|
uglifyjs -c pure_funcs -m reserved build/web/$(BUNDLE_NAME)/processor.js -o build/web/$(BUNDLE_NAME)/processor.js
|
||||||
|
|
||||||
.PHONY: all clean
|
-include $(MKINC_DIR)/rules-extra.mk
|
||||||
|
|
||||||
|
.PHONY: $(PHONY)
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
@ -115,4 +136,6 @@ $(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$
|
|||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||||
|
|
||||||
-include $(COMMON_DIR)/rules-secondexp-extra.mk
|
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
@ -20,15 +20,27 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
CFLAGS_EXTRA := {{=it.make?.cflags ?? ""}} {{=it.web_make?.cflags ?? ""}}
|
{{?(it.web_make?.commonDir || it.make?.commonDir)}}
|
||||||
CXXFLAGS_EXTRA := {{=it.make?.cxxflags ?? ""}} {{=it.web_make?.cxxflags ?? ""}}
|
|
||||||
LDFLAGS_EXTRA := {{=it.make?.ldflags ?? ""}} {{=it.web_make?.ldflags ?? ""}}
|
|
||||||
|
|
||||||
C_SRCS_EXTRA := {{=it.make?.cSrcs ?? ""}} {{=it.web_make?.cSrcs ?? ""}}
|
|
||||||
CXX_SRCS_EXTRA := {{=it.make?.cxxSrcs ?? ""}} {{=it.web_make?.cxxSrcs ?? ""}}
|
|
||||||
|
|
||||||
COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.web_make?.dataDir || it.make?.dataDir)}}
|
||||||
DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.web_make?.pluginDir || it.make?.pluginDir)}}
|
||||||
PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.web_make?.apiDir || it.make?.apiDir)}}
|
||||||
|
API_DIR := {{=it.web_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
{{?(it.web_make?.mkincDir || it.make?.mkincDir)}}
|
||||||
|
MKINC_DIR := {{=it.web_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||||
|
{{?}}
|
||||||
|
|
||||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
|
{{?it.make?.extra}}
|
||||||
|
{{=it.make.extra}}
|
||||||
|
{{?}}
|
||||||
|
{{?it.web_make?.extra}}
|
||||||
|
{{=it.web_make.extra}}
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -44,3 +44,7 @@ static size_t param_out_index[DATA_PRODUCT_PARAMETERS_OUTPUT_N] = {
|
|||||||
{{~it.product.parameters :p:i}}{{?p.direction == "output"}}{{=i}}, {{?}}{{~}}
|
{{~it.product.parameters :p:i}}{{?p.direction == "output"}}{{=i}}, {{?}}{{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{{?it.product.state && it.product.state.dspCustom}}
|
||||||
|
#define DATA_STATE_DSP_CUSTOM
|
||||||
|
{{?}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022-2024 Orastron Srl unipersonale
|
* Copyright (C) 2022-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -18,13 +18,12 @@
|
|||||||
* File author: Stefano D'Angelo
|
* File author: Stefano D'Angelo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const data = {
|
const buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
||||||
company: {{=JSON.stringify(it.company, null, 2)}},
|
const parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
||||||
product: {{=JSON.stringify(it.product, null, 2)}}
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Module {
|
export class Module {
|
||||||
static get data() { return data; }
|
static get buses() { return buses; }
|
||||||
|
static get parameters() { return parameters; }
|
||||||
|
|
||||||
async init(context, processorJsPath, wasmPath) {
|
async init(context, processorJsPath, wasmPath) {
|
||||||
var wasmBytes = await fetch(wasmPath)
|
var wasmBytes = await fetch(wasmPath)
|
||||||
@ -45,11 +44,11 @@ export class Module {
|
|||||||
|
|
||||||
export class Node extends AudioWorkletNode {
|
export class Node extends AudioWorkletNode {
|
||||||
constructor(module) {
|
constructor(module) {
|
||||||
super(module.context, data.product.bundleName,
|
super(module.context, "{{=it.product.bundleName}}",
|
||||||
{
|
{
|
||||||
numberOfInputs: data.product.buses.filter(b => b.type == "audio" && b.direction == "input").length,
|
numberOfInputs: buses.filter(b => b.type == "audio" && b.direction == "input").length,
|
||||||
numberOfOutputs: data.product.buses.filter(b => b.type == "audio" && b.direction == "output").length,
|
numberOfOutputs: buses.filter(b => b.type == "audio" && b.direction == "output").length,
|
||||||
outputChannelCount: data.product.buses.filter(b => b.type == "audio" && b.direction == "output").map(b => b.channels == "mono" ? 1 : 2),
|
outputChannelCount: buses.filter(b => b.type == "audio" && b.direction == "output").map(b => b.channels == "mono" ? 1 : 2),
|
||||||
processorOptions: { wasmBytes: module.wasmBytes }
|
processorOptions: { wasmBytes: module.wasmBytes }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022-2024 Orastron Srl unipersonale
|
* Copyright (C) 2022-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -30,15 +30,15 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plugin p;
|
plugin p;
|
||||||
void *mem;
|
void * mem;
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128];
|
float x_buf[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N * 128];
|
||||||
const float *x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||||
float zero_buf[128];
|
float zero_buf[128];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||||
float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128];
|
float y_buf[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N * 128];
|
||||||
float *y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0
|
#if DATA_PRODUCT_PARAMETERS_OUTPUT_N > 0
|
||||||
float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N];
|
float out_params[DATA_PRODUCT_PARAMETERS_OUTPUT_N];
|
||||||
@ -46,6 +46,11 @@ typedef struct {
|
|||||||
} instance;
|
} instance;
|
||||||
|
|
||||||
instance * processor_new(float sample_rate) {
|
instance * processor_new(float sample_rate) {
|
||||||
|
#ifdef DATA_STATE_DSP_CUSTOM
|
||||||
|
(void)plugin_state_load;
|
||||||
|
(void)plugin_state_save;
|
||||||
|
#endif
|
||||||
|
|
||||||
instance * i = malloc(sizeof(instance));
|
instance * i = malloc(sizeof(instance));
|
||||||
if (i == NULL)
|
if (i == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -18,19 +18,14 @@
|
|||||||
* File author: Stefano D'Angelo
|
* File author: Stefano D'Angelo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
var buses = {{=JSON.stringify(it.product.buses, null, 2)}};
|
||||||
const parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
var parameters = {{=JSON.stringify(it.product.parameters, null, 2)}};
|
||||||
|
|
||||||
const busesIn = buses.filter(x => x.type == "audio" && x.direction == "input");
|
var busesIn = buses.filter(x => x.type == "audio" && x.direction == "input");
|
||||||
const busesOut = buses.filter(x => x.type == "audio" && x.direction == "output");
|
var busesOut = buses.filter(x => x.type == "audio" && x.direction == "output");
|
||||||
|
|
||||||
const nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
var nChansIn = busesIn.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
||||||
const nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
var nChansOut = busesOut.reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0);
|
||||||
|
|
||||||
let cpu_meter = 0.0;
|
|
||||||
|
|
||||||
// performance is not available, and there's no better option than Date atm
|
|
||||||
const now = Date.now;
|
|
||||||
|
|
||||||
class Processor extends AudioWorkletProcessor {
|
class Processor extends AudioWorkletProcessor {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
@ -76,8 +71,6 @@ class Processor extends AudioWorkletProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process(inputs, outputs, params) {
|
process(inputs, outputs, params) {
|
||||||
const processTimeStart = now();
|
|
||||||
|
|
||||||
for (var i = 0; i < this.parametersIn.length; i++) {
|
for (var i = 0; i < this.parametersIn.length; i++) {
|
||||||
var index = this.parametersIn[i].index;
|
var index = this.parametersIn[i].index;
|
||||||
var parameter = parameters[index];
|
var parameter = parameters[index];
|
||||||
@ -148,11 +141,7 @@ class Processor extends AudioWorkletProcessor {
|
|||||||
|
|
||||||
for (var i = 0; i < this.parametersOut.length; i++) {
|
for (var i = 0; i < this.parametersOut.length; i++) {
|
||||||
var index = this.parametersOut[i].index;
|
var index = this.parametersOut[i].index;
|
||||||
var value;
|
var value = this.parametersOutValues[i];
|
||||||
if (parameters[index].isCpumeter)
|
|
||||||
value = cpu_meter;
|
|
||||||
else
|
|
||||||
value = this.parametersOutValues[i];
|
|
||||||
if (value != this.parametersOut[i].value) {
|
if (value != this.parametersOut[i].value) {
|
||||||
this.paramOutChangeMsg.index = index;
|
this.paramOutChangeMsg.index = index;
|
||||||
this.paramOutChangeMsg.value = value;
|
this.paramOutChangeMsg.value = value;
|
||||||
@ -160,9 +149,6 @@ class Processor extends AudioWorkletProcessor {
|
|||||||
this.parametersOut[i].value = value;
|
this.parametersOut[i].value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const processTimeEnd = now();
|
|
||||||
const processTimeMs = processTimeEnd - processTimeStart;
|
|
||||||
cpu_meter = cpu_meter * 0.99 + (processTimeMs * 0.128 / sampleRate) * 0.01; // TODO: something better than 0.99?
|
|
||||||
|
|
||||||
return true; // because Chrome sucks: https://bugs.chromium.org/p/chromium/issues/detail?id=921354
|
return true; // because Chrome sucks: https://bugs.chromium.org/p/chromium/issues/detail?id=921354
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,6 @@ module.exports = function (data, api) {
|
|||||||
api.copyFile(`src${sep}new.cpp`, `src${sep}new.cpp`);
|
api.copyFile(`src${sep}new.cpp`, `src${sep}new.cpp`);
|
||||||
api.copyFile(`src${sep}processor.c`, `src${sep}processor.c`);
|
api.copyFile(`src${sep}processor.c`, `src${sep}processor.c`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||||
api.generateFileFromTemplateFile(`src${sep}processor.js`, `res${sep}processor.js`, data);
|
api.generateFileFromTemplateFile(`src${sep}processor.js`, `src${sep}processor.js`, data);
|
||||||
api.generateFileFromTemplateFile(`src${sep}module.js`, `res${sep}module.js`, data);
|
api.generateFileFromTemplateFile(`src${sep}module.js`, `src${sep}module.js`, data);
|
||||||
};
|
};
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"android_make": {
|
|
||||||
"cxxflags" : "-I../../../miniaudio",
|
|
||||||
"keyStore" : "keystore.jks",
|
|
||||||
"keyAlias" : "androidkey",
|
|
||||||
"storePass" : "android",
|
|
||||||
"keyPass" : "android",
|
|
||||||
"sdkDir" : "${HOME}/Android/Sdk",
|
|
||||||
"ndkVersion" : "27.0.11902837",
|
|
||||||
"buildToolsVersion" : "35.0.0",
|
|
||||||
"androidxDir" : "${HOME}/Android/androidx",
|
|
||||||
"kotlinDir" : "${HOME}/Android/kotlin",
|
|
||||||
"androidVersion" : "35",
|
|
||||||
"androidxCoreVersion" : "1.13.1",
|
|
||||||
"androidxLifecycleCommonVersion" : "2.8.3",
|
|
||||||
"androidxVersionedparcelableVersion" : "1.2.0",
|
|
||||||
"kotlinStdlibVersion" : "2.0.0",
|
|
||||||
"kotlinxCoroutinesCoreVersion" : "1.8.0",
|
|
||||||
"kotlinxCoroutinesCoreJVMVersion" : "1.8.1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"android": {
|
"android": {
|
||||||
"javaPackageName" : "com.example.tibia_test"
|
"javaPackageName": "com.example.tibia_test",
|
||||||
|
"androidVersion": "36"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"cmd_make": {
|
|
||||||
"tinywavDir" : "../../../tinywav",
|
|
||||||
"midiParserDir" : "../../../midi-parser"
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@
|
|||||||
"company": {
|
"company": {
|
||||||
"name": "Example company",
|
"name": "Example company",
|
||||||
"url": "https://www.example.com/",
|
"url": "https://www.example.com/",
|
||||||
"email": "info@example.com",
|
"email": "info@example.com"
|
||||||
"domain": "com.example"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"daisy_seed_make": {
|
|
||||||
"libdaisyDir" : "../../../libDaisy"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"daisy_seed": {
|
"daisy_seed": {
|
||||||
"parameterPins" : [ 15, 16, 17, 18, 22 ]
|
"parameterPins": [ 15, 16, 17, 18, 22 ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ios_make": {
|
"ios_make": {
|
||||||
"headerSearchPaths" : [ "../../../../../miniaudio" ],
|
"headerSearchPaths": [ "../../../../../miniaudio" ],
|
||||||
"deploymentTarget" : 16.6
|
"deploymentTarget": "16.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ios": {
|
"ios": {
|
||||||
"productBundleIdentifier" : "com.example.tibia-test"
|
"productBundleIdentifier": "com.example.tibia-test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"lv2_make": {
|
|
||||||
"cflags" : "$(shell pkg-config --cflags pugl-cairo-0 pugl-0 cairo)",
|
|
||||||
"ldflags" : "$(shell pkg-config --libs pugl-cairo-0 pugl-0 cairo) -Wl,-rpath,$(shell pkg-config --variable=libdir pugl-cairo-0),-rpath,$(shell pkg-config --variable=libdir pugl-0),-rpath,$(shell pkg-config --variable=libdir cairo)"
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@
|
|||||||
"types": [ "@lv2:AmplifierPlugin" ],
|
"types": [ "@lv2:AmplifierPlugin" ],
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"ui": {
|
"ui": {
|
||||||
"uri": "@example:tibia_test_ui"
|
"uri": "@example:tibia_test#ui"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -18,6 +18,8 @@
|
|||||||
* File author: Stefano D'Angelo
|
* File author: Stefano D'Angelo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct plugin {
|
typedef struct plugin {
|
||||||
float sample_rate;
|
float sample_rate;
|
||||||
size_t delay_line_length;
|
size_t delay_line_length;
|
||||||
@ -27,14 +29,14 @@ typedef struct plugin {
|
|||||||
float cutoff;
|
float cutoff;
|
||||||
char bypass;
|
char bypass;
|
||||||
|
|
||||||
float *delay_line;
|
float * delay_line;
|
||||||
size_t delay_line_cur;
|
size_t delay_line_cur;
|
||||||
float z1;
|
float z1;
|
||||||
float cutoff_k;
|
float cutoff_k;
|
||||||
float yz1;
|
float yz1;
|
||||||
} plugin;
|
} plugin;
|
||||||
|
|
||||||
static void plugin_init(plugin *instance, plugin_callbacks *cbs) {
|
static void plugin_init(plugin *instance, const plugin_callbacks *cbs) {
|
||||||
(void)instance;
|
(void)instance;
|
||||||
(void)cbs;
|
(void)cbs;
|
||||||
}
|
}
|
||||||
@ -69,11 +71,10 @@ static void plugin_reset(plugin *instance) {
|
|||||||
static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case plugin_parameter_gain:
|
case plugin_parameter_gain:
|
||||||
//approx instance->gain = powf(10.f, 0.05f * value);
|
instance->gain = value;
|
||||||
instance->gain = ((2.6039890429412597e-4f * value + 0.032131027163547855f) * value + 1.f) / ((0.0012705124328080768f * value - 0.0666763481312185f) * value + 1.f);
|
|
||||||
break;
|
break;
|
||||||
case plugin_parameter_delay:
|
case plugin_parameter_delay:
|
||||||
instance->delay = 0.001f * value;
|
instance->delay = value;
|
||||||
break;
|
break;
|
||||||
case plugin_parameter_cutoff:
|
case plugin_parameter_cutoff:
|
||||||
instance->cutoff = value;
|
instance->cutoff = value;
|
||||||
@ -94,8 +95,10 @@ static size_t calc_index(size_t cur, size_t delay, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_process(plugin *instance, const float **inputs, float **outputs, size_t n_samples) {
|
static void plugin_process(plugin *instance, const float **inputs, float **outputs, size_t n_samples) {
|
||||||
//approx size_t delay = roundf(instance->sample_rate * instance->delay);
|
//approx const float gain = powf(10.f, 0.05f * instance->gain);
|
||||||
size_t delay = (size_t)(instance->sample_rate * instance->delay + 0.5f);
|
const float gain = ((2.6039890429412597e-4f * instance->gain + 0.032131027163547855f) * instance->gain + 1.f) / ((0.0012705124328080768f * instance->gain - 0.0666763481312185f) * instance->gain + 1.f);
|
||||||
|
//approx const size_t delay = roundf(instance->sample_rate * 0.001f * instance->delay);
|
||||||
|
const size_t delay = (size_t)(instance->sample_rate * 0.001f * instance->delay + 0.5f);
|
||||||
const float mA1 = instance->sample_rate / (instance->sample_rate + 6.283185307179586f * instance->cutoff * instance->cutoff_k);
|
const float mA1 = instance->sample_rate / (instance->sample_rate + 6.283185307179586f * instance->cutoff * instance->cutoff_k);
|
||||||
for (size_t i = 0; i < n_samples; i++) {
|
for (size_t i = 0; i < n_samples; i++) {
|
||||||
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
||||||
@ -105,7 +108,7 @@ static void plugin_process(plugin *instance, const float **inputs, float **outpu
|
|||||||
instance->delay_line_cur = 0;
|
instance->delay_line_cur = 0;
|
||||||
const float y = x + mA1 * (instance->z1 - x);
|
const float y = x + mA1 * (instance->z1 - x);
|
||||||
instance->z1 = y;
|
instance->z1 = y;
|
||||||
outputs[0][i] = instance->bypass ? inputs[0][i] : instance->gain * y;
|
outputs[0][i] = instance->bypass ? inputs[0][i] : gain * y;
|
||||||
instance->yz1 = outputs[0][i];
|
instance->yz1 = outputs[0][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,3 +119,63 @@ static void plugin_midi_msg_in(plugin *instance, size_t index, const uint8_t * d
|
|||||||
//approx instance->cutoff_k = powf(2.f, (1.f / 12.f) * (note - 60));
|
//approx instance->cutoff_k = powf(2.f, (1.f / 12.f) * (note - 60));
|
||||||
instance->cutoff_k = data[1] < 64 ? (-0.19558034980097166f * data[1] - 2.361735109225749f) / (data[1] - 75.57552349522389f) : (393.95397927344214f - 7.660826245588588f * data[1]) / (data[1] - 139.0755234952239f);
|
instance->cutoff_k = data[1] < 64 ? (-0.19558034980097166f * data[1] - 2.361735109225749f) / (data[1] - 75.57552349522389f) : (393.95397927344214f - 7.660826245588588f * data[1]) / (data[1] - 139.0755234952239f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void serialize_float(uint8_t *dest, float f) {
|
||||||
|
union { float f; uint32_t u; } v;
|
||||||
|
v.f = f;
|
||||||
|
dest[0] = v.u & 0xff;
|
||||||
|
dest[1] = (v.u & 0xff00) >> 8;
|
||||||
|
dest[2] = (v.u & 0xff0000) >> 16;
|
||||||
|
dest[3] = (v.u & 0xff000000) >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float parse_float(const uint8_t *data) {
|
||||||
|
union { float f; uint32_t u; } v;
|
||||||
|
v.u = data[0];
|
||||||
|
v.u |= data[1] << 8;
|
||||||
|
v.u |= data[2] << 16;
|
||||||
|
v.u |= data[3] << 24;
|
||||||
|
return v.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plugin_state_save(plugin *instance, const plugin_state_callbacks *cbs, float last_sample_rate) {
|
||||||
|
(void)last_sample_rate;
|
||||||
|
uint8_t data[13];
|
||||||
|
cbs->lock(cbs->handle);
|
||||||
|
const float gain = instance->gain;
|
||||||
|
const float delay = instance->delay;
|
||||||
|
const float cutoff = instance->cutoff;
|
||||||
|
const char bypass = instance->bypass;
|
||||||
|
cbs->unlock(cbs->handle);
|
||||||
|
serialize_float(data, gain);
|
||||||
|
serialize_float(data + 4, delay);
|
||||||
|
serialize_float(data + 8, cutoff);
|
||||||
|
data[12] = bypass ? 1 : 0;
|
||||||
|
return cbs->write(cbs->handle, (const char *)data, 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char x_isnan(float x) {
|
||||||
|
union { uint32_t u; float f; } v;
|
||||||
|
v.f = x;
|
||||||
|
return ((v.u & 0x7f800000) == 0x7f800000) && (v.u & 0x7fffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plugin_state_load(const plugin_state_callbacks *cbs, float cur_sample_rate, const char *data, size_t length) {
|
||||||
|
(void)cur_sample_rate;
|
||||||
|
if (length != 13)
|
||||||
|
return -1;
|
||||||
|
const uint8_t *d = (const uint8_t *)data;
|
||||||
|
const float gain = parse_float(d);
|
||||||
|
const float delay = parse_float(d + 4);
|
||||||
|
const float cutoff = parse_float(d + 8);
|
||||||
|
const float bypass = d[12] ? 1.f : 0.f;
|
||||||
|
if (x_isnan(gain) || x_isnan(delay) || x_isnan(cutoff))
|
||||||
|
return -1;
|
||||||
|
cbs->lock(cbs->handle);
|
||||||
|
cbs->set_parameter(cbs->handle, plugin_parameter_gain, gain);
|
||||||
|
cbs->set_parameter(cbs->handle, plugin_parameter_delay, delay);
|
||||||
|
cbs->set_parameter(cbs->handle, plugin_parameter_cutoff, cutoff);
|
||||||
|
cbs->set_parameter(cbs->handle, plugin_parameter_bypass, bypass);
|
||||||
|
cbs->unlock(cbs->handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
355
test/plugin_ui.h
355
test/plugin_ui.h
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Orastron Srl unipersonale
|
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -18,21 +18,16 @@
|
|||||||
* File author: Stefano D'Angelo, Paolo Marrone
|
* File author: Stefano D'Angelo, Paolo Marrone
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pugl/pugl.h>
|
#include "vinci.h"
|
||||||
#include <pugl/cairo.h>
|
#include <stdio.h>
|
||||||
#include <cairo.h>
|
#include <string.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void * widget;
|
void *widget;
|
||||||
PuglWorld * world;
|
|
||||||
PuglView * view;
|
|
||||||
|
|
||||||
double fw;
|
vinci *ui;
|
||||||
double fh;
|
window *w;
|
||||||
double x;
|
int param_down;
|
||||||
double y;
|
|
||||||
double w;
|
|
||||||
double h;
|
|
||||||
|
|
||||||
float gain;
|
float gain;
|
||||||
float delay;
|
float delay;
|
||||||
@ -40,267 +35,213 @@ typedef struct {
|
|||||||
char bypass;
|
char bypass;
|
||||||
float y_z1;
|
float y_z1;
|
||||||
|
|
||||||
int param_down;
|
|
||||||
|
|
||||||
plugin_ui_callbacks cbs;
|
plugin_ui_callbacks cbs;
|
||||||
} plugin_ui;
|
} plugin_ui;
|
||||||
|
|
||||||
#define WIDTH 600.0
|
#define WIDTH 600.0
|
||||||
#define HEIGHT 400.0
|
#define HEIGHT 400.0
|
||||||
#define RATIO (WIDTH / HEIGHT)
|
|
||||||
#define INV_RATIO (HEIGHT / WIDTH)
|
|
||||||
|
|
||||||
static void plugin_ui_get_default_size(uint32_t *width, uint32_t *height) {
|
static void plugin_ui_get_default_size(uint32_t *width, uint32_t *height) {
|
||||||
*width = WIDTH;
|
*width = WIDTH;
|
||||||
*height = HEIGHT;
|
*height = HEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_ui_update_geometry(plugin_ui *instance) {
|
static void draw_rect(window *w, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color) {
|
||||||
PuglRect frame = puglGetFrame(instance->view);
|
uint32_t *data = (uint32_t*) malloc(width * height * 4);
|
||||||
instance->fw = frame.width;
|
uint32_t p = 0;
|
||||||
instance->fh = frame.height;
|
for (uint32_t i = 0; i < height; i++)
|
||||||
if (frame.width == 0 || frame.height == 0)
|
for (uint32_t j = 0; j < width; j++, p++)
|
||||||
return;
|
data[p] = color;
|
||||||
|
window_draw(w, (unsigned char*)data, 0, 0, width, height, x, y, width, height);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (instance->fw / instance->fh > RATIO) {
|
static void draw_slider(plugin_ui *pui, int id, float value) {
|
||||||
instance->w = RATIO * instance->fh;
|
const int w = window_get_width(pui->w);
|
||||||
instance->h = instance->fh;
|
const int h = window_get_height(pui->w);
|
||||||
instance->x = 0.5 * (instance->fw - instance->w);
|
draw_rect(pui->w, 0.1 * w, 0.15 * (id + 1) * h, 0.8 * w * value, 0.1 * h, 0x6789ab);
|
||||||
instance->y = 0.0;
|
draw_rect(pui->w, 0.1 * w + 0.8 * w * value, 0.15 * (id + 1) * h, 0.8 * w * (1.f - value), 0.1 * h, 0x1223bc);
|
||||||
} else {
|
}
|
||||||
instance->w = instance->fw;
|
|
||||||
instance->h = INV_RATIO * instance->fw;
|
static void draw_button(plugin_ui *pui, int id, char value) {
|
||||||
instance->x = 0.0;
|
const int w = window_get_width(pui->w);
|
||||||
instance->y = 0.5 * (instance->fh - instance->h);
|
const int h = window_get_height(pui->w);
|
||||||
|
draw_rect(pui->w, 0.4 * w, 0.15 * (id + 1) * h, 0.2 * w, 0.1 * h, value ? 0x6789ab : 0x1223bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_close(window *w) {
|
||||||
|
printf("on_close %p \n", (void*)w); fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_mouse_press (window *win, int32_t x, int32_t y, uint32_t state) {
|
||||||
|
(void) state;
|
||||||
|
|
||||||
|
plugin_ui *pui = (plugin_ui*) window_get_data(win);
|
||||||
|
const int w = window_get_width(win);
|
||||||
|
const int h = window_get_height(win);
|
||||||
|
|
||||||
|
if (x >= 0.1 * w && x <= 0.9 * w && y >= 0.15 * h && y <= 0.25 * h) {
|
||||||
|
pui->param_down = 0;
|
||||||
|
pui->gain = (float)((x - (0.1 * w)) / (0.8 * w));
|
||||||
|
pui->cbs.set_parameter_begin(pui->cbs.handle, 0, -60.f + 80.f * pui->gain);
|
||||||
|
draw_slider(pui, 0, pui->gain);
|
||||||
|
} else if (x >= 0.1 * w && x <= 0.9 * w && y >= 0.3 * h && y <= 0.4 * h) {
|
||||||
|
pui->param_down = 1;
|
||||||
|
pui->delay = (float)((x - (0.1 * w)) / (0.8 * w));
|
||||||
|
pui->cbs.set_parameter_begin(pui->cbs.handle, 1, 1000.f * pui->delay);
|
||||||
|
draw_slider(pui, 1, pui->delay);
|
||||||
|
} else if (x >= 0.1 * w && x <= 0.9 * w && y >= 0.45 * h && y <= 0.55 * h) {
|
||||||
|
pui->param_down = 2;
|
||||||
|
pui->cutoff = (float)((x - (0.1 * w)) / (0.8 * w));
|
||||||
|
pui->cbs.set_parameter_begin(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff));
|
||||||
|
draw_slider(pui, 2, pui->cutoff);
|
||||||
|
} else if (x >= 0.4 * w && x <= 0.6 * w && y >= 0.6 * h && y <= 0.7 * h) {
|
||||||
|
pui->param_down = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_ui_draw(plugin_ui *instance) {
|
static void on_mouse_release (window *win, int32_t x, int32_t y, uint32_t state) {
|
||||||
cairo_t *cr = (cairo_t *)puglGetContext(instance->view);
|
(void) state;
|
||||||
double x = instance->x;
|
|
||||||
double y = instance->y;
|
|
||||||
double w = instance->w;
|
|
||||||
double h = instance->h;
|
|
||||||
|
|
||||||
cairo_set_line_width(cr, 0.005 * h);
|
plugin_ui *pui = (plugin_ui*) window_get_data(win);
|
||||||
|
const int w = window_get_width(win);
|
||||||
|
const int h = window_get_height(win);
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0, 0, 0);
|
if (pui->param_down == 4)
|
||||||
cairo_paint(cr);
|
if (x >= 0.4 * w && x <= 0.6 * w && y >= 0.6 * h && y <= 0.7 * h) {
|
||||||
|
pui->bypass = !pui->bypass;
|
||||||
cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
|
pui->cbs.set_parameter(pui->cbs.handle, 3, pui->bypass ? 1.f : 0.f);
|
||||||
cairo_rectangle(cr, x, y, w, h);
|
draw_button(pui, 3, pui->bypass);
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.15 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.15 * h, 0.8 * w * instance->gain, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.15 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.3 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.3 * h, 0.8 * w * instance->delay, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.3 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.45 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.45 * h, 0.8 * w * instance->cutoff, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.45 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
|
|
||||||
if (instance->bypass)
|
|
||||||
cairo_set_source_rgb(cr, 1.0, 0, 0);
|
|
||||||
else
|
|
||||||
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
|
|
||||||
cairo_rectangle(cr, x + 0.4 * w, y + 0.6 * h, 0.2 * w, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.75 * h, 0.8 * w, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
|
||||||
cairo_rectangle(cr, x + 0.1 * w, y + 0.75 * h, 0.8 * w * instance->y_z1, 0.1 * h);
|
|
||||||
cairo_fill(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PuglStatus plugin_ui_on_event(PuglView *view, const PuglEvent *event) {
|
|
||||||
switch (event->type) {
|
|
||||||
case PUGL_CONFIGURE:
|
|
||||||
{
|
|
||||||
plugin_ui *instance = (plugin_ui *)puglGetHandle(view);
|
|
||||||
plugin_ui_update_geometry(instance);
|
|
||||||
puglPostRedisplay(instance->view);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case PUGL_BUTTON_PRESS:
|
|
||||||
{
|
|
||||||
plugin_ui *instance = (plugin_ui *)puglGetHandle(view);
|
|
||||||
const PuglButtonEvent *ev = (const PuglButtonEvent *)event;
|
|
||||||
double x = instance->x;
|
|
||||||
double y = instance->y;
|
|
||||||
double w = instance->w;
|
|
||||||
double h = instance->h;
|
|
||||||
|
|
||||||
if (ev->x >= x + 0.1 * w && ev->x <= x + 0.9 * w
|
if (pui->param_down != -1) {
|
||||||
&& ev->y >= y + 0.15 * h && ev->y <= y + 0.25 * h) {
|
float v = x < 0.1 * w ? 0.f : (x > 0.9 * w ? 1.f : (float)((x - (0.1 * w)) / (0.8 * w)));
|
||||||
instance->param_down = 0;
|
switch (pui->param_down) {
|
||||||
instance->gain = (float)((ev->x - (x + 0.1 * w)) / (0.8 * w));
|
|
||||||
instance->cbs.set_parameter_begin(instance->cbs.handle, 0);
|
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 0, -60.f + 80.f * instance->gain);
|
|
||||||
puglPostRedisplay(instance->view);
|
|
||||||
} else if (ev->x >= x + 0.1 * w && ev->x <= x + 0.9 * w
|
|
||||||
&& ev->y >= y + 0.3 * h && ev->y <= y + 0.4 * h) {
|
|
||||||
instance->param_down = 1;
|
|
||||||
instance->delay = (float)((ev->x - (x + 0.1 * w)) / (0.8 * w));
|
|
||||||
instance->cbs.set_parameter_begin(instance->cbs.handle, 1);
|
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 1, 1000.f * instance->delay);
|
|
||||||
puglPostRedisplay(instance->view);
|
|
||||||
} else if (ev->x >= x + 0.1 * w && ev->x <= x + 0.9 * w
|
|
||||||
&& ev->y >= y + 0.45 * h && ev->y <= y + 0.55 * h) {
|
|
||||||
instance->param_down = 2;
|
|
||||||
instance->cutoff = (float)((ev->x - (x + 0.1 * w)) / (0.8 * w));
|
|
||||||
instance->cbs.set_parameter_begin(instance->cbs.handle, 2);
|
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 2, (632.4555320336746f * instance->cutoff + 20.653108640674372f) / (1.0326554320337158f - instance->cutoff));
|
|
||||||
puglPostRedisplay(instance->view);
|
|
||||||
} else if (ev->x >= x + 0.4 * w && ev->x <= x + 0.6 * w
|
|
||||||
&& ev->y >= y + 0.6 * h && ev->y <= y + 0.7 * h) {
|
|
||||||
instance->param_down = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PUGL_MOTION:
|
|
||||||
{
|
|
||||||
plugin_ui *instance = (plugin_ui *)puglGetHandle(view);
|
|
||||||
const PuglMotionEvent *ev = (const PuglMotionEvent *)event;
|
|
||||||
double x = instance->x;
|
|
||||||
double w = instance->w;
|
|
||||||
float v = ev->x < x + 0.1 * w ? 0.f : (ev->x > x + 0.9 * w ? 1.f : (float)((ev->x - (x + 0.1 * w)) / (0.8 * w)));
|
|
||||||
|
|
||||||
switch (instance->param_down) {
|
|
||||||
case 0:
|
case 0:
|
||||||
instance->gain = v;
|
pui->gain = v;
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 0, -60.f + 80.f * instance->gain);
|
pui->cbs.set_parameter_end(pui->cbs.handle, 0, -60.f + 80.f * pui->gain);
|
||||||
puglPostRedisplay(instance->view);
|
draw_slider(pui, 0, pui->gain);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
instance->delay = v;
|
pui->delay = v;
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 1, 1000.f * instance->delay);
|
pui->cbs.set_parameter_end(pui->cbs.handle, 1, 1000.f * pui->delay);
|
||||||
puglPostRedisplay(instance->view);
|
draw_slider(pui, 1, pui->delay);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
instance->cutoff = v;
|
pui->cutoff = v;
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 2, (632.4555320336746f * instance->cutoff + 20.653108640674372f) / (1.0326554320337158f - instance->cutoff));
|
pui->cbs.set_parameter_end(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff));
|
||||||
puglPostRedisplay(instance->view);
|
draw_slider(pui, 2, pui->cutoff);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
pui->param_down = -1;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case PUGL_BUTTON_RELEASE:
|
|
||||||
{
|
|
||||||
plugin_ui *instance = (plugin_ui *)puglGetHandle(view);
|
|
||||||
const PuglButtonEvent *ev = (const PuglButtonEvent *)event;
|
|
||||||
double x = instance->x;
|
|
||||||
double y = instance->y;
|
|
||||||
double w = instance->w;
|
|
||||||
double h = instance->h;
|
|
||||||
|
|
||||||
if (instance->param_down == 3)
|
static void on_mouse_move (window *win, int32_t x, int32_t y, uint32_t state) {
|
||||||
if (ev->x >= x + 0.4 * w && ev->x <= x + 0.6 * w
|
(void) y;
|
||||||
&& ev->y >= y + 0.6 * h && ev->y <= y + 0.7 * h) {
|
(void) state;
|
||||||
instance->bypass = !instance->bypass;
|
|
||||||
instance->cbs.set_parameter(instance->cbs.handle, 3, instance->bypass ? 1.f : 0.f);
|
|
||||||
puglPostRedisplay(instance->view);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance->param_down != -1) {
|
plugin_ui *pui = (plugin_ui*) window_get_data(win);
|
||||||
instance->cbs.set_parameter_end(instance->cbs.handle, instance->param_down);
|
const int w = window_get_width(win);
|
||||||
instance->param_down = -1;
|
|
||||||
}
|
float v = x < 0.1 * w ? 0.f : (x > 0.9 * w ? 1.f : (float)((x - (0.1 * w)) / (0.8 * w)));
|
||||||
}
|
|
||||||
|
switch (pui->param_down) {
|
||||||
|
case 0:
|
||||||
|
pui->gain = v;
|
||||||
|
pui->cbs.set_parameter(pui->cbs.handle, 0, -60.f + 80.f * pui->gain);
|
||||||
|
draw_slider(pui, 0, pui->gain);
|
||||||
break;
|
break;
|
||||||
case PUGL_EXPOSE:
|
case 1:
|
||||||
{
|
pui->delay = v;
|
||||||
plugin_ui *instance = (plugin_ui *)puglGetHandle(view);
|
pui->cbs.set_parameter(pui->cbs.handle, 1, 1000.f * pui->delay);
|
||||||
plugin_ui_update_geometry(instance); // I didn't expect this was needed here for X11 to work decently when resizing
|
draw_slider(pui, 1, pui->delay);
|
||||||
plugin_ui_draw(instance);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
case 2:
|
||||||
|
pui->cutoff = v;
|
||||||
|
pui->cbs.set_parameter(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff));
|
||||||
|
draw_slider(pui, 2, pui->cutoff);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return PUGL_SUCCESS;
|
}
|
||||||
|
|
||||||
|
static void on_window_resize (window *w, int32_t width, int32_t height) {
|
||||||
|
draw_rect(w, 0, 0, width, height, 0xff9999);
|
||||||
|
|
||||||
|
plugin_ui *pui = (plugin_ui*) window_get_data(w);
|
||||||
|
|
||||||
|
draw_slider(pui, 0, pui->gain);
|
||||||
|
draw_slider(pui, 1, pui->delay);
|
||||||
|
draw_slider(pui, 2, pui->cutoff);
|
||||||
|
draw_button(pui, 3, pui->bypass);
|
||||||
|
draw_slider(pui, 4, pui->y_z1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_ui *plugin_ui_create(char has_parent, void *parent, plugin_ui_callbacks *cbs) {
|
static plugin_ui *plugin_ui_create(char has_parent, void *parent, plugin_ui_callbacks *cbs) {
|
||||||
plugin_ui *instance = malloc(sizeof(plugin_ui));
|
plugin_ui *instance = (plugin_ui *) malloc(sizeof(plugin_ui));
|
||||||
if (instance == NULL)
|
if (instance == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
struct window_cbs wcbs;
|
||||||
|
memset(&wcbs, 0, sizeof(window_cbs));
|
||||||
|
wcbs.on_window_close = on_close;
|
||||||
|
wcbs.on_mouse_press = on_mouse_press;
|
||||||
|
wcbs.on_mouse_release = on_mouse_release;
|
||||||
|
wcbs.on_mouse_move = on_mouse_move;
|
||||||
|
wcbs.on_window_resize = on_window_resize;
|
||||||
|
|
||||||
instance->param_down = -1;
|
instance->param_down = -1;
|
||||||
instance->world = puglNewWorld(PUGL_MODULE, 0);
|
instance->ui = vinci_new();
|
||||||
instance->view = puglNewView(instance->world);
|
instance->w = window_new(instance->ui, has_parent ? parent : NULL, WIDTH, HEIGHT, &wcbs);
|
||||||
puglSetSizeHint(instance->view, PUGL_DEFAULT_SIZE, WIDTH, HEIGHT);
|
instance->widget = window_get_handle(instance->w);
|
||||||
puglSetViewHint(instance->view, PUGL_RESIZABLE, PUGL_TRUE);
|
window_set_data(instance->w, (void*) instance);
|
||||||
puglSetHandle(instance->view, instance);
|
window_show(instance->w);
|
||||||
puglSetBackend(instance->view, puglCairoBackend());
|
|
||||||
PuglRect frame = { 0, 0, WIDTH, HEIGHT };
|
// just some valid values to allow drawing
|
||||||
puglSetFrame(instance->view, frame);
|
instance->gain = 0.f;
|
||||||
puglSetEventFunc(instance->view, plugin_ui_on_event);
|
instance->delay = 0.f;
|
||||||
if (has_parent)
|
instance->cutoff = 0.f;
|
||||||
puglSetParentWindow(instance->view, (PuglNativeView)parent);
|
instance->bypass = 0;
|
||||||
if (puglRealize(instance->view)) {
|
instance->y_z1 = 0.f;
|
||||||
puglFreeView(instance->view);
|
|
||||||
puglFreeWorld(instance->world);
|
on_window_resize(instance->w, window_get_width(instance->w), window_get_height(instance->w));
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
instance->widget = (void *)puglGetNativeView(instance->view);
|
|
||||||
instance->cbs = *cbs;
|
instance->cbs = *cbs;
|
||||||
puglSetFrame(instance->view, frame); // Intentionally duplicated because of ardour/lv2/mac strange event order call
|
|
||||||
puglShow(instance->view, PUGL_SHOW_RAISE); // Cocoa calls events at this so it's better this happens late
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_ui_free(plugin_ui *instance) {
|
static void plugin_ui_free(plugin_ui *instance) {
|
||||||
puglFreeView(instance->view);
|
window_free(instance->w);
|
||||||
puglFreeWorld(instance->world);
|
vinci_destroy(instance->ui);
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_ui_idle(plugin_ui *instance) {
|
static void plugin_ui_idle(plugin_ui *instance) {
|
||||||
puglUpdate(instance->world, 0);
|
vinci_idle(instance->ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_ui_set_parameter(plugin_ui *instance, size_t index, float value) {
|
static void plugin_ui_set_parameter(plugin_ui *instance, size_t index, float value) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
instance->gain = 0.0125f * value + 0.75f;
|
instance->gain = 0.0125f * value + 0.75f;
|
||||||
|
draw_slider(instance, 0, instance->gain);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
instance->delay = 0.001f * value;
|
instance->delay = 0.001f * value;
|
||||||
|
draw_slider(instance, 1, instance->delay);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// (bad) approx log unmap
|
// (bad) approx log unmap
|
||||||
instance->cutoff = (1.0326554320337176f * value - 20.65310864067435f) / (value + 632.4555320336754f);
|
instance->cutoff = (1.0326554320337176f * value - 20.65310864067435f) / (value + 632.4555320336754f);
|
||||||
|
draw_slider(instance, 2, instance->cutoff);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
instance->bypass = value >= 0.5f;
|
instance->bypass = value >= 0.5f;
|
||||||
|
draw_button(instance, 3, instance->bypass);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
instance->y_z1 = 0.5f * value + 0.5f;
|
instance->y_z1 = 0.5f * value + 0.5f;
|
||||||
|
draw_slider(instance, 4, instance->y_z1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
puglPostRedisplay(instance->view);
|
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
"product": {
|
"product": {
|
||||||
"name": "Tibia test product",
|
"name": "Tibia test product",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"buildVersion": "1",
|
"buildVersion": 0,
|
||||||
"bundleName": "tibia_test",
|
"description": "A toy plugin to test Tibia",
|
||||||
|
"copyright": "Copyright © 2021-2025 Orastron Srl unipersonale",
|
||||||
|
"bundleName": "tibia-test",
|
||||||
"buses": [
|
"buses": [
|
||||||
{
|
{
|
||||||
"type": "audio",
|
"type": "audio",
|
||||||
@ -132,29 +134,15 @@
|
|||||||
"list": false,
|
"list": false,
|
||||||
"unit": "",
|
"unit": "",
|
||||||
"map": "linear"
|
"map": "linear"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cpu",
|
|
||||||
"shortName": "cpu",
|
|
||||||
"id": "cpu",
|
|
||||||
"direction": "output",
|
|
||||||
"isBypass": false,
|
|
||||||
"isLatency": false,
|
|
||||||
"isCpumeter": true,
|
|
||||||
"defaultValue": 0.0,
|
|
||||||
"minimum": 0.0,
|
|
||||||
"maximum": 1.0,
|
|
||||||
"toggled": false,
|
|
||||||
"optional": false,
|
|
||||||
"integer": false,
|
|
||||||
"list": false,
|
|
||||||
"unit": "",
|
|
||||||
"map": "linear"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ui": {
|
"ui": {
|
||||||
"userResizable": true,
|
"userResizable": true,
|
||||||
"selfResizable": false
|
"selfResizable": false,
|
||||||
|
"highResolution": true
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"dspCustom": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
test/rules-extra.mk
Normal file
21
test/rules-extra.mk
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# Tibia
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Orastron Srl unipersonale
|
||||||
|
#
|
||||||
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 3 of the License.
|
||||||
|
#
|
||||||
|
# Tibia is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Tibia. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File author: Stefano D'Angelo
|
||||||
|
#
|
||||||
|
|
||||||
|
include rules-extra-web-demo.mk
|
47
test/run.sh
47
test/run.sh
@ -1,39 +1,62 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tibia
|
||||||
|
#
|
||||||
|
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
|
#
|
||||||
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 3 of the License.
|
||||||
|
#
|
||||||
|
# Tibia is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Tibia. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File author: Stefano D'Angelo
|
||||||
|
#
|
||||||
|
|
||||||
dir=`dirname $0`
|
dir=`dirname $0`
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/vst3
|
|
||||||
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/api $dir/../out/api
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3 $dir/../out/vst3
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3 $dir/../out/vst3
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json,$dir/vst3-make.json $dir/../templates/vst3-make $dir/../out/vst3
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3-make $dir/../out/vst3
|
||||||
cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/vst3/src
|
cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/vst3/src
|
||||||
|
cp $dir/vars-pre.mk $dir/../out/vst3
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/lv2
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json,$dir/lv2-make.json $dir/../templates/lv2-make $dir/../out/lv2
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2-make $dir/../out/lv2
|
||||||
cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src
|
cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src
|
||||||
|
cp $dir/vars-pre.mk $dir/../out/lv2
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/web
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-make $dir/../out/web
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-make $dir/../out/web
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-demo $dir/../out/web
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-demo $dir/../out/web
|
||||||
cp $dir/plugin.h $dir/../out/web/src
|
cp $dir/plugin.h $dir/../out/web/src
|
||||||
|
cp $dir/vars-pre.mk $dir/vars-extra.mk $dir/rules-extra.mk $dir/../out/web
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/android
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android $dir/../out/android
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android $dir/../out/android
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json,$dir/android-make.json $dir/../templates/android-make $dir/../out/android
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android-make $dir/../out/android
|
||||||
cp $dir/keystore.jks $dir/../out/android
|
cp $dir/keystore.jks $dir/../out/android
|
||||||
cp $dir/plugin.h $dir/../out/android/src
|
cp $dir/plugin.h $dir/../out/android/src
|
||||||
|
cp $dir/vars-pre.mk $dir/../out/android
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/ios
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json $dir/../templates/ios $dir/../out/ios
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json $dir/../templates/ios $dir/../out/ios
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json,$dir/ios-make.json $dir/../templates/ios-make $dir/../out/ios
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json,$dir/ios-make.json $dir/../templates/ios-make $dir/../out/ios
|
||||||
cp $dir/plugin.h $dir/../out/ios/src
|
cp $dir/plugin.h $dir/../out/ios/src
|
||||||
|
cp $dir/vars-pre.mk $dir/../out/ios
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/cmd
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd $dir/../out/cmd
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd $dir/../out/cmd
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/cmd-make.json $dir/../templates/cmd-make $dir/../out/cmd
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd-make $dir/../out/cmd
|
||||||
cp $dir/plugin.h $dir/../out/cmd/src
|
cp $dir/plugin.h $dir/../out/cmd/src
|
||||||
|
cp $dir/vars-pre.mk $dir/../out/cmd
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/common $dir/../out/daisy-seed
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/daisy-seed.json $dir/../templates/daisy-seed $dir/../out/daisy-seed
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/daisy-seed.json $dir/../templates/daisy-seed $dir/../out/daisy-seed
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/daisy-seed.json,$dir/daisy-seed-make.json $dir/../templates/daisy-seed-make $dir/../out/daisy-seed
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/daisy-seed.json $dir/../templates/daisy-seed-make $dir/../out/daisy-seed
|
||||||
cp $dir/plugin.h $dir/../out/daisy-seed/src
|
cp $dir/plugin.h $dir/../out/daisy-seed/src
|
||||||
|
cp $dir/vars-pre.mk $dir/../out/daisy-seed
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# Tibia
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
# Copyright (C) 2024 Orastron Srl unipersonale
|
||||||
#
|
#
|
||||||
# Tibia is free software: you can redistribute it and/or modify
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,4 +18,4 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
ALL := $(ALL) build/web/index.html build/web/cert.pem build/web/key.pem
|
include vars-extra-web-demo.mk
|
86
test/vars-pre.mk
Normal file
86
test/vars-pre.mk
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#
|
||||||
|
# Tibia
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||||
|
#
|
||||||
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 3 of the License.
|
||||||
|
#
|
||||||
|
# Tibia is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Tibia. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File author: Stefano D'Angelo
|
||||||
|
#
|
||||||
|
|
||||||
|
API_DIR := ../api
|
||||||
|
|
||||||
|
VINCI_DIR := ../../../vinci
|
||||||
|
|
||||||
|
ifeq ($(TEMPLATE), cmd)
|
||||||
|
TINYWAV_DIR := ../../../tinywav
|
||||||
|
MIDI_PARSER_DIR := ../../../midi-parser
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TEMPLATE), lv2)
|
||||||
|
ifeq ($(OS), Windows_NT)
|
||||||
|
C_SRCS_EXTRA := $(VINCI_DIR)/vinci-win32.c
|
||||||
|
LDFLAGS_EXTRA := -mwindows
|
||||||
|
else
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
ifeq ($(UNAME_S), Darwin)
|
||||||
|
M_SRCS_EXTRA := $(VINCI_DIR)/vinci-cocoa.m
|
||||||
|
LDFLAGS_EXTRA := -framework Cocoa -lobjc
|
||||||
|
else
|
||||||
|
C_SRCS_EXTRA := $(VINCI_DIR)/vinci-xcb.c
|
||||||
|
LDFLAGS_EXTRA := -lxcb
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
CFLAGS_EXTRA := $(CFLAGS_EXTRA) -I${VINCI_DIR}
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TEMPLATE), vst3)
|
||||||
|
ifeq ($(OS), Windows_NT)
|
||||||
|
C_SRCS_EXTRA := $(VINCI_DIR)/vinci-win32.c
|
||||||
|
LDFLAGS_EXTRA := -mwindows
|
||||||
|
else
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
ifeq ($(UNAME_S), Darwin)
|
||||||
|
M_SRCS_EXTRA := $(VINCI_DIR)/vinci-cocoa.m
|
||||||
|
LDFLAGS_EXTRA := -framework Cocoa -lobjc
|
||||||
|
else
|
||||||
|
C_SRCS_EXTRA := $(VINCI_DIR)/vinci-xcb.c
|
||||||
|
LDFLAGS_EXTRA := -lxcb
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
CFLAGS_EXTRA := $(CFLAGS_EXTRA) -I../../../vst3_c_api
|
||||||
|
CFLAGS_EXTRA := $(CFLAGS_EXTRA) -I${VINCI_DIR}
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TEMPLATE), daisy-seed)
|
||||||
|
LIBDAISY_DIR := ../../../libDaisy
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TEMPLATE), android)
|
||||||
|
CXXFLAGS_EXTRA := -I../../../miniaudio
|
||||||
|
KEY_STORE := keystore.jks
|
||||||
|
KEY_ALIAS := androidkey
|
||||||
|
STORE_PASS := android
|
||||||
|
KEY_PASS := android
|
||||||
|
SDK_DIR := $(HOME)/Android/Sdk
|
||||||
|
ANDROIDX_DIR := $(HOME)/Android/androidx
|
||||||
|
KOTLIN_DIR := $(HOME)/Android/kotlin
|
||||||
|
NDK_VERSION := 28.0.13004108
|
||||||
|
BUILD_TOOLS_VERSION := 36.0.0
|
||||||
|
ANDROIDX_CORE_VERSION := 1.16.0
|
||||||
|
ANDROIDX_LIFECYCLE_COMMON_VERSION := 2.8.7
|
||||||
|
ANDROIDX_VERSIONEDPARCELABLE_VERSION := 1.2.1
|
||||||
|
KOTLIN_STDLIB_VERSION := 2.1.20
|
||||||
|
KOTLINX_COROUTINES_CORE_VERSION := 1.10.2
|
||||||
|
KOTLINX_COROUTINES_CORE_JVM_VERSION := 1.10.2
|
||||||
|
endif
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"vst3_make": {
|
|
||||||
"cflags" : "-I../../../vst3_c_api $(shell pkg-config --cflags pugl-cairo-0)",
|
|
||||||
"ldflags" : "$(shell pkg-config --libs pugl-cairo-0 pugl-0 cairo) -Wl,-rpath,$(shell pkg-config --variable=libdir pugl-cairo-0),-rpath,$(shell pkg-config --variable=libdir pugl-0),-rpath,$(shell pkg-config --variable=libdir cairo)"
|
|
||||||
}
|
|
||||||
}
|
|
102
tibia
102
tibia
@ -1,38 +1,77 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tibia
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||||
|
*
|
||||||
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3 of the License.
|
||||||
|
*
|
||||||
|
* Tibia is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tibia. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* File author: Stefano D'Angelo
|
||||||
|
*/
|
||||||
|
|
||||||
function usage() {
|
function usage() {
|
||||||
console.log("Usage:");
|
console.log("Usage:");
|
||||||
console.log(" tibia file1.json,file2.json,...filen.json template outDirectory");
|
console.log(" tibia file1.json,file2.json,...filen.json template outDirectory [override1=value1] [override2=value2] ...");
|
||||||
console.log(" tibia --common template outDirectory");
|
console.log(" tibia --common template outDirectory [override1=value1] [override2=value2] ...");
|
||||||
console.log(" tibia --data file1.json,file2.json,...filen.json template outDirectory");
|
console.log(" tibia --data file1.json,file2.json,...filen.json template outDirectory [override1=value1] [override2=value2] ...");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonFiles, template, outputDir, outputCommon, outputData;
|
var jsonFiles, template, outputDir, outputCommon, outputData, i;
|
||||||
if (process.argv[2] == "--common") {
|
if (process.argv[2] == "--common") {
|
||||||
if (process.argv.length != 5)
|
if (process.argv.length < 5)
|
||||||
usage();
|
usage();
|
||||||
jsonFiles = [];
|
jsonFiles = [];
|
||||||
template = process.argv[3];
|
template = process.argv[3];
|
||||||
outputDir = process.argv[4];
|
outputDir = process.argv[4];
|
||||||
outputCommon = true;
|
outputCommon = true;
|
||||||
outputData = false;
|
outputData = false;
|
||||||
|
i = 5;
|
||||||
} else if (process.argv[2] == "--data") {
|
} else if (process.argv[2] == "--data") {
|
||||||
if (process.argv.length != 6)
|
if (process.argv.length < 6)
|
||||||
usage();
|
usage();
|
||||||
jsonFiles = process.argv[3].split(",");
|
jsonFiles = process.argv[3].split(",");
|
||||||
template = process.argv[4];
|
template = process.argv[4];
|
||||||
outputDir = process.argv[5];
|
outputDir = process.argv[5];
|
||||||
outputCommon = false;
|
outputCommon = false;
|
||||||
outputData = true;
|
outputData = true;
|
||||||
|
i = 6;
|
||||||
} else {
|
} else {
|
||||||
if (process.argv.length != 5)
|
if (process.argv.length < 5)
|
||||||
usage();
|
usage();
|
||||||
jsonFiles = process.argv[2].split(",");
|
jsonFiles = process.argv[2].split(",");
|
||||||
template = process.argv[3];
|
template = process.argv[3];
|
||||||
outputDir = process.argv[4];
|
outputDir = process.argv[4];
|
||||||
outputCommon = true;
|
outputCommon = true;
|
||||||
outputData = true;
|
outputData = true;
|
||||||
|
i = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
var overrides = [];
|
||||||
|
for (; i < process.argv.length; i++) {
|
||||||
|
var o = process.argv[i];
|
||||||
|
var r = o.match(/^([_a-zA-Z][_a-zA-Z0-9]*(\.[_a-zA-Z][_a-zA-Z0-9]*)*)=/);
|
||||||
|
if (!r)
|
||||||
|
usage();
|
||||||
|
var p = r[1].split(".");
|
||||||
|
var v = o.substring(r[0].length);
|
||||||
|
try {
|
||||||
|
v = JSON.parse(v);
|
||||||
|
} catch (e) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
overrides.push({ property: p, value: v });
|
||||||
}
|
}
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
@ -54,6 +93,13 @@ for (var i = 0; i < jsonFiles.length; i++) {
|
|||||||
for (var k in d)
|
for (var k in d)
|
||||||
data[k] = d[k];
|
data[k] = d[k];
|
||||||
}
|
}
|
||||||
|
for (var i = 0; i < overrides.length; i++) {
|
||||||
|
var p = data;
|
||||||
|
var o = overrides[i];
|
||||||
|
for (var j = 0; j < o.property.length - 1; j++)
|
||||||
|
p = p[o.property[j]];
|
||||||
|
p[o.property[o.property.length - 1]] = o.value;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (outputData) {
|
if (outputData) {
|
||||||
@ -69,39 +115,30 @@ var doT = require("dot");
|
|||||||
doT.templateSettings.strip = false;
|
doT.templateSettings.strip = false;
|
||||||
|
|
||||||
var api = {
|
var api = {
|
||||||
// https://coderrocketfuel.com/article/recursively-list-all-the-files-in-a-directory-using-node-js
|
generateFileFromTemplateFile: function (templateFile, outFile, data, mode) {
|
||||||
getAllFiles: function (dirPath, arrayOfFiles, relDir) {
|
|
||||||
var files = fs.readdirSync(dirPath);
|
|
||||||
|
|
||||||
var arrayOfFiles = arrayOfFiles || [];
|
|
||||||
var relDir = relDir || "";
|
|
||||||
|
|
||||||
files.forEach(function(file) {
|
|
||||||
if (fs.statSync(dirPath + path.sep + file).isDirectory())
|
|
||||||
arrayOfFiles = api.getAllFiles(dirPath + path.sep + file, arrayOfFiles, relDir + file + path.sep);
|
|
||||||
else
|
|
||||||
arrayOfFiles.push(relDir + file);
|
|
||||||
});
|
|
||||||
|
|
||||||
return arrayOfFiles
|
|
||||||
},
|
|
||||||
|
|
||||||
generateFileFromTemplateFile: function (templateFile, outFile, data) {
|
|
||||||
if (!outputData)
|
if (!outputData)
|
||||||
return;
|
return;
|
||||||
var dir = outputDir + path.sep + path.dirname(outFile);
|
var dir = outputDir + path.sep + path.dirname(outFile);
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
var t = doT.template(fs.readFileSync(template + path.sep + templateFile, { encoding: "utf-8" }));
|
var t = doT.template(fs.readFileSync(template + path.sep + templateFile, { encoding: "utf-8" }));
|
||||||
fs.writeFileSync(outputDir + path.sep + outFile, t(data), { encoding: "utf-8" });
|
var outputFile = outputDir + path.sep + outFile;
|
||||||
|
fs.writeFileSync(outputFile, t(data), { encoding: "utf-8" });
|
||||||
|
if (mode !== undefined)
|
||||||
|
fs.chmodSync(outputFile, mode);
|
||||||
},
|
},
|
||||||
|
|
||||||
copyFile: function (inFile, outFile) {
|
copyFile: function (inFile, outFile, mode) {
|
||||||
if (!outputCommon)
|
if (!outputCommon)
|
||||||
return;
|
return;
|
||||||
var dir = outputDir + path.sep + path.dirname(outFile);
|
var dir = outputDir + path.sep + path.dirname(outFile);
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
fs.copyFileSync(template + path.sep + inFile, outputDir + path.sep + outFile);
|
var outputFile = outputDir + path.sep + outFile;
|
||||||
}
|
fs.copyFileSync(template + path.sep + inFile, outputFile);
|
||||||
|
if (mode !== undefined)
|
||||||
|
fs.chmodSync(outputFile, mode);
|
||||||
|
},
|
||||||
|
|
||||||
|
templateDir: template
|
||||||
};
|
};
|
||||||
|
|
||||||
data.tibia = {
|
data.tibia = {
|
||||||
@ -145,6 +182,13 @@ data.tibia = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
},
|
||||||
|
|
||||||
|
sdbm: function (s) {
|
||||||
|
var hash = 0;
|
||||||
|
for (var i = 0; i < s.length; i++)
|
||||||
|
hash = s.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
|
||||||
|
return hash >>> 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user