Compare commits
No commits in common. "main" and "v0.0.1" have entirely different histories.
@ -20,7 +20,7 @@ Feel free to try it out anyway and perhaps give us some feedback (we'd appreciat
|
||||
|
||||
## Legal
|
||||
|
||||
Copyright (C) 2021-2025 Orastron Srl unipersonale.
|
||||
Copyright (C) 2021-2024 Orastron Srl unipersonale.
|
||||
|
||||
Authors: Stefano D'Angelo, Paolo Marrone.
|
||||
|
||||
|
46
notes
46
notes
@ -5,21 +5,18 @@ company {
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
url:
|
||||
VST3: PFactoryInfo.url
|
||||
LV2: manifest.ttl doap:maintainer rdfs:seeAlso
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
email:
|
||||
VST3: PFactoryInfo.email
|
||||
LV2: manifest.ttl doap:maintainer foaf:mbox
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
}
|
||||
|
||||
product {
|
||||
@ -29,28 +26,24 @@ product {
|
||||
web: web-demo <title> and <h1>
|
||||
cmd: not used
|
||||
android: index.html <title>, AndroidManifest.xml <application> <activity> android:label
|
||||
ios: index.html <title>
|
||||
version:
|
||||
VST3: PClassInfo{2,W}.version (first 3 numbers)
|
||||
LV2: not used
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
buildVersion:
|
||||
VST3: PClassInfo{2,W}.version (last number)
|
||||
LV2: not used
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
bundleName:
|
||||
VST3: plugin folder name, plugin .dll name, Info.plist
|
||||
LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary
|
||||
web: registerProcessor(), output file names
|
||||
cmd: executable file name
|
||||
android: .so/.apk filenames
|
||||
ios: xcodegen name and target name, xcodeproj filename
|
||||
buses: [
|
||||
{
|
||||
name:
|
||||
@ -60,7 +53,6 @@ product {
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
shortName:
|
||||
bus short name string, required
|
||||
VST3: not used
|
||||
@ -68,15 +60,6 @@ product {
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
id:
|
||||
bus unique id string, required
|
||||
VST3; not used
|
||||
LV2: manifest.ttl lv2:port lv2:symbol (resulting ports can have _l or _r appended)
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
direction:
|
||||
"input" or "output", required
|
||||
VST3: BusInfo flags - lots of implications
|
||||
@ -84,7 +67,6 @@ product {
|
||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
type:
|
||||
"audio" or "midi", required
|
||||
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
||||
@ -92,7 +74,6 @@ product {
|
||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
channels:
|
||||
"mono" or "stereo", audio type only, required
|
||||
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
||||
@ -100,7 +81,6 @@ product {
|
||||
web: AudioWorkletNode.outputChannelCount - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
sidechain:
|
||||
bus is not part of main audio path (sidechain)? boolean, default false
|
||||
VST3: BusInfo busType
|
||||
@ -115,7 +95,6 @@ product {
|
||||
web: web-demo choice of audio I/O buses
|
||||
cmd: choice of audio I/O buses
|
||||
android: choice of audio I/O buses
|
||||
ios: choice of audio I/O buses
|
||||
control:
|
||||
bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false
|
||||
VST3: not used
|
||||
@ -123,7 +102,6 @@ product {
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
optional:
|
||||
bus is optionally connected? boolean, default false
|
||||
VST3: BusInfo flags, plugin initialize, activate bus, set active
|
||||
@ -131,7 +109,6 @@ product {
|
||||
web: not used
|
||||
cmd: whether to pass NULLs if not chosen audio I/O buses
|
||||
android: whether to pass NULLs if not chosen audio I/O buses
|
||||
ios: whether to pass NULLs if not chosen audio I/O buses
|
||||
}
|
||||
]
|
||||
parameters: [
|
||||
@ -143,7 +120,6 @@ product {
|
||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <label>
|
||||
cmd: not used
|
||||
android: index.html <label>
|
||||
ios: index.html <label>
|
||||
shortName:
|
||||
parameter short name string, required
|
||||
VST3: ParameterInfo shortTitle
|
||||
@ -151,15 +127,6 @@ product {
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
id:
|
||||
parameter unique id string, required
|
||||
VST3; not used
|
||||
LV2: manifest.ttl lv2:port lv2:symbol (bypass ports used "enabled")
|
||||
web: not used
|
||||
cmd: command line parameter name etc.
|
||||
android: not used
|
||||
ios: not used
|
||||
direction:
|
||||
"input" or "output", required
|
||||
VST3: ParameterInfo flags - lots of implications
|
||||
@ -167,7 +134,6 @@ product {
|
||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
||||
cmd: lots of places
|
||||
android: lots of places
|
||||
ios: lots of places
|
||||
isBypass:
|
||||
parameter is bypass/enabled? boolean - lots of implications, default false
|
||||
VST3: ParameterInfo, controller get/set parameter/state
|
||||
@ -175,7 +141,6 @@ product {
|
||||
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
|
||||
cmd: set parameter
|
||||
android: JNI set parameter, index.html <range> min/max/step
|
||||
ios: native set parameter, index.html <range> min/max/step
|
||||
isLatency:
|
||||
parameter is latency output? boolean - lots of implications, default false
|
||||
VST3: TBD
|
||||
@ -183,7 +148,6 @@ product {
|
||||
web: not (yet) used
|
||||
cmd: not (yet) used
|
||||
android: not (yet) used
|
||||
ios: not (yet) used
|
||||
defaultValue:
|
||||
default value, number, mapped, required for non-bypass
|
||||
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
||||
@ -191,7 +155,6 @@ product {
|
||||
web: AudioWorkletProcessor.parameterDescriptors, processor_new(), web-demo initial <range> value and value <span> innerText
|
||||
cmd: default parameter value
|
||||
android: JNI set parameter initial value, index.html initial <range> value
|
||||
ios: native set parameter initial value, index.html initial <range> value
|
||||
minimum:
|
||||
minimum value, number, mapped, required for non-bypass
|
||||
VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped)
|
||||
@ -199,7 +162,6 @@ product {
|
||||
web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping
|
||||
cmd: set parameter (value clamped)
|
||||
android: JNI set parameter (value clamped), index.html <range> mapping
|
||||
ios: native set parameter (value clamped), index.html <range> mapping
|
||||
maximum:
|
||||
maximum value, number, mapped, required for non-bypass
|
||||
VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped)
|
||||
@ -207,7 +169,6 @@ product {
|
||||
web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping
|
||||
cmd: set parameter (value clamped)
|
||||
android: JNI set parameter (value clamped), index.html <range> mapping
|
||||
ios: native set parameter (value clamped), index.html <range> mapping
|
||||
toggled:
|
||||
parameter is on/off? boolean, default false
|
||||
VST3: ParameterInfo stepCount, controller set parameter/state
|
||||
@ -215,7 +176,6 @@ product {
|
||||
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
|
||||
cmd: set parameter
|
||||
android: JNI set parameter, index.html <range> min/max/step
|
||||
ios: native set parameter, index.html <range> min/max/step
|
||||
optional:
|
||||
parameter is optionally connected? boolean, default false
|
||||
VST3: not used
|
||||
@ -223,7 +183,6 @@ product {
|
||||
web: not used
|
||||
cmd: not used
|
||||
android: not used
|
||||
ios: not used
|
||||
integer:
|
||||
parameter values are integers? boolean, default false
|
||||
VST3: ParameterInfo stepCount, controller set parameter/state
|
||||
@ -231,7 +190,6 @@ product {
|
||||
web: AudoWorkletProcessor.process(), web-demo <range> step
|
||||
cmd: set parameter
|
||||
android: JNI set parameter, index.html <range> step
|
||||
ios: native set parameter, index.html <range> step
|
||||
scalePoints:
|
||||
{ "label1": value1, "label2", value2, ... }
|
||||
labeled values, default none
|
||||
@ -240,7 +198,6 @@ product {
|
||||
web: not (yet) used
|
||||
cmd: not (yet) used
|
||||
android: not (yet) used
|
||||
ios: not (yet) used
|
||||
list:
|
||||
parameter is a list (using scalePoints values)? default false
|
||||
VST3: TBD (+approx to closest?)
|
||||
@ -248,7 +205,6 @@ product {
|
||||
web: TBD (approx to closest? dropdown? both?)
|
||||
cmd: not (yet) used
|
||||
android: not (yet) used
|
||||
ios: not (yet) used
|
||||
unit:
|
||||
unit of measure (from predefined list, see tibia-index.js), default ""
|
||||
VST3: ParameterInfo units
|
||||
@ -256,7 +212,6 @@ product {
|
||||
web: web-demo value <span> innerText
|
||||
cmd: not (yet) used
|
||||
android: not (yet) used
|
||||
ios: not (yet) used
|
||||
map:
|
||||
"linear" vs "logarithmic"
|
||||
VST3: many places (requires libm)
|
||||
@ -264,7 +219,6 @@ product {
|
||||
web: web-demo <range> values
|
||||
cmd: not used
|
||||
android: index.html <range> values
|
||||
ios: index.html <range> values
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -18,143 +18,104 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := android
|
||||
|
||||
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
|
||||
else
|
||||
MIN_API := 26
|
||||
endif
|
||||
|
||||
NDK_DIR := $(SDK_DIR)/ndk/$(NDK_VERSION)
|
||||
BUILD_TOOLS_DIR := $(SDK_DIR)/build-tools/$(BUILD_TOOLS_VERSION)
|
||||
CC = ${ANDROID_NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi${MIN_API}-clang
|
||||
CXX = ${ANDROID_NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi${MIN_API}-clang++
|
||||
JC = javac
|
||||
|
||||
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
|
||||
|
||||
APKSIGNER := $(BUILD_TOOLS_DIR)/apksigner
|
||||
ZIPALIGN := $(BUILD_TOOLS_DIR)/zipalign
|
||||
AAPT := $(BUILD_TOOLS_DIR)/aapt
|
||||
D8 := $(BUILD_TOOLS_DIR)/d8
|
||||
ADB := $(SDK_DIR)/platform-tools/adb
|
||||
APKSIGNER = ${BUILD_TOOLS_DIR}/apksigner
|
||||
ZIPALIGN = ${BUILD_TOOLS_DIR}/zipalign
|
||||
AAPT = ${BUILD_TOOLS_DIR}/aapt
|
||||
D8 = ${BUILD_TOOLS_DIR}/d8
|
||||
ADB = ${ANDROID_SDK_DIR}/platform-tools/adb
|
||||
|
||||
JARS := \
|
||||
$(ANDROID_JAR_FILE) \
|
||||
$(ANDROIDX_CORE_FILE) \
|
||||
$(ANDROIDX_LIFECYCLE_COMMON_FILE) \
|
||||
$(ANDROIDX_VERSIONEDPARCELABLE_FILE) \
|
||||
$(KOTLIN_STDLIB_FILE) \
|
||||
$(KOTLINX_COROUTINES_CORE_FILE) \
|
||||
$(KOTLINX_COROUTINES_CORE_JVM_FILE)
|
||||
${ANDROID_JAR_FILE} \
|
||||
${ANDROIDX_CORE_FILE} \
|
||||
${ANDROIDX_LIFECYCLE_COMMON_FILE} \
|
||||
${ANDROIDX_VERSIONEDPARCELABLE_FILE} \
|
||||
${KOTLIN_STDLIB_FILE} \
|
||||
${KOTLINX_COROUTINES_CORE_FILE} \
|
||||
${KOTLINX_COROUTINES_CORE_JVM_FILE}
|
||||
|
||||
CLASSES_PATH := $(subst .,/,$(JAVA_PACKAGE_NAME))
|
||||
|
||||
CLASSES := \
|
||||
MainActivity \
|
||||
MainActivity$$WebAppInterface
|
||||
ifeq ($(HAS_MIDI_IN), yes)
|
||||
ifeq (${HAS_MIDI_IN}, yes)
|
||||
CLASSES += MainActivity$$WebAppInterface$$MidiDeviceCallback MainActivity$$WebAppInterface$$1
|
||||
endif
|
||||
|
||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CFLAGS_EXTRA) $(CFLAGS)
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -std=c++11 $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||
CFLAGS = -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CFLAGS} ${CFLAGS_EXTRA}
|
||||
|
||||
LDFLAGS :=
|
||||
LDFLAGS_ALL := -shared -static-libstdc++ -landroid
|
||||
ifeq ($(HAS_MIDI_IN), yes)
|
||||
CXXFLAGS = ${CFLAGS}
|
||||
CXXFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC -std=c++11 ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||
|
||||
LDFLAGS =
|
||||
LDFLAGS_ALL = -shared -static-libstdc++ -landroid
|
||||
ifeq (${HAS_MIDI_IN}, yes)
|
||||
LDFLAGS += -lamidi
|
||||
endif
|
||||
LDFLAGS_ALL += $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||
LDFLAGS_ALL += ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||
|
||||
JFLAGS :=
|
||||
JFLAGS_ALL := $(JFLAGS_EXTRA) $(JFLAGS)
|
||||
JFLAGS =
|
||||
JFLAGS_ALL = ${JFLAGS} ${JFLAGS_EXTRA}
|
||||
|
||||
C_SRCS := $(C_SRCS_EXTRA)
|
||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
C_SRCS = ${C_SRCS_EXTRA}
|
||||
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
|
||||
CXX_SRCS := $(COMMON_DIR)/src/jni.cpp $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
CXX_SRCS = ${COMMON_DIR}/src/jni.cpp ${CXX_SRCS_EXTRA}
|
||||
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
|
||||
build/${BUNDLE_NAME}.apk: build/gen/${BUNDLE_NAME}.aligned.apk ${KEY_STORE}
|
||||
${APKSIGNER} sign --ks ${KEY_STORE} --ks-key-alias ${KEY_ALIAS} --ks-pass pass:${STORE_PASS} --key-pass pass:${KEY_PASS} --out $@ build/gen/${BUNDLE_NAME}.aligned.apk
|
||||
|
||||
-include $(MKINC_DIR)/vars-extra.mk
|
||||
build/gen/${BUNDLE_NAME}.aligned.apk: build/gen/${BUNDLE_NAME}.unsigned.apk
|
||||
${ZIPALIGN} -f -p 4 $^ $@
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
build/$(BUNDLE_NAME).apk: build/gen/$(BUNDLE_NAME).aligned.apk $(KEY_STORE)
|
||||
$(APKSIGNER) sign --ks $(KEY_STORE) --ks-key-alias $(KEY_ALIAS) --ks-pass pass:$(STORE_PASS) --key-pass pass:$(KEY_PASS) --out $@ build/gen/$(BUNDLE_NAME).aligned.apk
|
||||
|
||||
build/gen/$(BUNDLE_NAME).aligned.apk: build/gen/$(BUNDLE_NAME).unsigned.apk
|
||||
$(ZIPALIGN) -f -p 4 $^ $@
|
||||
|
||||
build/gen/$(BUNDLE_NAME).unsigned.apk: build/apk/classes.dex build/apk/lib/armeabi-v7a/lib$(BUNDLE_NAME).so $(DATA_DIR)/data/AndroidManifest.xml build/assets/index.html | build/gen
|
||||
$(AAPT) package -f -M $(DATA_DIR)/data/AndroidManifest.xml -A build/assets $(foreach jar,$(JARS),-I $(jar)) -F $@ build/apk
|
||||
build/gen/${BUNDLE_NAME}.unsigned.apk: build/apk/classes.dex build/apk/lib/armeabi-v7a/lib${BUNDLE_NAME}.so ${DATA_DIR}/data/AndroidManifest.xml build/assets/index.html | build/gen
|
||||
${AAPT} package -f -M ${DATA_DIR}/data/AndroidManifest.xml -A build/assets $(foreach jar,$(JARS),-I $(jar)) -F $@ build/apk
|
||||
|
||||
build/apk/classes.dex: build/apk/my_classes.jar
|
||||
cd build/apk && $(D8) --min-api $(MIN_API) ../../$^ $(JARS) && cd ../..
|
||||
cd build/apk && ${D8} --min-api ${MIN_API} ../../$^ ${JARS} && cd ../..
|
||||
|
||||
build/apk/my_classes.jar: $(foreach class,$(CLASSES),build/obj/$(CLASSES_PATH)/$(class).class) | build/apk
|
||||
@echo $(CLASSES_PATH)
|
||||
$(D8) $(foreach class,$(CLASSES),'build/obj/$(CLASSES_PATH)/$(class).class') --min-api $(MIN_API) --output $@ --no-desugaring
|
||||
@echo ${CLASSES_PATH}
|
||||
${D8} $(foreach class,$(CLASSES),'build/obj/$(CLASSES_PATH)/$(class).class') --min-api ${MIN_API} --output $@ --no-desugaring
|
||||
|
||||
build/obj/$(CLASSES_PATH)/MainActivity.class: $(DATA_DIR)/src/MainActivity.java | build/obj
|
||||
$(JC) $(JFLAGS_ALL) -classpath "$(subst $() $(),:,$(JARS))" -d build/obj $^
|
||||
build/obj/${CLASSES_PATH}/MainActivity.class: ${DATA_DIR}/src/MainActivity.java | build/obj
|
||||
${JC} ${JFLAGS_ALL} -classpath "$(subst $() $(),:,$(JARS))" -d build/obj $^
|
||||
|
||||
build/apk/lib/armeabi-v7a/lib$(BUNDLE_NAME).so: $(C_OBJS) $(CXX_OBJS) | build/apk/lib/armeabi-v7a
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/apk/lib/armeabi-v7a/lib${BUNDLE_NAME}.so: ${C_OBJS} ${CXX_OBJS} | build/apk/lib/armeabi-v7a
|
||||
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
|
||||
build/assets/index.html: $(DATA_DIR)/src/index.html | build/assets
|
||||
build/assets/index.html: ${DATA_DIR}/src/index.html | build/assets
|
||||
cp $^ $@
|
||||
|
||||
$(DIRS):
|
||||
build/gen build/apk build/obj build/apk/lib/armeabi-v7a build/assets:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
install: build/$(BUNDLE_NAME).apk
|
||||
[ -n "`$(ADB) shell pm list packages | grep ^package:$(JAVA_PACKAGE_NAME)`" ] && $(ADB) uninstall $(JAVA_PACKAGE_NAME); exit 0
|
||||
$(ADB) install $^
|
||||
|
||||
-include $(MKINC_DIR)/rules-extra.mk
|
||||
install: build/${BUNDLE_NAME}.apk
|
||||
[ -n "`${ADB} shell pm list packages | grep ^package:${JAVA_PACKAGE_NAME}`" ] && ${ADB} uninstall ${JAVA_PACKAGE_NAME}; exit 0
|
||||
${ADB} install $^
|
||||
|
||||
.PHONY: all clean install
|
||||
|
||||
@ -163,9 +124,7 @@ install: build/$(BUNDLE_NAME).apk
|
||||
PERCENT := %
|
||||
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||
|
@ -20,29 +20,36 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
||||
ANDROID_VERSION := {{=it.android.androidVersion}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.android_make?.pluginDir || it.make?.pluginDir)}}
|
||||
PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.android_make?.apiDir || it.make?.apiDir)}}
|
||||
API_DIR := {{=it.android_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.android_make?.mkincDir || it.make?.mkincDir)}}
|
||||
MKINC_DIR := {{=it.android_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||
{{?}}
|
||||
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.android_make && it.android_make.cflags ? it.android_make.cflags : ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.android_make && it.android_make.cxxflags ? it.android_make.cxxflags : ""}}
|
||||
JFLAGS_EXTRA := {{=it.make && it.make.jflags ? it.make.jflags : ""}} {{=it.android_make && it.android_make.jflags ? it.android_make.jflags : ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.android_make && it.android_make.ldflags ? it.android_make.ldflags : ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.android_make && it.android_make.cSrcs ? it.android_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.android_make && it.android_make.cxxSrcs ? it.android_make.cxxSrcs : ""}}
|
||||
|
||||
COMMON_DIR := {{=it.android_make && it.android_make.commonDir ? it.android_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.android_make && it.android_make.dataDir ? it.android_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.android_make && it.android_make.pluginDir ? it.android_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
|
||||
KEY_STORE := {{=it.android_make.keyStore}}
|
||||
KEY_ALIAS := {{=it.android_make.keyAlias}}
|
||||
STORE_PASS := {{=it.android_make.storePass}}
|
||||
KEY_PASS := {{=it.android_make.keyPass}}
|
||||
|
||||
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"}}
|
||||
|
||||
{{?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:targetSdkVersion="{{=it.android.androidVersion}}" />
|
||||
<uses-sdk android:targetSdkVersion="34" />
|
||||
<application android:label="{{=it.product.name}}">
|
||||
<activity android:name=".MainActivity" android:label="{{=it.product.name}}" android:exported="true">
|
||||
<intent-filter>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -83,7 +83,3 @@ static struct {
|
||||
#endif
|
||||
|
||||
#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
|
||||
*
|
||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
* Copyright (C) 2023, 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
|
||||
@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -189,10 +188,6 @@ JNIEXPORT jboolean JNICALL
|
||||
JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
||||
(void)env;
|
||||
(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 == 0
|
||||
@ -230,13 +225,7 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
|
||||
return false;
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ NULL,
|
||||
/* .format = */ "android",
|
||||
/* .get_bindir = */ NULL,
|
||||
/* .get_datadir = */ NULL
|
||||
};
|
||||
plugin_init(&instance, &cbs);
|
||||
plugin_init(&instance);
|
||||
|
||||
#if PARAMETERS_N > 0
|
||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_API_H
|
||||
#define PLUGIN_API_H
|
||||
|
||||
typedef struct {
|
||||
void * handle;
|
||||
const char * format;
|
||||
const char * (*get_bindir)(void *handle);
|
||||
const char * (*get_datadir)(void *handle);
|
||||
} plugin_callbacks;
|
||||
|
||||
{{?it.product.state && it.product.state.dspCustom}}
|
||||
typedef struct {
|
||||
void * handle;
|
||||
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;
|
||||
{{?}}
|
||||
|
||||
typedef struct {
|
||||
void * handle;
|
||||
const char * format;
|
||||
const char * (*get_bindir)(void *handle);
|
||||
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;
|
||||
|
||||
{{?it.product.parameters.length > 0}}
|
||||
enum {
|
||||
{{~it.product.parameters :p}}
|
||||
plugin_parameter_{{=p.id}},
|
||||
{{~}}
|
||||
plugin_parameter__count
|
||||
};
|
||||
{{?}}
|
||||
|
||||
#endif
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
var path = require("path");
|
||||
var sep = path.sep;
|
||||
|
||||
module.exports = function (data, api) {
|
||||
api.generateFileFromTemplateFile(`src${sep}plugin_api.h`, `plugin_api.h`, data);
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Tibia
|
||||
#
|
||||
# Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
# 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
|
||||
@ -18,114 +18,85 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := cmd
|
||||
|
||||
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)
|
||||
EXE_SUFFIX := .exe
|
||||
EXE_SUFFIX = .exe
|
||||
else
|
||||
UNAME_S := $(shell uname -s)
|
||||
EXE_SUFFIX :=
|
||||
PREFIX := /usr/local
|
||||
BINDIR := $(PREFIX)/bin
|
||||
UNAME_S = $(shell uname -s)
|
||||
EXE_SUFFIX =
|
||||
PREFIX = /usr/local
|
||||
BINDIR = ${PREFIX}/bin
|
||||
endif
|
||||
|
||||
TINYWAV_DIR ?= ../tinywav
|
||||
MIDI_PARSER_DIR ?= ../midi-parser
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
CC := gcc
|
||||
CXX := g++
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
|
||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include $(CFLAGS_EXTRA) $(CFLAGS)
|
||||
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}
|
||||
|
||||
LDFLAGS :=
|
||||
LDFLAGS_ALL := $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||
LDFLAGS =
|
||||
LDFLAGS_ALL = ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||
CXXFLAGS = ${CFLAGS}
|
||||
CXXFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -I${TINYWAV_DIR} -I${MIDI_PARSER_DIR}/include -fPIC ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
CFLAGS_ALL := ${CFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
LDFLAGS_ALL := ${LDFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
CXXFLAGS_ALL := ${CXXFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
endif
|
||||
|
||||
PROGRAM := $(BUNDLE_NAME)$(EXE_SUFFIX)
|
||||
PROGRAM = ${BUNDLE_NAME}${EXE_SUFFIX}
|
||||
|
||||
C_SRCS := $(COMMON_DIR)/src/main.c $(C_SRCS_EXTRA)
|
||||
C_SRCS = ${COMMON_DIR}/src/main.c ${C_SRCS_EXTRA}
|
||||
ifeq ($(HAS_MIDI_IN), yes)
|
||||
C_SRCS := $(C_SRCS) $(MIDI_PARSER_DIR)/src/midi-parser.c
|
||||
C_SRCS += ${MIDI_PARSER_DIR}/src/midi-parser.c
|
||||
endif
|
||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
|
||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
CXX_SRCS = ${CXX_SRCS_EXTRA}
|
||||
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
|
||||
DIRS := build build/obj
|
||||
|
||||
ALL := build/$(PROGRAM)
|
||||
|
||||
STRIP_ALL := build/$(PROGRAM)
|
||||
STRIP_PHONY :=
|
||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
||||
|
||||
-include $(MKINC_DIR)/vars-extra.mk
|
||||
|
||||
all: $(ALL)
|
||||
all: build/${PROGRAM}
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/$(PROGRAM): $(C_OBJS) build/obj/tinywav.o | build
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/${PROGRAM}: ${C_OBJS} build/obj/tinywav.o | build
|
||||
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
else
|
||||
build/$(PROGRAM): $(C_OBJS) $(CXX_OBJS) build/obj/tinywav.o | build
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/${PROGRAM}: ${C_OBJS} ${CXX_OBJS} build/obj/tinywav.o | build
|
||||
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
endif
|
||||
|
||||
$(DIRS):
|
||||
build build/obj:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
strip: $(STRIP_PREREQS)
|
||||
strip build/$(PROGRAM)
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
.PHONY: all clean strip $(STRIP_PHONY)
|
||||
.PHONY: all clean
|
||||
else
|
||||
install: all
|
||||
mkdir -m 0755 -p $(BINDIR)
|
||||
install -m 0755 build/$(PROGRAM) $(BINDIR)
|
||||
mkdir -p -m 0755 ${BINDIR}
|
||||
install -m 0755 build/${PROGRAM} ${BINDIR}
|
||||
|
||||
.PHONY: all clean strip $(STRIP_PHONY) install
|
||||
.PHONY: all clean install
|
||||
endif
|
||||
|
||||
-include $(MKINC_DIR)/rules-extra.mk
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
PERCENT := %
|
||||
|
||||
build/obj/tinywav.o: $(TINYWAV_DIR)/tinywav.c
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL) -Wno-unused-result
|
||||
build/obj/tinywav.o: ${TINYWAV_DIR}/tinywav.c
|
||||
${CC} $^ -o $@ -c ${CFLAGS_ALL} -Wno-unused-result
|
||||
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||
|
@ -20,27 +20,18 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.cmd_make?.pluginDir || it.make?.pluginDir)}}
|
||||
PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.cmd_make?.apiDir || it.make?.apiDir)}}
|
||||
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 ?? "")}}
|
||||
{{?}}
|
||||
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.cmd_make.cflags ? it.cmd_make.cflags : ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.cmd_make.cxxflags ? it.cmd_make.cxxflags : ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.cmd_make.ldflags ? it.cmd_make.ldflags : ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.cmd_make && it.cmd_make.cSrcs ? it.cmd_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.cmd_make && it.cmd_make.cxxSrcs ? it.cmd_make.cxxSrcs : ""}}
|
||||
|
||||
COMMON_DIR := {{=it.cmd_make && it.cmd_make.commonDir ? it.cmd_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.cmd_make && it.cmd_make.dataDir ? it.cmd_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.cmd_make && it.cmd_make.pluginDir ? it.cmd_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
|
||||
TINYWAV_DIR := {{=it.cmd_make.tinywavDir}}
|
||||
MIDI_PARSER_DIR := {{=it.cmd_make.midiParserDir}}
|
||||
|
||||
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
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -73,7 +73,7 @@ static struct {
|
||||
} param_data[PARAMETERS_N] = {
|
||||
{{~it.product.parameters :p:i}}
|
||||
{
|
||||
/* .id = */ "{{=p.id}}",
|
||||
/* .id = */ "{{=it.cmd.parameterIds[i]}}",
|
||||
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}}f,
|
||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||
@ -83,7 +83,3 @@ static struct {
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
{{?it.product.state && it.product.state.dspCustom}}
|
||||
#define STATE_DSP_CUSTOM
|
||||
{{?}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -162,11 +161,6 @@ float clampf(float x, float m, float M) {
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
#ifdef STATE_DSP_CUSTOM
|
||||
(void)plugin_state_load;
|
||||
(void)plugin_state_save;
|
||||
#endif
|
||||
|
||||
#if PARAMETERS_N > 0
|
||||
for (size_t i = 0; i < PARAMETERS_N; i++)
|
||||
param_values[i] = param_data[i].def;
|
||||
@ -358,13 +352,7 @@ int main(int argc, char * argv[]) {
|
||||
printf(" %s: %g\n", param_data[i].id, param_values[i]);
|
||||
#endif
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ NULL,
|
||||
/* .format = */ "cmd",
|
||||
/* .get_bindir = */ NULL,
|
||||
/* .get_datadir = */ NULL
|
||||
};
|
||||
plugin_init(&instance, &cbs);
|
||||
plugin_init(&instance);
|
||||
|
||||
#if PARAMETERS_N > 0
|
||||
for (size_t i = 0; i < PARAMETERS_N; i++)
|
||||
|
@ -18,32 +18,22 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := daisy-seed
|
||||
|
||||
include vars.mk
|
||||
|
||||
COMMON_DIR ?= .
|
||||
DATA_DIR ?= .
|
||||
PLUGIN_DIR ?= src
|
||||
API_DIR ?= $(PLUGIN_DIR)
|
||||
MKINC_DIR ?= $(COMMON_DIR)
|
||||
TARGET = ${BUNDLE_NAME}
|
||||
|
||||
-include $(MKINC_DIR)/vars-pre.mk
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
LIBDAISY_DIR ?= ../libDaisy
|
||||
CPP_SOURCES = ${COMMON_DIR}/src/main.cpp ${CXX_SRCS_EXTRA}
|
||||
|
||||
TARGET := $(BUNDLE_NAME)
|
||||
SYSTEM_FILES_DIR = ${LIBDAISY_DIR}/core
|
||||
|
||||
CPP_SOURCES := $(COMMON_DIR)/src/main.cpp $(CXX_SRCS_EXTRA)
|
||||
include ${SYSTEM_FILES_DIR}/Makefile
|
||||
|
||||
SYSTEM_FILES_DIR := $(LIBDAISY_DIR)/core
|
||||
C_SOURCES += ${C_SRCS_EXTRA}
|
||||
|
||||
include $(SYSTEM_FILES_DIR)/Makefile
|
||||
|
||||
C_SOURCES += $(C_SRCS_EXTRA)
|
||||
|
||||
CFLAGS += -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(CFLAGS_EXTRA)
|
||||
LDFLAGS += $(LDFLAGS_EXTRA)
|
||||
CXXFLAGS += -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(CXXFLAGS_EXTRA)
|
||||
|
||||
-include $(COMMON_DIR)/extra.mk
|
||||
CFLAGS += -I${DATA_DIR}/src -I${PLUGIN_DIR} ${CFLAGS_EXTRA}
|
||||
LDFLAGS += ${LDFLAGS_EXTRA}
|
||||
CXXFLAGS += -I${DATA_DIR}/src -I${PLUGIN_DIR} ${CXXFLAGS_EXTRA}
|
||||
|
@ -20,25 +20,14 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.daisy_seed_make.cflags ? it.daisy_seed_make.cflags : ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.daisy_seed_make.ldflags ? it.daisy_seed_make.ldflags : ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.daisy_seed_make.cxxflags ? it.daisy_seed_make.cxxflags : ""}}
|
||||
|
||||
{{?it.make?.extra}}
|
||||
{{=it.make.extra}}
|
||||
{{?}}
|
||||
{{?it.daisy_seed_make?.extra}}
|
||||
{{=it.daisy_seed_make.extra}}
|
||||
{{?}}
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.daisy_seed_make && it.daisy_seed_make.cSrcs ? it.daisy_seed_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.daisy_seed_make && it.daisy_seed_make.cxxSrcs ? it.daisy_seed_make.cxxSrcs : ""}}
|
||||
|
||||
COMMON_DIR := {{=it.daisy_seed_make && it.daisy_seed_make.commonDir ? it.daisy_seed_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.daisy_seed_make && it.daisy_seed_make.dataDir ? it.daisy_seed_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.daisy_seed_make && it.daisy_seed_make.pluginDir ? it.daisy_seed_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
LIBDAISY_DIR := {{=it.daisy_seed_make.libdaisyDir}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -98,7 +98,3 @@ static int midi_cc_maps[NUM_PARAMETERS] = { {{~it.daisy_seed.midiCCMaps :p}}{{=p
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
{{?it.product.state && it.product.state.dspCustom}}
|
||||
#define STATE_DSP_CUSTOM
|
||||
{{?}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
* Copyright (C) 2023, 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
|
||||
@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -150,11 +149,6 @@ static void AudioCallback(
|
||||
}
|
||||
|
||||
int main() {
|
||||
#ifdef STATE_DSP_CUSTOM
|
||||
(void)plugin_state_load;
|
||||
(void)plugin_state_save;
|
||||
#endif
|
||||
|
||||
hardware.Configure();
|
||||
hardware.Init();
|
||||
|
||||
@ -174,13 +168,7 @@ int main() {
|
||||
hardware.SetAudioBlockSize(BLOCK_SIZE);
|
||||
float sample_rate = hardware.AudioSampleRate();
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ NULL,
|
||||
/* .format = */ "daisy-seed",
|
||||
/* .get_bindir = */ NULL,
|
||||
/* .get_datadir = */ NULL
|
||||
};
|
||||
plugin_init(&instance, &cbs);
|
||||
plugin_init(&instance);
|
||||
|
||||
plugin_set_sample_rate(&instance, sample_rate);
|
||||
if (plugin_mem_req(&instance) != 0)
|
||||
|
@ -18,70 +18,34 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := ios
|
||||
|
||||
include vars.mk
|
||||
|
||||
COMMON_DIR ?= .
|
||||
DATA_DIR ?= .
|
||||
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) $(CFLAGS_EXTRA) $(CFLAGS)
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||
|
||||
LDFLAGS :=
|
||||
LDFLAGS_ALL := $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
SOURCES := \
|
||||
$(C_SRCS_EXTRA) \
|
||||
$(M_SRCS_EXTRA) \
|
||||
$(CXX_SRCS_EXTRA) \
|
||||
$(SRCS_EXTRA) \
|
||||
$(DATA_DIR)/src/data.h \
|
||||
$(COMMON_DIR)/src/app.swift \
|
||||
$(COMMON_DIR)/src/native.mm \
|
||||
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
||||
$(PLUGIN_DIR)/plugin.h \
|
||||
$(API_DIR)/plugin_api.h
|
||||
SOURCES_OUT := $(addprefix build/gen/src/, $(notdir $(SOURCES)))
|
||||
${DATA_DIR}/src/data.h \
|
||||
${DATA_DIR}/src/index.html \
|
||||
${COMMON_DIR}/src/app.swift \
|
||||
${COMMON_DIR}/src/native.mm \
|
||||
${COMMON_DIR}/src/app-Bridging-Header.h \
|
||||
${PLUGIN_DIR}/plugin.h \
|
||||
${C_SRCS_EXTRA} \
|
||||
${CXX_SRCS_EXTRA}
|
||||
SOURCES_OUT = $(addprefix build/gen/src/, $(notdir $(SOURCES)))
|
||||
|
||||
RESOURCES := $(PLUGIN_DIR)/index.html
|
||||
RESOURCES_OUT := $(addprefix build/gen/res/, $(notdir $(RESOURCES)))
|
||||
all: build/gen/${BUNDLE_NAME}.xcodeproj
|
||||
|
||||
DIRS := build build/gen build/gen/src build/gen/res
|
||||
build/gen/${BUNDLE_NAME}.xcodeproj: ${SOURCES_OUT}
|
||||
xcodegen generate --spec project.yml -r build/gen -p build/gen
|
||||
|
||||
ALL := build/gen/$(BUNDLE_NAME).xcodeproj
|
||||
|
||||
-include $(MKINC_DIR)/vars-extra.mk
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
build/gen/$(BUNDLE_NAME).xcodeproj: $(SOURCES_OUT) $(RESOURCES_OUT) build/project_out.yml
|
||||
xcodegen generate --spec build/project_out.yml -r build/gen -p build/gen
|
||||
|
||||
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):
|
||||
build/gen/src:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
-include $(MKINC_DIR)/rules-extra.mk
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
.SECONDEXPANSION:
|
||||
@ -89,9 +53,4 @@ clean:
|
||||
PERCENT := %
|
||||
|
||||
$(SOURCES_OUT): build/gen/src/%: $$(filter $$(PERCENT)/%,$$(SOURCES)) | build/gen/src
|
||||
cp -R $^ $@
|
||||
|
||||
$(RESOURCES_OUT): build/gen/res/%: $$(filter $$(PERCENT)/%,$$(RESOURCES)) | build/gen/res
|
||||
cp -R $^ $@
|
||||
|
||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||
cp $^ $@
|
||||
|
@ -21,35 +21,15 @@
|
||||
name: {{=it.product.bundleName}}
|
||||
targets:
|
||||
{{=it.product.bundleName}}:
|
||||
{{?it.ios_make.supportedDestinations}}
|
||||
supportedDestinations: {{=Array.isArray(it.ios_make.supportedDestinations) ? "[" + it.ios_make.supportedDestinations.toString() + "]" : it.ios_make.supportedDestinations}}
|
||||
{{??}}
|
||||
platform: [iOS]
|
||||
{{?}}
|
||||
deploymentTarget: "{{=it.ios_make.deploymentTarget}}"
|
||||
deploymentTarget:
|
||||
iOS: {{=it.ios_make.deploymentTarget}}
|
||||
type: application
|
||||
sources:
|
||||
- path: src
|
||||
- path: res
|
||||
type: folder
|
||||
|
||||
{{?it.ios_make.dependencies}}
|
||||
dependencies:
|
||||
{{~it.ios_make.dependencies :d}}
|
||||
- target: {{=d}}{{~}}
|
||||
{{?}}
|
||||
|
||||
settings:
|
||||
base:
|
||||
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
|
||||
{{?it.ios_make.headerSearchPaths}}
|
||||
HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}}
|
||||
@ -57,19 +37,7 @@ targets:
|
||||
{{?}}
|
||||
info:
|
||||
path: Info.plist
|
||||
{{?(it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length > 0) || it.ios_make.infoProperties || it.ios_make.uiLaunchScreen}}
|
||||
properties:
|
||||
{{?it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length > 0}}
|
||||
properties:
|
||||
NSMicrophoneUsageDescription: Need audio input for processing sound
|
||||
{{?}}
|
||||
{{?it.ios_make.infoProperties}}
|
||||
{{~it.ios_make.infoProperties :p}}
|
||||
{{=p.key}}: {{=Array.isArray(p.value) ? "[" + p.value.toString() + "]" : p.value}}
|
||||
{{~}}
|
||||
{{?}}
|
||||
{{?it.ios_make.launchScreen}}
|
||||
UILaunchScreen:
|
||||
UIColorName: {{=it.ios_make.launchScreen.colorName}}
|
||||
UIImageName: {{=it.ios_make.launchScreen.imageName}}
|
||||
{{?}}
|
||||
{{?}}
|
||||
|
@ -20,25 +20,9 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.ios_make && it.ios_make.cSrcs ? it.ios_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.ios_make && it.ios_make.cxxSrcs ? it.ios_make.cxxSrcs : ""}}
|
||||
|
||||
{{?it.make?.extra}}
|
||||
{{=it.make.extra}}
|
||||
{{?}}
|
||||
{{?it.ios_make?.extra}}
|
||||
{{=it.ios_make.extra}}
|
||||
{{?}}
|
||||
COMMON_DIR := {{=it.ios_make && it.ios_make.commonDir ? it.ios_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.ios_make && it.ios_make.dataDir ? it.ios_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.ios_make && it.ios_make.pluginDir ? it.ios_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
|
@ -20,7 +20,5 @@
|
||||
|
||||
char audioStart();
|
||||
void audioStop();
|
||||
void audioPause();
|
||||
void audioResume();
|
||||
void setParameter(int i, float v);
|
||||
float getParameter(int i);
|
||||
|
@ -19,11 +19,11 @@
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
@preconcurrency import WebKit
|
||||
import WebKit
|
||||
import AVFoundation
|
||||
|
||||
struct WebView: UIViewRepresentable {
|
||||
class Coordinator: NSObject, WKScriptMessageHandlerWithReply, WKNavigationDelegate {
|
||||
class Coordinator: NSObject, WKScriptMessageHandlerWithReply {
|
||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
|
||||
guard let body = message.body as? [String : Any] else { return }
|
||||
guard let name = body["name"] as? String else { return }
|
||||
@ -57,15 +57,6 @@ struct WebView: UIViewRepresentable {
|
||||
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 {
|
||||
@ -76,11 +67,9 @@ struct WebView: UIViewRepresentable {
|
||||
|
||||
func makeUIView(context: Context) -> WKWebView {
|
||||
let configuration = WKWebViewConfiguration()
|
||||
configuration.userContentController.addScriptMessageHandler(Coordinator(), contentWorld: .page, name: "messageHandler")
|
||||
configuration.setValue(true, forKey: "allowUniversalAccessFromFileURLs")
|
||||
configuration.userContentController.addScriptMessageHandler(Coordinator(), contentWorld: .page, name: "listener")
|
||||
let webView = WKWebView(frame: .zero, configuration: configuration)
|
||||
webView.navigationDelegate = context.coordinator
|
||||
//webView.isInspectable = true
|
||||
webView.isInspectable = true
|
||||
return webView
|
||||
}
|
||||
|
||||
@ -92,8 +81,8 @@ struct WebView: UIViewRepresentable {
|
||||
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "res")
|
||||
WebView(url: url!).ignoresSafeArea().preferredColorScheme(.dark)
|
||||
let url = Bundle.main.url(forResource: "index", withExtension: "html")
|
||||
WebView(url: url!)
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,12 +97,6 @@ struct templateApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
|
||||
audioPause()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
||||
audioResume()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -81,7 +81,3 @@ static struct {
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
{{?it.product.state && it.product.state.dspCustom}}
|
||||
#define STATE_DSP_CUSTOM
|
||||
{{?}}
|
||||
|
@ -26,7 +26,7 @@
|
||||
<title>{{=it.product.name}}</title>
|
||||
<script type="text/javascript">
|
||||
function request(data) {
|
||||
return window.webkit.messageHandlers.messageHandler.postMessage(data);
|
||||
return window.webkit.messageHandlers.listener.postMessage(data);
|
||||
}
|
||||
|
||||
function needAudioPermission() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
* Copyright (C) 2023, 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
|
||||
@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#include "plugin.h"
|
||||
#if PARAMETERS_N > 0
|
||||
#include <algorithm>
|
||||
@ -37,8 +36,6 @@
|
||||
#define BLOCK_SIZE 32
|
||||
|
||||
static ma_device device;
|
||||
static ma_device_config deviceConfig;
|
||||
char device_inited = 0;
|
||||
static plugin instance;
|
||||
static void * mem;
|
||||
#if NUM_NON_OPT_CHANNELS_IN > NUM_CHANNELS_IN
|
||||
@ -190,21 +187,16 @@ void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^(
|
||||
|
||||
extern "C"
|
||||
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 == 0
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
# elif NUM_CHANNELS_OUT == 0
|
||||
deviceConfig = ma_device_config_init(ma_device_type_capture);
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_capture);
|
||||
# else
|
||||
deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
||||
# endif
|
||||
#else
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
#endif
|
||||
|
||||
deviceConfig.periodSizeInFrames = BLOCK_SIZE;
|
||||
@ -258,13 +250,7 @@ char audioStart() {
|
||||
}
|
||||
#endif
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ NULL,
|
||||
/* .format = */ "ios",
|
||||
/* .get_bindir = */ NULL,
|
||||
/* .get_datadir = */ NULL
|
||||
};
|
||||
plugin_init(&instance, &cbs);
|
||||
plugin_init(&instance);
|
||||
|
||||
#if PARAMETERS_N > 0
|
||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||
@ -342,9 +328,6 @@ char audioStart() {
|
||||
ma_device_uninit(&device);
|
||||
return false;
|
||||
}
|
||||
|
||||
device_inited = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -358,23 +341,6 @@ void audioStop() {
|
||||
// No need to close MIDI connections (e.g. via MIDIClientDispose), the system terminates them when the app terminates.
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void audioPause() {
|
||||
if (device_inited) {
|
||||
ma_device_stop(&device);
|
||||
ma_device_uninit(&device);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void audioResume() {
|
||||
// TODO: could this fail?...
|
||||
if (device_inited) {
|
||||
ma_device_init(NULL, &deviceConfig, &device);
|
||||
ma_device_start(&device);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
float getParameter(int i) {
|
||||
#if PARAMETERS_N > 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Tibia
|
||||
#
|
||||
# Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
# 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
|
||||
@ -18,157 +18,98 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := lv2
|
||||
|
||||
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)
|
||||
DLL_SUFFIX := .dll
|
||||
UI_TYPE := WindowsUI
|
||||
LV2DIR := $(subst \,/,$(COMMONPROGRAMFILES))/LV2
|
||||
LV2DIR_USER := $(subst \,/,$(APPDATA))/LV2
|
||||
CC := gcc
|
||||
CXX := g++
|
||||
DLL_SUFFIX = .dll
|
||||
LV2DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/LV2
|
||||
LV2DIR_USER = $(shell echo '${APPDATA}' | sed 's:\\:/:g')/LV2
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
else
|
||||
UNAME_S = $(shell uname -s)
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
DLL_SUFFIX := .dylib
|
||||
UI_TYPE := CocoaUI
|
||||
LV2DIR := /Library/Audio/Plug-Ins/LV2
|
||||
LV2DIR_USER := $(HOME)/Library/Audio/Plug-Ins/LV2
|
||||
CC := clang
|
||||
CXX := clang++
|
||||
DLL_SUFFIX = .dylib
|
||||
LV2DIR = /Library/Audio/Plug-Ins/LV2
|
||||
LV2DIR_USER = ${HOME}/Library/Audio/Plug-Ins/LV2
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
else
|
||||
DLL_SUFFIX := .so
|
||||
UI_TYPE := X11UI
|
||||
PREFIX := /usr/local
|
||||
LV2DIR := $(PREFIX)/lib/lv2
|
||||
LV2DIR_USER := $(HOME)/.lv2
|
||||
CC := gcc
|
||||
CXX := g++
|
||||
DLL_SUFFIX = .so
|
||||
PREFIX = /usr/local
|
||||
LV2DIR = ${PREFIX}/lib/lv2
|
||||
LV2DIR_USER = ${HOME}/.lv2
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(shell pkg-config --cflags lv2) -fPIC $(CFLAGS_EXTRA) $(CFLAGS)
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
LDFLAGS :=
|
||||
LDFLAGS_ALL := -shared $(shell pkg-config --libs lv2) $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||
CFLAGS = -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CFLAGS} ${CFLAGS_EXTRA}
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||
LDFLAGS =
|
||||
LDFLAGS_ALL = -shared ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||
|
||||
CXXFLAGS = ${CFLAGS}
|
||||
CXXFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
CFLAGS_ALL := ${CFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
LDFLAGS_ALL := ${LDFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
CXXFLAGS_ALL := ${CXXFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
endif
|
||||
|
||||
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||
BUNDLE_DIR = ${BUNDLE_NAME}.lv2
|
||||
|
||||
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
DLL_FILE = ${BUNDLE_NAME}${DLL_SUFFIX}
|
||||
|
||||
M_SRCS := $(M_SRCS_EXTRA)
|
||||
M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
||||
C_SRCS = ${COMMON_DIR}/src/lv2.c ${C_SRCS_EXTRA}
|
||||
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
|
||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
CXX_SRCS = ${CXX_SRCS_EXTRA}
|
||||
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)
|
||||
|
||||
STRIP_ALL := build/$(BUNDLE_DIR)/$(DLL_FILE) build/$(BUNDLE_DIR)/manifest.ttl
|
||||
STRIP_PHONY :=
|
||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
||||
|
||||
-include $(MKINC_DIR)/vars-extra.mk
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
build/$(BUNDLE_DIR)/manifest.ttl: $(DATA_DIR)/data/manifest.ttl.in | build/$(BUNDLE_DIR)
|
||||
cat $^ | sed s/@DLL_SUFFIX@/$(DLL_SUFFIX)/g | sed s/@UI_TYPE@/$(UI_TYPE)/g > $@
|
||||
build/${BUNDLE_DIR}/manifest.ttl: ${DATA_DIR}/data/manifest.ttl.in | build/${BUNDLE_DIR}
|
||||
cat $^ | sed s/@DLL_SUFFIX@/${DLL_SUFFIX}/g > $@
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) | build/$(BUNDLE_DIR)
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} | build/${BUNDLE_DIR}
|
||||
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
else
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} ${CXX_OBJS} | build/${BUNDLE_DIR}
|
||||
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
endif
|
||||
|
||||
$(DIRS):
|
||||
build/${BUNDLE_DIR} build/obj:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
strip: $(STRIP_PREREQS)
|
||||
strip 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
|
||||
f=`sed '/^[[:space:]]*$$/d' build/$(BUNDLE_DIR)/manifest.ttl` && echo "$$f" > build/$(BUNDLE_DIR)/manifest.ttl
|
||||
|
||||
install: all
|
||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||
d=`echo $$d | sed 's:^build/::'` ; \
|
||||
echo mkdir -m 0755 -p "$(LV2DIR)/$$d"; \
|
||||
mkdir -m 0755 -p "$(LV2DIR)/$$d"; \
|
||||
done
|
||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||
d=`echo $$f | sed 's:^build/::'` ; \
|
||||
d=`dirname $$d`; \
|
||||
echo install -m $$m $$f "$(LV2DIR)/$$d"; \
|
||||
install -m $$m $$f "$(LV2DIR)/$$d"; \
|
||||
done
|
||||
mkdir -p -m 0755 "${LV2DIR}/${BUNDLE_DIR}"
|
||||
install -m 0644 build/${BUNDLE_DIR}/manifest.ttl "${LV2DIR}/${BUNDLE_DIR}"
|
||||
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${LV2DIR}/${BUNDLE_DIR}"
|
||||
|
||||
install-user: all
|
||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||
d=`echo $$d | sed 's:^build/::'` ; \
|
||||
echo mkdir -m 0755 -p "$(LV2DIR_USER)/$$d"; \
|
||||
mkdir -m 0755 -p "$(LV2DIR_USER)/$$d"; \
|
||||
done
|
||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||
d=`echo $$f | sed 's:^build/::'` ; \
|
||||
d=`dirname $$d`; \
|
||||
echo install -m $$m $$f "$(LV2DIR_USER)/$$d"; \
|
||||
install -m $$m $$f "$(LV2DIR_USER)/$$d"; \
|
||||
done
|
||||
mkdir -p -m 0755 "${LV2DIR_USER}/${BUNDLE_DIR}"
|
||||
install -m 0644 build/${BUNDLE_DIR}/manifest.ttl "${LV2DIR_USER}/${BUNDLE_DIR}"
|
||||
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${LV2DIR_USER}/${BUNDLE_DIR}"
|
||||
|
||||
-include $(MKINC_DIR)/rules-extra.mk
|
||||
|
||||
.PHONY: all clean strip $(STRIP_PHONY) install install-user
|
||||
.PHONY: all clean install install-user
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
PERCENT := %
|
||||
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
|
||||
$(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$(M_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||
|
@ -20,25 +20,13 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.lv2_make && it.lv2_make.cflags ? it.lv2_make.cflags : ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.lv2_make && it.lv2_make.ldflags ? it.lv2_make.ldflags : ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.lv2_make && it.lv2_make.cxxflags ? it.lv2_make.cxxflags : ""}}
|
||||
|
||||
{{?it.make?.extra}}
|
||||
{{=it.make.extra}}
|
||||
{{?}}
|
||||
{{?it.lv2_make?.extra}}
|
||||
{{=it.lv2_make.extra}}
|
||||
{{?}}
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.lv2_make && it.lv2_make.cSrcs ? it.lv2_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.lv2_make && it.lv2_make.cxxSrcs ? it.lv2_make.cxxSrcs : ""}}
|
||||
|
||||
COMMON_DIR := {{=it.lv2_make && it.lv2_make.commonDir ? it.lv2_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.lv2_make && it.lv2_make.dataDir ? it.lv2_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.lv2_make && it.lv2_make.pluginDir ? it.lv2_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
|
@ -1 +0,0 @@
|
||||
This is experimental and broken, do not use this.
|
@ -1,95 +0,0 @@
|
||||
{{~it.tibia.lv2.prefixes :p}}
|
||||
@prefix {{=p.id}}: <{{=p.uri}}> .
|
||||
{{~}}
|
||||
|
||||
{{~it.product.parameters :p}}
|
||||
plugin:{{=p.id}}
|
||||
a lv2:Parameter ;
|
||||
rdfs:label "{{=p.name}}" ;
|
||||
lv2:name "{{=p.name}}" ;
|
||||
{{?"shortName" in p}}
|
||||
lv2:shortName "{{=p.shortName.substring(0, 16)}}" ;
|
||||
{{?}}
|
||||
lv2:symbol "{{=p.id}}" ;
|
||||
rdfs:range atom:Float .
|
||||
{{~}}
|
||||
|
||||
{{=it.tibia.lv2.ttlURI(it.lv2.uri)}}
|
||||
a lv2:Plugin ;
|
||||
{{~it.lv2.types :t}}
|
||||
a {{=it.tibia.lv2.ttlURI(t)}} ;
|
||||
{{~}}
|
||||
{{?it.lv2.project}}
|
||||
lv2:project {{=it.tibia.lv2.ttlURI(it.lv2.project)}} ;
|
||||
{{?}}
|
||||
lv2:binary <{{=it.product.bundleName}}@DLL_SUFFIX@> ;
|
||||
doap:name "{{=it.product.name}}" ;
|
||||
doap:maintainer [
|
||||
a foaf:Organization ;
|
||||
foaf:name "{{=it.company.name}}" ;
|
||||
foaf:mbox <mailto:{{=it.company.email}}> ;
|
||||
rdfs:seeAlso {{=it.tibia.lv2.ttlURI(it.company.url)}}
|
||||
] ;
|
||||
lv2:minorVersion {{=/^([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" || p.type == "param")}}
|
||||
lv2:requiredFeature urid:map ;
|
||||
lv2:optionalFeature log:log ;
|
||||
{{?}}
|
||||
{{?it.product.parameters.find(p => p.direction == "input")}}
|
||||
patch:writable {{=it.product.parameters.filter(p => p.direction == "input").map(p => "plugin:" + p.id).join(" , ")}} ;
|
||||
{{?}}
|
||||
{{?it.product.parameters.find(p => p.direction == "output")}}
|
||||
patch:readable {{=it.product.parameters.filter(p => p.direction == "output").map(p => "plugin:" + p.id).join(" , ")}} ;
|
||||
{{?}}
|
||||
lv2:optionalFeature lv2:hardRTCapable ;
|
||||
{{?it.product.ui}}
|
||||
ui:ui plugin:ui ;
|
||||
{{?}}
|
||||
lv2:port [
|
||||
{{~it.tibia.lv2.ports :p:i}}
|
||||
a {{?p.type == "control"}}lv2:ControlPort{{??(p.type == "midi" || p.type == "param")}}atom:AtomPort{{??}}{{?p.cv}}lv2:CVPort{{??}}lv2:AudioPort{{?}}{{?}} ,
|
||||
{{?p.direction == "input"}}lv2:InputPort{{??}}lv2:OutputPort{{?}} ;
|
||||
lv2:name "{{=p.name}}" ;
|
||||
{{?"shortName" in p}}
|
||||
lv2:shortName "{{=p.shortName.substring(0, 16)}}" ;
|
||||
{{?}}
|
||||
lv2:symbol "{{=p.id}}" ;
|
||||
{{?p.type == "param"}}
|
||||
atom:bufferType atom:Sequence ;
|
||||
atom:supports atom:Object ;
|
||||
atom:supports patch:Message ;
|
||||
{{??p.type == "midi"}}
|
||||
atom:bufferType atom:Sequence ;
|
||||
atom:supports midi:MidiEvent ;
|
||||
{{?}}
|
||||
{{?p.sidechain}}
|
||||
lv2:portProperty lv2:isSideChain ;
|
||||
{{?}}
|
||||
{{?p.control}}
|
||||
lv2:designation lv2:control ;
|
||||
{{?}}
|
||||
{{?p.optional}}
|
||||
lv2:portProperty lv2:connectionOptional ;
|
||||
{{?}}
|
||||
lv2:index {{=i}}
|
||||
{{?i < it.tibia.lv2.ports.length - 1}}
|
||||
] , [
|
||||
{{??}}
|
||||
] .
|
||||
{{?}}
|
||||
{{~}}
|
||||
|
||||
{{?it.product.ui}}
|
||||
plugin:ui
|
||||
a ui:@UI_TYPE@ ;
|
||||
ui:binary <{{=it.product.bundleName}}@DLL_SUFFIX@> ;
|
||||
{{?!it.product.ui.userResizable}}
|
||||
lv2:optionalFeature ui:noUserResize ; # doesn't work as lv2:requiredFeature, don't ask me why
|
||||
{{?!it.product.ui.selfResizable}}
|
||||
lv2:optionalFeature ui:fixedSize ;
|
||||
{{?}}
|
||||
{{?}}
|
||||
lv2:requiredFeature ui:idleInterface ;
|
||||
lv2:extensionData ui:idleInterface .
|
||||
{{?}}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define DATA_LV2_URI "{{=it.tibia.CGetUTF8StringLiteral(it.tibia.lv2.expandURI(it.lv2.uri))}}"
|
||||
|
||||
#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||
#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||
#define DATA_PRODUCT_MIDI_INPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||
#define DATA_PRODUCT_MIDI_OUTPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").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}}
|
||||
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
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}}, {{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
|
||||
# define DATA_PARAM_BYPASS 1
|
||||
# define DATA_PARAM_TOGGLED (1<<1)
|
||||
# define DATA_PARAM_INTEGER (1<<2)
|
||||
|
||||
static struct {
|
||||
uint32_t index;
|
||||
float min;
|
||||
float max;
|
||||
float def;
|
||||
uint32_t flags;
|
||||
} param_data[DATA_PRODUCT_CONTROL_INPUTS_N] = {
|
||||
{{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "input") :p}}
|
||||
{
|
||||
/* .index = */ {{=p.paramIndex}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||
/* .max = */ {{=p.maximum.toExponential()}}f,
|
||||
/* .def = */ {{=p.defaultValue.toExponential()}}f,
|
||||
/* .flags = */ {{?p.isBypass}}DATA_PARAM_BYPASS{{??p.isLatency}}DATA_PARAM_INTEGER{{??}}0{{?p.toggled}} | DATA_PARAM_TOGGLED{{?}}{{?p.integer}} | DATA_PARAM_INTEGER{{?}}{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||
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}}, {{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
{{?it.lv2.ui}}
|
||||
#define DATA_UI
|
||||
#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}}
|
||||
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
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}}, {{~}}
|
||||
};
|
||||
#endif
|
||||
{{?}}
|
@ -1,499 +0,0 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#include "plugin.h"
|
||||
#ifdef DATA_UI
|
||||
# include "plugin_ui.h"
|
||||
#endif
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "lv2/core/lv2.h"
|
||||
#include "lv2/core/lv2_util.h"
|
||||
#include "lv2/log/log.h"
|
||||
#include "lv2/log/logger.h"
|
||||
#include "lv2/urid/urid.h"
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
# include "lv2/atom/util.h"
|
||||
# include "lv2/atom/atom.h"
|
||||
# include "lv2/midi/midi.h"
|
||||
#endif
|
||||
#ifdef DATA_UI
|
||||
# include "lv2/ui/ui.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# include <xmmintrin.h>
|
||||
# include <pmmintrin.h>
|
||||
#endif
|
||||
|
||||
static inline float clampf(float x, float m, float M) {
|
||||
return x < m ? m : (x > M ? M : x);
|
||||
}
|
||||
|
||||
static float adjust_param(size_t index, float value) {
|
||||
if (param_data[index].flags & DATA_PARAM_BYPASS)
|
||||
value = value > 0.f ? 0.f : 1.f;
|
||||
else if (param_data[index].flags & DATA_PARAM_TOGGLED)
|
||||
value = value > 0.f ? 1.f : 0.f;
|
||||
else if (param_data[index].flags & DATA_PARAM_INTEGER)
|
||||
value = (int32_t)(value + (value >= 0.f ? 0.5f : -0.5f));
|
||||
return clampf(value, param_data[index].min, param_data[index].max);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
plugin p;
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||
#endif
|
||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||
float * y[DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N];
|
||||
#endif
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
const LV2_Atom_Sequence * x_midi[DATA_PRODUCT_MIDI_INPUTS_N];
|
||||
#endif
|
||||
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
LV2_Atom_Sequence * y_midi[DATA_PRODUCT_MIDI_OUTPUTS_N];
|
||||
#endif
|
||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||
float * c[DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N];
|
||||
#endif
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||
#endif
|
||||
void * mem;
|
||||
char * bundle_path;
|
||||
LV2_Log_Logger logger;
|
||||
LV2_URID_Map * map;
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
LV2_URID uri_midi_MidiEvent;
|
||||
#endif
|
||||
} plugin_instance;
|
||||
|
||||
static const char * get_bundle_path_cb(void *handle) {
|
||||
plugin_instance *instance = (plugin_instance *)handle;
|
||||
return instance->bundle_path;
|
||||
}
|
||||
|
||||
static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double sample_rate, const char * bundle_path, const LV2_Feature * const * features) {
|
||||
(void)descriptor;
|
||||
(void)bundle_path;
|
||||
|
||||
plugin_instance *instance = malloc(sizeof(plugin_instance));
|
||||
if (instance == NULL)
|
||||
goto err_instance;
|
||||
|
||||
instance->bundle_path = strdup(bundle_path);
|
||||
if (instance->bundle_path == NULL)
|
||||
goto err_bundle_path;
|
||||
|
||||
// from https://lv2plug.in/book
|
||||
const char* missing = lv2_features_query(features,
|
||||
LV2_LOG__log, &instance->logger.log, false,
|
||||
LV2_URID__map, &instance->map, true,
|
||||
NULL);
|
||||
|
||||
lv2_log_logger_set_map(&instance->logger, instance->map);
|
||||
if (missing) {
|
||||
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
|
||||
goto err_urid;
|
||||
}
|
||||
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
instance->uri_midi_MidiEvent = instance->map->map(instance->map->handle, LV2_MIDI__MidiEvent);
|
||||
#endif
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ (void *)instance,
|
||||
/* .format = */ "lv2",
|
||||
/* .get_bindir = */ get_bundle_path_cb,
|
||||
/* .get_datadir = */ get_bundle_path_cb
|
||||
};
|
||||
plugin_init(&instance->p, &cbs);
|
||||
|
||||
plugin_set_sample_rate(&instance->p, sample_rate);
|
||||
size_t req = plugin_mem_req(&instance->p);
|
||||
if (req != 0) {
|
||||
instance->mem = malloc(req);
|
||||
if (instance->mem == NULL) {
|
||||
lv2_log_error(&instance->logger, "Not enough memory\n");
|
||||
goto err_mem;
|
||||
}
|
||||
plugin_mem_set(&instance->p, instance->mem);
|
||||
} else
|
||||
instance->mem = NULL;
|
||||
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
for (uint32_t i = 0; i < DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N; i++)
|
||||
instance->x[i] = NULL;
|
||||
#endif
|
||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||
for (uint32_t i = 0; i < DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N; i++)
|
||||
instance->y[i] = NULL;
|
||||
#endif
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
for (uint32_t i = 0; i < DATA_PRODUCT_MIDI_INPUTS_N; i++)
|
||||
instance->x_midi[i] = NULL;
|
||||
#endif
|
||||
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
for (uint32_t i = 0; i < DATA_PRODUCT_MIDI_OUTPUTS_N; i++)
|
||||
instance->y_midi[i] = NULL;
|
||||
#endif
|
||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||
for (uint32_t i = 0; i < DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N; i++)
|
||||
instance->c[i] = NULL;
|
||||
#endif
|
||||
|
||||
return instance;
|
||||
|
||||
err_mem:
|
||||
plugin_fini(&instance->p);
|
||||
err_urid:
|
||||
free(instance->bundle_path);
|
||||
err_bundle_path:
|
||||
free(instance);
|
||||
err_instance:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void connect_port(LV2_Handle instance, uint32_t port, void * data_location) {
|
||||
plugin_instance * i = (plugin_instance *)instance;
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
if (port < DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N) {
|
||||
i->x[port] = data_location;
|
||||
return;
|
||||
}
|
||||
port -= DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N;
|
||||
#endif
|
||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||
if (port < DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N) {
|
||||
i->y[port] = data_location;
|
||||
return;
|
||||
}
|
||||
port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N;
|
||||
#endif
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
if (port < DATA_PRODUCT_MIDI_INPUTS_N) {
|
||||
i->x_midi[port] = data_location;
|
||||
return;
|
||||
}
|
||||
port -= DATA_PRODUCT_MIDI_INPUTS_N;
|
||||
#endif
|
||||
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
if (port < DATA_PRODUCT_MIDI_OUTPUTS_N) {
|
||||
i->y_midi[port] = data_location;
|
||||
return;
|
||||
}
|
||||
port -= DATA_PRODUCT_MIDI_OUTPUTS_N;
|
||||
#endif
|
||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||
i->c[port] = data_location;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void activate(LV2_Handle instance) {
|
||||
plugin_instance * i = (plugin_instance *)instance;
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
||||
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]);
|
||||
}
|
||||
#endif
|
||||
plugin_reset(&i->p);
|
||||
}
|
||||
|
||||
static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||
plugin_instance * i = (plugin_instance *)instance;
|
||||
|
||||
#if defined(__aarch64__)
|
||||
uint64_t fpcr;
|
||||
__asm__ __volatile__ ("mrs %0, fpcr" : "=r"(fpcr));
|
||||
__asm__ __volatile__ ("msr fpcr, %0" :: "r"(fpcr | 0x1000000)); // enable FZ
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
const unsigned int flush_zero_mode = _MM_GET_FLUSH_ZERO_MODE();
|
||||
const unsigned int denormals_zero_mode = _MM_GET_DENORMALS_ZERO_MODE();
|
||||
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
||||
if (i->c[j] == NULL)
|
||||
continue;
|
||||
float v = adjust_param(j, *i->c[j]);
|
||||
if (v != i->params[j]) {
|
||||
i->params[j] = v;
|
||||
plugin_set_parameter(&i->p, param_data[j].index, v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// from https://lv2plug.in/book
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) {
|
||||
if (i->x_midi[j] == NULL)
|
||||
continue;
|
||||
LV2_ATOM_SEQUENCE_FOREACH(i->x_midi[j], ev) {
|
||||
if (ev->body.type == i->uri_midi_MidiEvent) {
|
||||
const uint8_t * data = (const uint8_t *)(ev + 1);
|
||||
if ((data[0] & 0xf0) != 0xf0)
|
||||
plugin_midi_msg_in(&i->p, midi_in_index[j], data);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
const float ** x = i->x;
|
||||
#else
|
||||
const float ** x = NULL;
|
||||
#endif
|
||||
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
|
||||
float ** y = i-> y;
|
||||
#else
|
||||
float ** y = NULL;
|
||||
#endif
|
||||
plugin_process(&i->p, x, y, sample_count);
|
||||
|
||||
#if DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_OUTPUTS_N; j++) {
|
||||
uint32_t k = param_out_index[j];
|
||||
if (i->c[k] != NULL)
|
||||
*i->c[k] = plugin_get_parameter(&i->p, k);
|
||||
}
|
||||
#else
|
||||
(void)plugin_get_parameter;
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
__asm__ __volatile__ ("msr fpcr, %0" : : "r"(fpcr));
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cleanup(LV2_Handle instance) {
|
||||
plugin_instance * i = (plugin_instance *)instance;
|
||||
plugin_fini(&i->p);
|
||||
if (i->mem)
|
||||
free(i->mem);
|
||||
free(i->bundle_path);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static const LV2_Descriptor descriptor = {
|
||||
/* .URI = */ DATA_LV2_URI,
|
||||
/* .instantiate = */ instantiate,
|
||||
/* .connect_port = */ connect_port,
|
||||
/* .activate = */ activate,
|
||||
/* .run = */ run,
|
||||
/* .deactivate = */ NULL,
|
||||
/* .cleanup = */ cleanup,
|
||||
/* .extension_data = */ NULL
|
||||
};
|
||||
|
||||
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
||||
return index == 0 ? &descriptor : NULL;
|
||||
}
|
||||
|
||||
#ifdef DATA_UI
|
||||
typedef struct {
|
||||
plugin_ui * ui;
|
||||
char * bundle_path;
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
LV2UI_Write_Function write;
|
||||
LV2UI_Controller controller;
|
||||
char has_touch;
|
||||
LV2UI_Touch touch;
|
||||
# endif
|
||||
} 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) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
return instance->bundle_path;
|
||||
}
|
||||
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
static void ui_set_parameter_begin_cb(void *handle, size_t index, float value) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
if (instance->has_touch) {
|
||||
index = index_to_param[index];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_set_parameter_cb(void *handle, size_t index, float value) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
index = index_to_param[index];
|
||||
value = adjust_param(index - CONTROL_INPUT_INDEX_OFFSET, value);
|
||||
instance->write(instance->controller, index, sizeof(float), 0, &value);
|
||||
}
|
||||
|
||||
static void ui_set_parameter_end_cb(void *handle, size_t index, float value) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
if (instance->has_touch) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const char * plugin_uri, const char * bundle_path, LV2UI_Write_Function write_function, LV2UI_Controller controller, LV2UI_Widget * widget, const LV2_Feature * const * features) {
|
||||
(void)descriptor;
|
||||
(void)plugin_uri;
|
||||
|
||||
ui_instance *instance = malloc(sizeof(ui_instance));
|
||||
if (instance == NULL)
|
||||
goto err_instance;
|
||||
|
||||
instance->bundle_path = strdup(bundle_path);
|
||||
if (instance->bundle_path == NULL)
|
||||
goto err_bundle_path;
|
||||
|
||||
char has_parent = 0;
|
||||
void *parent = NULL;
|
||||
instance->has_touch = 0;
|
||||
for (size_t i = 0; features[i] != NULL; i++) {
|
||||
if (!strcmp(features[i]->URI, LV2_UI__parent)) {
|
||||
has_parent = 1;
|
||||
parent = features[i]->data;
|
||||
}
|
||||
if (!strcmp(features[i]->URI, LV2_UI__touch)) {
|
||||
instance->has_touch = 1;
|
||||
instance->touch = *((LV2UI_Touch *)features[i]->data);
|
||||
}
|
||||
}
|
||||
|
||||
plugin_ui_callbacks cbs = {
|
||||
/* .handle = */ (void *)instance,
|
||||
/* .format = */ "lv2",
|
||||
/* .get_bindir = */ ui_get_bundle_path_cb,
|
||||
/* .get_datadir = */ ui_get_bundle_path_cb,
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
/* .set_parameter_begin = */ ui_set_parameter_begin_cb,
|
||||
/* .set_parameter = */ ui_set_parameter_cb,
|
||||
/* .set_parameter_end = */ ui_set_parameter_end_cb
|
||||
# else
|
||||
/* .set_parameter_begin = */ NULL,
|
||||
/* .set_parameter = */ NULL,
|
||||
/* .set_parameter_end = */ NULL
|
||||
# endif
|
||||
};
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
instance->write = write_function;
|
||||
instance->controller = controller;
|
||||
# else
|
||||
(void)write_function;
|
||||
(void)controller;
|
||||
# endif
|
||||
instance->ui = plugin_ui_create(has_parent, parent, &cbs);
|
||||
if (instance->ui == NULL)
|
||||
goto err_create;
|
||||
|
||||
*widget = instance->ui->widget;
|
||||
return instance;
|
||||
|
||||
err_create:
|
||||
free(instance->bundle_path);
|
||||
err_bundle_path:
|
||||
free(instance);
|
||||
err_instance:
|
||||
*widget = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ui_cleanup(LV2UI_Handle handle) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
plugin_ui_free(instance->ui);
|
||||
free(instance->bundle_path);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||
static void ui_port_event(LV2UI_Handle handle, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void * buffer) {
|
||||
(void)buffer_size;
|
||||
(void)format;
|
||||
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
if (port_index < CONTROL_OUTPUT_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)));
|
||||
}
|
||||
# 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));
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
static int ui_idle(LV2UI_Handle handle) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
plugin_ui_idle(instance->ui);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void * ui_extension_data(const char * uri) {
|
||||
static const LV2UI_Idle_Interface idle = { ui_idle };
|
||||
if (!strcmp(uri, LV2_UI__idleInterface))
|
||||
return &idle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const LV2UI_Descriptor ui_descriptor = {
|
||||
/* .URI = */ DATA_LV2_UI_URI,
|
||||
/* .instantiate = */ ui_instantiate,
|
||||
/* .cleanup = */ ui_cleanup,
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||
/* .port_event = */ ui_port_event,
|
||||
# else
|
||||
/* .port_event = */ NULL,
|
||||
# endif
|
||||
/* .extension_data = */ ui_extension_data
|
||||
};
|
||||
|
||||
LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) {
|
||||
return index == 0 ? &ui_descriptor : NULL;
|
||||
}
|
||||
#endif
|
@ -1,136 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
var path = require("path");
|
||||
var sep = path.sep;
|
||||
|
||||
module.exports = function (data, api, outputCommon, outputData) {
|
||||
if (outputData) {
|
||||
data.tibia.lv2 = {
|
||||
prefixes: [
|
||||
{ id: "atom", uri: "http://lv2plug.in/ns/ext/atom#" },
|
||||
{ id: "doap", uri: "http://usefulinc.com/ns/doap#" },
|
||||
{ id: "foaf", uri: "http://xmlns.com/foaf/0.1/" },
|
||||
{ id: "log", uri: "http://lv2plug.in/ns/ext/log#" },
|
||||
{ id: "lv2", uri: "http://lv2plug.in/ns/lv2core#" },
|
||||
{ id: "midi", uri: "http://lv2plug.in/ns/ext/midi#" },
|
||||
{ id: "patch", uri: "http://lv2plug.in/ns/ext/patch#" },
|
||||
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
||||
{ 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: "ui", uri: "http://lv2plug.in/ns/extensions/ui#" },
|
||||
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
|
||||
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
|
||||
],
|
||||
units: {
|
||||
"bar": "@units:bar",
|
||||
"beat": "@units:beat",
|
||||
"bpm": "@units:bpm",
|
||||
"cent": "@units:cent",
|
||||
"cm": "@units:cm",
|
||||
"coef": "@units:coef",
|
||||
"db": "@units:db",
|
||||
"degree": "@units:degree",
|
||||
"frame": "@units:frame",
|
||||
"hz": "@units:hz",
|
||||
"inch": "@units:inch",
|
||||
"khz": "@units:khz",
|
||||
"km": "@units:km",
|
||||
"m": "@units:m",
|
||||
"mhz": "@units:mhz",
|
||||
"midiNote": "@units:midiNote",
|
||||
"mile": "@units:mile",
|
||||
"min": "@units:min",
|
||||
"mm": "@units:mm",
|
||||
"ms": "@units:ms",
|
||||
"oct": "@units:oct",
|
||||
"pc": "@units:pc",
|
||||
"s": "@units:s",
|
||||
"semitone12TET": "@units:semitone12TET"
|
||||
},
|
||||
ports: [],
|
||||
|
||||
ttlURI: function (uri) {
|
||||
if (uri.charAt(0) == "@") {
|
||||
if (uri.indexOf("#") == -1)
|
||||
return uri.substring(1);
|
||||
uri = data.tibia.lv2.expandURI(uri);
|
||||
}
|
||||
return "<" + uri + ">";
|
||||
},
|
||||
|
||||
expandURI: function (uri) {
|
||||
if (uri.charAt(0) != "@")
|
||||
return uri;
|
||||
var i = uri.indexOf(":");
|
||||
var p = uri.substring(1, uri.indexOf(":"));
|
||||
return data.tibia.lv2.prefixes.find(x => x.id == p).uri + uri.substring(i + 1);
|
||||
}
|
||||
};
|
||||
|
||||
for (var id in data.lv2.prefixes)
|
||||
data.tibia.lv2.prefixes.push({ id: id, uri: data.lv2.prefixes[id] });
|
||||
|
||||
data.tibia.lv2.prefixes.push({ id: "plugin", uri: data.tibia.lv2.expandURI(data.lv2.uri) + "#" });
|
||||
|
||||
var buses = data.product.buses;
|
||||
var audioPorts = [];
|
||||
var midiPorts = [];
|
||||
for (var bi = 0; bi < buses.length; bi++) {
|
||||
var b = buses[bi];
|
||||
if (b.type == "audio") {
|
||||
if (b.channels == "mono") {
|
||||
var e = { type: "audio", direction: b.direction, name: b.name, sidechain: b.sidechain, cv: b.cv, optional: b.optional, busIndex: bi, id: b.id };
|
||||
audioPorts.push(e);
|
||||
} else {
|
||||
var e = { type: "audio", direction: b.direction, name: b.name + " Left", shortName: b.shortName + " L", sidechain: b.sidechain, cv: b.cv, busIndex: bi, id: b.id + "_l" };
|
||||
audioPorts.push(e);
|
||||
var e = { type: "audio", direction: b.direction, name: b.name + " Right", shortName: b.shortName + " R", sidechain: b.sidechain, cv: b.cv, busIndex: bi, id: b.id + "_r" };
|
||||
audioPorts.push(e);
|
||||
}
|
||||
} else {
|
||||
var e = { type: "midi", direction: b.direction, name: b.name, sidechain: b.sidechain, control: b.control, optional: b.optional, busIndex: bi, id: b.id };
|
||||
midiPorts.push(e);
|
||||
}
|
||||
}
|
||||
audioPorts.sort((a, b) => a.direction != b.direction ? (a.direction == "input" ? -1 : 1) : 0);
|
||||
midiPorts.sort((a, b) => a.direction != b.direction ? (a.direction == "input" ? -1 : 1) : 0);
|
||||
data.tibia.lv2.ports.push.apply(data.tibia.lv2.ports, audioPorts);
|
||||
data.tibia.lv2.ports.push.apply(data.tibia.lv2.ports, midiPorts);
|
||||
|
||||
var hasCtrlIn = false;
|
||||
var hasCtrlOut = false;
|
||||
for (var i = 0; i < data.product.parameters.length && !(hasCtrlIn && hasCtrlOut); i++) {
|
||||
var p = data.product.parameters[i];
|
||||
if (p.direction == "input")
|
||||
hasCtrlIn = true;
|
||||
else
|
||||
hasCtrlOut = true;
|
||||
}
|
||||
if (hasCtrlIn)
|
||||
data.tibia.lv2.ports.push({ type: "param", direction: "input", name: "Control in", id: "control_in", control: true });
|
||||
if (hasCtrlOut)
|
||||
data.tibia.lv2.ports.push({ type: "param", direction: "output", name: "Control out", id: "control_out", control: true });
|
||||
}
|
||||
|
||||
api.generateFileFromTemplateFile(`data${sep}manifest.ttl.in`, `data${sep}manifest.ttl.in`, data);
|
||||
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||
};
|
@ -15,27 +15,16 @@
|
||||
doap:maintainer [
|
||||
a foaf:Organization ;
|
||||
foaf:name "{{=it.company.name}}" ;
|
||||
foaf:mbox <mailto:{{=it.company.email}}> ;
|
||||
foaf:mbox "{{=it.company.email}}" ;
|
||||
rdfs:seeAlso {{=it.tibia.lv2.ttlURI(it.company.url)}}
|
||||
] ;
|
||||
lv2:minorVersion {{=/^([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" && !p.optional))}}
|
||||
{{?it.tibia.lv2.ports.find(p => p.type == "midi")}}
|
||||
lv2:requiredFeature urid:map ;
|
||||
{{??}}
|
||||
lv2:optionalFeature urid:map ;
|
||||
{{?}}
|
||||
lv2:optionalFeature log:log ;
|
||||
{{?}}
|
||||
lv2:optionalFeature lv2:hardRTCapable ;
|
||||
{{?(it.product.state && it.product.state.dspCustom)}}
|
||||
lv2:optionalFeature state:threadSafeRestore ;
|
||||
{{?}}
|
||||
{{?it.product.ui}}
|
||||
ui:ui plugin:ui ;
|
||||
{{?}}
|
||||
{{?(it.product.state && it.product.state.dspCustom)}}
|
||||
lv2:extensionData state:interface ;
|
||||
{{?}}
|
||||
lv2:port [
|
||||
{{~it.tibia.lv2.ports :p:i}}
|
||||
{{?p.isBypass}}
|
||||
@ -44,7 +33,7 @@
|
||||
lv2:designation lv2:enabled ;
|
||||
lv2:name "Enabled" ;
|
||||
lv2:shortName "Enabled" ;
|
||||
lv2:symbol "enabled" ;
|
||||
lv2:symbol "{{=p.symbol}}" ;
|
||||
lv2:default 1 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 1 ;
|
||||
@ -64,7 +53,7 @@
|
||||
lv2:designation lv2:latency ;
|
||||
lv2:name "Latency" ;
|
||||
lv2:shortName "Latency" ;
|
||||
lv2:symbol "{{=p.id}}" ;
|
||||
lv2:symbol "{{=p.symbol}}" ;
|
||||
lv2:portProperty lv2:connectionOptional ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:portProperty lv2:reportsLatency ;
|
||||
@ -75,7 +64,7 @@
|
||||
{{?"shortName" in p}}
|
||||
lv2:shortName "{{=p.shortName.substring(0, 16)}}" ;
|
||||
{{?}}
|
||||
lv2:symbol "{{=p.id}}" ;
|
||||
lv2:symbol "{{=p.symbol}}" ;
|
||||
{{?p.type == "control"}}
|
||||
lv2:minimum {{=p.minimum.toExponential()}} ;
|
||||
lv2:maximum {{=p.maximum.toExponential()}} ;
|
||||
@ -128,17 +117,3 @@
|
||||
] .
|
||||
{{?}}
|
||||
{{~}}
|
||||
|
||||
{{?it.product.ui}}
|
||||
plugin:ui
|
||||
a ui:@UI_TYPE@ ;
|
||||
ui:binary <{{=it.product.bundleName}}@DLL_SUFFIX@> ;
|
||||
{{?!it.product.ui.userResizable}}
|
||||
lv2:optionalFeature ui:noUserResize ; # doesn't work as lv2:requiredFeature, don't ask me why
|
||||
{{?!it.product.ui.selfResizable}}
|
||||
lv2:optionalFeature ui:fixedSize ;
|
||||
{{?}}
|
||||
{{?}}
|
||||
lv2:requiredFeature ui:idleInterface ;
|
||||
lv2:extensionData ui:idleInterface .
|
||||
{{?}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -27,10 +27,6 @@
|
||||
#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}}
|
||||
|
||||
{{?it.product.buses.find(x => x.type == "midi" && !x.optional)}}
|
||||
#define DATA_PRODUCT_MIDI_REQUIRED
|
||||
{{?}}
|
||||
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
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}}, {{~}}
|
||||
@ -68,21 +64,3 @@ 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}}, {{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
{{?it.product.ui}}
|
||||
#define DATA_UI
|
||||
#define DATA_LV2_UI_URI "{{=it.tibia.CGetUTF8StringLiteral(it.tibia.lv2.expandURI(it.lv2.uri + '#ui'))}}"
|
||||
#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
|
||||
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}}, {{~}}
|
||||
};
|
||||
#endif
|
||||
{{?}}
|
||||
|
||||
{{?it.product.state && it.product.state.dspCustom}}
|
||||
#define DATA_STATE_DSP_CUSTOM
|
||||
{{?}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -22,78 +22,26 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#include "plugin.h"
|
||||
#ifdef DATA_UI
|
||||
# include "plugin_ui.h"
|
||||
#endif
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <lv2/core/lv2.h>
|
||||
#include <lv2/core/lv2_util.h>
|
||||
#include <lv2/log/log.h>
|
||||
#include <lv2/log/logger.h>
|
||||
#include <lv2/urid/urid.h>
|
||||
#if (DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0) || defined(DATA_STATE_DSP_CUSTOM)
|
||||
# include <lv2/atom/atom.h>
|
||||
#include "lv2/core/lv2.h"
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
# include <lv2/atom/util.h>
|
||||
# include <lv2/midi/midi.h>
|
||||
#include "lv2/core/lv2_util.h"
|
||||
#include "lv2/atom/util.h"
|
||||
#include "lv2/atom/atom.h"
|
||||
#include "lv2/log/log.h"
|
||||
#include "lv2/log/logger.h"
|
||||
#include "lv2/midi/midi.h"
|
||||
#include "lv2/urid/urid.h"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DATA_UI
|
||||
# include <lv2/ui/ui.h>
|
||||
#endif
|
||||
#ifdef DATA_STATE_DSP_CUSTOM
|
||||
# include <lv2/state/state.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include <xmmintrin.h>
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N > 0) && defined(DATA_STATE_DSP_CUSTOM)
|
||||
# include <stdatomic.h>
|
||||
# if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# include <processthreadsapi.h>
|
||||
# define yield SwitchToThread
|
||||
# else
|
||||
# include <sched.h>
|
||||
# define yield sched_yield
|
||||
# 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) {
|
||||
return x < m ? m : (x > M ? M : x);
|
||||
}
|
||||
|
||||
static float adjust_param(size_t index, float value) {
|
||||
if (param_data[index].flags & DATA_PARAM_BYPASS)
|
||||
value = value > 0.f ? 0.f : 1.f;
|
||||
else if (param_data[index].flags & DATA_PARAM_TOGGLED)
|
||||
value = value > 0.f ? 1.f : 0.f;
|
||||
else if (param_data[index].flags & DATA_PARAM_INTEGER)
|
||||
value = (int32_t)(value + (value >= 0.f ? 0.5f : -0.5f));
|
||||
return clampf(value, param_data[index].min, param_data[index].max);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
plugin p;
|
||||
float sample_rate;
|
||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||
#endif
|
||||
@ -111,75 +59,24 @@ typedef struct {
|
||||
#endif
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||
# ifdef DATA_STATE_DSP_CUSTOM
|
||||
float params_sync[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||
atomic_flag sync_lock_flag;
|
||||
char synced;
|
||||
char loaded;
|
||||
# endif
|
||||
#endif
|
||||
void * mem;
|
||||
char * bundle_path;
|
||||
LV2_Log_Logger logger;
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
|
||||
LV2_URID_Map * map;
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||
LV2_Log_Logger logger;
|
||||
LV2_URID uri_midi_MidiEvent;
|
||||
#endif
|
||||
#ifdef DATA_STATE_DSP_CUSTOM
|
||||
LV2_URID uri_atom_Chunk;
|
||||
LV2_URID uri_state_data;
|
||||
plugin_state_callbacks state_cbs;
|
||||
LV2_State_Store_Function state_store;
|
||||
LV2_State_Handle state_handle;
|
||||
#endif
|
||||
} plugin_instance;
|
||||
|
||||
static const char * get_bundle_path_cb(void *handle) {
|
||||
plugin_instance *instance = (plugin_instance *)handle;
|
||||
return instance->bundle_path;
|
||||
}
|
||||
|
||||
#ifdef DATA_STATE_DSP_CUSTOM
|
||||
static void state_lock_cb(void *handle) {
|
||||
plugin_instance * i = (plugin_instance *)handle;
|
||||
while (atomic_flag_test_and_set(&i->sync_lock_flag))
|
||||
yield();
|
||||
i->synced = 0;
|
||||
}
|
||||
|
||||
static void state_unlock_cb(void *handle) {
|
||||
plugin_instance * i = (plugin_instance *)handle;
|
||||
atomic_flag_clear(&i->sync_lock_flag);
|
||||
}
|
||||
|
||||
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) {
|
||||
(void)descriptor;
|
||||
(void)bundle_path;
|
||||
|
||||
plugin_instance *instance = malloc(sizeof(plugin_instance));
|
||||
if (instance == NULL)
|
||||
goto err_instance;
|
||||
|
||||
instance->bundle_path = strdup(bundle_path);
|
||||
if (instance->bundle_path == NULL)
|
||||
goto err_bundle_path;
|
||||
return NULL;
|
||||
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
|
||||
// from https://lv2plug.in/book
|
||||
const char* missing = lv2_features_query(features,
|
||||
LV2_LOG__log, &instance->logger.log, false,
|
||||
@ -189,38 +86,24 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
||||
lv2_log_logger_set_map(&instance->logger, instance->map);
|
||||
if (missing) {
|
||||
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
|
||||
#ifdef DATA_PRODUCT_MIDI_REQUIRED
|
||||
goto err_urid;
|
||||
#endif
|
||||
free(instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#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);
|
||||
#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");
|
||||
}
|
||||
#else
|
||||
(void)features;
|
||||
#endif
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ (void *)instance,
|
||||
/* .format = */ "lv2",
|
||||
/* .get_bindir = */ get_bundle_path_cb,
|
||||
/* .get_datadir = */ get_bundle_path_cb
|
||||
};
|
||||
plugin_init(&instance->p, &cbs);
|
||||
plugin_init(&instance->p);
|
||||
|
||||
instance->sample_rate = (float)sample_rate;
|
||||
plugin_set_sample_rate(&instance->p, instance->sample_rate);
|
||||
plugin_set_sample_rate(&instance->p, sample_rate);
|
||||
size_t req = plugin_mem_req(&instance->p);
|
||||
if (req != 0) {
|
||||
instance->mem = malloc(req);
|
||||
if (instance->mem == NULL) {
|
||||
lv2_log_error(&instance->logger, "Not enough memory\n");
|
||||
goto err_mem;
|
||||
plugin_fini(&instance->p);
|
||||
return NULL;
|
||||
}
|
||||
plugin_mem_set(&instance->p, instance->mem);
|
||||
} else
|
||||
@ -248,17 +131,6 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
||||
#endif
|
||||
|
||||
return instance;
|
||||
|
||||
err_mem:
|
||||
plugin_fini(&instance->p);
|
||||
#ifdef DATA_PRODUCT_MIDI_REQUIRED
|
||||
err_urid:
|
||||
#endif
|
||||
free(instance->bundle_path);
|
||||
err_bundle_path:
|
||||
free(instance);
|
||||
err_instance:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void connect_port(LV2_Handle instance, uint32_t port, void * data_location) {
|
||||
@ -300,22 +172,18 @@ static void activate(LV2_Handle instance) {
|
||||
plugin_instance * i = (plugin_instance *)instance;
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
||||
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]);
|
||||
uint32_t k = param_data[j].index;
|
||||
i->params[j] = i->c[k] != NULL ? *i->c[k] : param_data[j].def;
|
||||
plugin_set_parameter(&i->p, k, 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];
|
||||
// why is this not correct?
|
||||
// i->sync_lock_flag = ATOMIC_FLAG_INIT;
|
||||
atomic_flag_clear(&i->sync_lock_flag);
|
||||
i->synced = 1;
|
||||
i->loaded = 0;
|
||||
# endif
|
||||
#endif
|
||||
plugin_reset(&i->p);
|
||||
}
|
||||
|
||||
static inline float clampf(float x, float m, float M) {
|
||||
return x < m ? m : (x > M ? M : x);
|
||||
}
|
||||
|
||||
static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||
plugin_instance * i = (plugin_instance *)instance;
|
||||
|
||||
@ -332,54 +200,30 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
# ifdef DATA_STATE_DSP_CUSTOM
|
||||
_Bool locked = !atomic_flag_test_and_set(&i->sync_lock_flag);
|
||||
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++) {
|
||||
if (i->c[j] == NULL)
|
||||
uint32_t k = param_data[j].index;
|
||||
if (i->c[k] == NULL)
|
||||
continue;
|
||||
float v = adjust_param(j, *i->c[j]);
|
||||
float v;
|
||||
if (param_data[j].flags & DATA_PARAM_BYPASS)
|
||||
v = *i->c[k] > 0.f ? 0.f : 1.f;
|
||||
else if (param_data[j].flags & DATA_PARAM_TOGGLED)
|
||||
v = *i->c[k] > 0.f ? 1.f : 0.f;
|
||||
else if (param_data[j].flags & DATA_PARAM_INTEGER)
|
||||
v = (int32_t)(*i->c[k] + (*i->c[k] >= 0.f ? 0.5f : -0.5f));
|
||||
else
|
||||
v = *i->c[k];
|
||||
|
||||
v = clampf(v, param_data[j].min, param_data[j].max);
|
||||
if (v != i->params[j]) {
|
||||
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);
|
||||
# ifdef DATA_STATE_DSP_CUSTOM
|
||||
}
|
||||
# endif
|
||||
plugin_set_parameter(&i->p, k, v);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef DATA_STATE_DSP_CUSTOM
|
||||
if (locked)
|
||||
atomic_flag_clear(&i->sync_lock_flag);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
// from https://lv2plug.in/book
|
||||
if (i->map)
|
||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||
for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) {
|
||||
if (i->x_midi[j] == NULL)
|
||||
continue;
|
||||
@ -421,6 +265,7 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void cleanup(LV2_Handle instance) {
|
||||
@ -428,70 +273,9 @@ static void cleanup(LV2_Handle instance) {
|
||||
plugin_fini(&i->p);
|
||||
if (i->mem)
|
||||
free(i->mem);
|
||||
free(i->bundle_path);
|
||||
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 = 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 = {
|
||||
/* .URI = */ DATA_LV2_URI,
|
||||
/* .instantiate = */ instantiate,
|
||||
@ -500,181 +284,9 @@ static const LV2_Descriptor descriptor = {
|
||||
/* .run = */ run,
|
||||
/* .deactivate = */ NULL,
|
||||
/* .cleanup = */ cleanup,
|
||||
#ifdef DATA_STATE_DSP_CUSTOM
|
||||
/* .extension_data = */ extension_data
|
||||
#else
|
||||
/* .extension_data = */ NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
||||
return index == 0 ? &descriptor : NULL;
|
||||
}
|
||||
|
||||
#ifdef DATA_UI
|
||||
typedef struct {
|
||||
plugin_ui * ui;
|
||||
char * bundle_path;
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
LV2UI_Write_Function write;
|
||||
LV2UI_Controller controller;
|
||||
char has_touch;
|
||||
LV2UI_Touch touch;
|
||||
# endif
|
||||
} ui_instance;
|
||||
|
||||
static const char * ui_get_bundle_path_cb(void *handle) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
return instance->bundle_path;
|
||||
}
|
||||
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
static void ui_set_parameter_begin_cb(void *handle, size_t index, float value) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
if (instance->has_touch) {
|
||||
index = index_to_param[index];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_set_parameter_cb(void *handle, size_t index, float value) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
index = index_to_param[index];
|
||||
value = adjust_param(index - CONTROL_INPUT_INDEX_OFFSET, value);
|
||||
instance->write(instance->controller, index, sizeof(float), 0, &value);
|
||||
}
|
||||
|
||||
static void ui_set_parameter_end_cb(void *handle, size_t index, float value) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
if (instance->has_touch) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const char * plugin_uri, const char * bundle_path, LV2UI_Write_Function write_function, LV2UI_Controller controller, LV2UI_Widget * widget, const LV2_Feature * const * features) {
|
||||
(void)descriptor;
|
||||
(void)plugin_uri;
|
||||
|
||||
ui_instance *instance = malloc(sizeof(ui_instance));
|
||||
if (instance == NULL)
|
||||
goto err_instance;
|
||||
|
||||
instance->bundle_path = strdup(bundle_path);
|
||||
if (instance->bundle_path == NULL)
|
||||
goto err_bundle_path;
|
||||
|
||||
char has_parent = 0;
|
||||
void *parent = NULL;
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
instance->has_touch = 0;
|
||||
# endif
|
||||
for (size_t i = 0; features[i] != NULL; i++) {
|
||||
if (!strcmp(features[i]->URI, LV2_UI__parent)) {
|
||||
has_parent = 1;
|
||||
parent = features[i]->data;
|
||||
}
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
else if (!strcmp(features[i]->URI, LV2_UI__touch)) {
|
||||
instance->has_touch = 1;
|
||||
instance->touch = *((LV2UI_Touch *)features[i]->data);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
plugin_ui_callbacks cbs = {
|
||||
/* .handle = */ (void *)instance,
|
||||
/* .format = */ "lv2",
|
||||
/* .get_bindir = */ ui_get_bundle_path_cb,
|
||||
/* .get_datadir = */ ui_get_bundle_path_cb,
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
/* .set_parameter_begin = */ ui_set_parameter_begin_cb,
|
||||
/* .set_parameter = */ ui_set_parameter_cb,
|
||||
/* .set_parameter_end = */ ui_set_parameter_end_cb,
|
||||
# endif
|
||||
};
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
instance->write = write_function;
|
||||
instance->controller = controller;
|
||||
# else
|
||||
(void)write_function;
|
||||
(void)controller;
|
||||
# endif
|
||||
instance->ui = plugin_ui_create(has_parent, parent, &cbs);
|
||||
if (instance->ui == NULL)
|
||||
goto err_create;
|
||||
|
||||
*widget = instance->ui->widget;
|
||||
return instance;
|
||||
|
||||
err_create:
|
||||
free(instance->bundle_path);
|
||||
err_bundle_path:
|
||||
free(instance);
|
||||
err_instance:
|
||||
*widget = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ui_cleanup(LV2UI_Handle handle) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
plugin_ui_free(instance->ui);
|
||||
free(instance->bundle_path);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||
static void ui_port_event(LV2UI_Handle handle, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void * buffer) {
|
||||
(void)buffer_size;
|
||||
(void)format;
|
||||
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||
if (port_index < CONTROL_OUTPUT_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)));
|
||||
}
|
||||
# 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));
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
static int ui_idle(LV2UI_Handle handle) {
|
||||
ui_instance *instance = (ui_instance *)handle;
|
||||
plugin_ui_idle(instance->ui);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void * ui_extension_data(const char * uri) {
|
||||
static const LV2UI_Idle_Interface idle = { ui_idle };
|
||||
if (!strcmp(uri, LV2_UI__idleInterface))
|
||||
return &idle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const LV2UI_Descriptor ui_descriptor = {
|
||||
/* .URI = */ DATA_LV2_UI_URI,
|
||||
/* .instantiate = */ ui_instantiate,
|
||||
/* .cleanup = */ ui_cleanup,
|
||||
# if DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N > 0
|
||||
/* .port_event = */ ui_port_event,
|
||||
# else
|
||||
/* .port_event = */ NULL,
|
||||
# endif
|
||||
/* .extension_data = */ ui_extension_data
|
||||
};
|
||||
|
||||
LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) {
|
||||
return index == 0 ? &ui_descriptor : NULL;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -34,8 +34,6 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
||||
{ 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: "state", uri: "http://lv2plug.in/ns/extensions/state#" },
|
||||
{ id: "ui", uri: "http://lv2plug.in/ns/extensions/ui#" },
|
||||
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
|
||||
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
|
||||
],
|
||||
@ -68,12 +66,7 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
ports: [],
|
||||
|
||||
ttlURI: function (uri) {
|
||||
if (uri.charAt(0) == "@") {
|
||||
if (uri.indexOf("#") == -1)
|
||||
return uri.substring(1);
|
||||
uri = data.tibia.lv2.expandURI(uri);
|
||||
}
|
||||
return "<" + uri + ">";
|
||||
return uri.charAt(0) == "@" ? uri.substring(1) : "<" + uri + ">";
|
||||
},
|
||||
|
||||
expandURI: function (uri) {
|
||||
@ -88,8 +81,6 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
for (var id in data.lv2.prefixes)
|
||||
data.tibia.lv2.prefixes.push({ id: id, uri: data.lv2.prefixes[id] });
|
||||
|
||||
data.tibia.lv2.prefixes.push({ id: "plugin", uri: data.tibia.lv2.expandURI(data.lv2.uri) + "#" });
|
||||
|
||||
var buses = data.product.buses;
|
||||
var audioPorts = [];
|
||||
var midiPorts = [];
|
||||
@ -97,16 +88,20 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
var b = buses[bi];
|
||||
if (b.type == "audio") {
|
||||
if (b.channels == "mono") {
|
||||
var e = { type: "audio", direction: b.direction, name: b.name, sidechain: b.sidechain, cv: b.cv, optional: b.optional, busIndex: bi, id: b.id };
|
||||
var e = { type: "audio", direction: b.direction, name: b.name, sidechain: b.sidechain, cv: b.cv, optional: b.optional, busIndex: bi };
|
||||
e.symbol = data.lv2.busSymbols[bi];
|
||||
audioPorts.push(e);
|
||||
} else {
|
||||
var e = { type: "audio", direction: b.direction, name: b.name + " Left", shortName: b.shortName + " L", sidechain: b.sidechain, cv: b.cv, busIndex: bi, id: b.id + "_l" };
|
||||
var e = { type: "audio", direction: b.direction, name: b.name + " Left", shortName: b.shortName + " L", sidechain: b.sidechain, cv: b.cv, busIndex: bi };
|
||||
e.symbol = data.lv2.busSymbols[bi] + "_L";
|
||||
audioPorts.push(e);
|
||||
var e = { type: "audio", direction: b.direction, name: b.name + " Right", shortName: b.shortName + " R", sidechain: b.sidechain, cv: b.cv, busIndex: bi, id: b.id + "_r" };
|
||||
var e = { type: "audio", direction: b.direction, name: b.name + " Right", shortName: b.shortName + " R", sidechain: b.sidechain, cv: b.cv, busIndex: bi };
|
||||
e.symbol = data.lv2.busSymbols[bi] + "_R";
|
||||
audioPorts.push(e);
|
||||
}
|
||||
} else {
|
||||
var e = { type: "midi", direction: b.direction, name: b.name, sidechain: b.sidechain, control: b.control, optional: b.optional, busIndex: bi, id: b.id };
|
||||
var e = { type: "midi", direction: b.direction, name: b.name, sidechain: b.sidechain, control: b.control, optional: b.optional, busIndex: bi };
|
||||
e.symbol = data.lv2.busSymbols[bi];
|
||||
midiPorts.push(e);
|
||||
}
|
||||
}
|
||||
@ -120,6 +115,7 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
var p = data.product.parameters[i];
|
||||
var e = Object.create(p);
|
||||
e.type = "control";
|
||||
e.symbol = data.lv2.parameterSymbols[i];
|
||||
e.paramIndex = i;
|
||||
ports.push(e);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Tibia
|
||||
#
|
||||
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
# Copyright (C) 2023, 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
|
||||
@ -18,177 +18,119 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := vst3
|
||||
|
||||
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)
|
||||
DLL_SUFFIX := .vst3
|
||||
VST3DIR := $(subst \,/,$(COMMONPROGRAMFILES))/VST3
|
||||
VST3DIR_USER := $(subst \,/,$(LOCALAPPDATA))/Programs/Common/VST3
|
||||
CC := gcc
|
||||
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
|
||||
DLL_SUFFIX = .vst3
|
||||
PLATFORM = x86_64-win
|
||||
VST3DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/VST3
|
||||
VST3DIR_USER = $(shell echo '${LOCALAPPDATA}' | sed 's:\\:/:g')/Programs/Common/VST3
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
else
|
||||
UNAME_S := $(shell uname -s)
|
||||
UNAME_S = $(shell uname -s)
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
DLL_SUFFIX :=
|
||||
VST3DIR := /Library/Audio/Plug-Ins/VST3
|
||||
VST3DIR_USER := $(HOME)/Library/Audio/Plug-Ins/VST3
|
||||
CC := clang
|
||||
CXX := clang++
|
||||
VST3_PLATFORM := MacOS
|
||||
DLL_SUFFIX =
|
||||
PLATFORM = MacOS
|
||||
VST3DIR = /Library/Audio/Plug-Ins/VST3
|
||||
VST3DIR_USER = ${HOME}/Library/Audio/Plug-Ins/VST3
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
else
|
||||
DLL_SUFFIX := .so
|
||||
VST3DIR := /usr/local/lib/vst3
|
||||
VST3DIR_USER := $(HOME)/.vst3
|
||||
CC := gcc
|
||||
CXX := g++
|
||||
VST3_PLATFORM := $(shell uname -m)-linux
|
||||
DLL_SUFFIX = .so
|
||||
PLATFORM = $(shell uname -m)-linux
|
||||
VST3DIR = /usr/local/lib/vst3
|
||||
VST3DIR_USER = ${HOME}/.vst3
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
endif
|
||||
DLL_DIR := Contents/$(VST3_PLATFORM)
|
||||
|
||||
BUILD_BIN_DIR := build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
BUILD_DATA_DIR := build/$(BUNDLE_DIR)/Contents/Resources
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
-include $(MKINC_DIR)/vars-pre.mk
|
||||
CFLAGS = -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CFLAGS} ${CFLAGS_EXTRA}
|
||||
|
||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CFLAGS_EXTRA) $(CFLAGS)
|
||||
LDFLAGS =
|
||||
LDFLAGS_ALL = -shared -lm ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||
|
||||
LDFLAGS :=
|
||||
LDFLAGS_ALL := -shared -lm $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||
CXXFLAGS = ${CFLAGS}
|
||||
CXXFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
||||
ifeq ($(HAS_UI), yes)
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,-framework,Foundation -Wl,-framework,Cocoa -Wl,-framework,Corevideo
|
||||
endif
|
||||
CFLAGS_ALL := ${CFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
LDFLAGS_ALL := ${LDFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
CXXFLAGS_ALL := ${CXXFLAGS_ALL} -arch arm64 -arch x86_64
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S), Linux)
|
||||
CFLAGS_ALL := $(CFLAGS_ALL) -D_GNU_SOURCE
|
||||
ifeq ($(HAS_UI), yes)
|
||||
CFLAGS_ALL := $(CFLAGS_ALL) $(shell pkg-config --cflags x11)
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) $(shell pkg-config --libs x11)
|
||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) $(shell pkg-config --cflags x11)
|
||||
endif
|
||||
endif
|
||||
BUNDLE_DIR = ${BUNDLE_NAME}.vst3
|
||||
|
||||
DLL_FILE := $(DLL_DIR)/$(BUNDLE_NAME)$(DLL_SUFFIX)
|
||||
DLL_DIR = Contents/${PLATFORM}
|
||||
DLL_FILE = ${DLL_DIR}/${BUNDLE_NAME}${DLL_SUFFIX}
|
||||
|
||||
C_SRCS := $(COMMON_DIR)/src/vst3.c $(C_SRCS_EXTRA)
|
||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
C_SRCS = ${COMMON_DIR}/src/vst3.c ${C_SRCS_EXTRA}
|
||||
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||
|
||||
M_SRCS := $(M_SRCS_EXTRA)
|
||||
M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
||||
CXX_SRCS = ${CXX_SRCS_EXTRA}
|
||||
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
|
||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
|
||||
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)
|
||||
ALL := $(ALL) build/$(BUNDLE_DIR)/Contents/Info.plist build/$(BUNDLE_DIR)/Contents/PkgInfo
|
||||
all: build/${BUNDLE_DIR}/${DLL_FILE} build/${BUNDLE_DIR}/Contents/Info.plist
|
||||
|
||||
build/${BUNDLE_DIR}/Contents/Info.plist: ${DATA_DIR}/data/Info.plist | build/${BUNDLE_DIR}/Contents
|
||||
cp $^ $@
|
||||
else
|
||||
all: build/${BUNDLE_DIR}/${DLL_FILE}
|
||||
endif
|
||||
|
||||
STRIP_ALL := build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||
STRIP_PHONY :=
|
||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
||||
|
||||
-include $(MKINC_DIR)/vars-extra.mk
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} | build/${BUNDLE_DIR}/${DLL_DIR}
|
||||
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
else
|
||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} ${CXX_OBJS} | build/${BUNDLE_DIR}/${DLL_DIR}
|
||||
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
build/$(BUNDLE_DIR)/Contents/%: $(DATA_DIR)/data/% | build/$(BUNDLE_DIR)/Contents
|
||||
cp $^ $@
|
||||
|
||||
build/$(BUNDLE_DIR)/Contents/%: $(COMMON_DIR)/data/% | build/$(BUNDLE_DIR)/Contents
|
||||
cp $^ $@
|
||||
endif
|
||||
|
||||
$(DIRS):
|
||||
build/${BUNDLE_DIR}/${DLL_DIR} build/obj:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
strip: $(STRIP_PREREQS)
|
||||
strip build/$(BUNDLE_DIR)/$(DLL_FILE)
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
|
||||
install: all
|
||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||
d=`echo $$d | sed 's:^build/::'` ; \
|
||||
echo mkdir -m 0755 -p "$(VST3DIR)/$$d"; \
|
||||
mkdir -m 0755 -p "$(VST3DIR)/$$d"; \
|
||||
done
|
||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||
d=`echo $$f | sed 's:^build/::'` ; \
|
||||
d=`dirname $$d`; \
|
||||
echo install -m $$m $$f "$(VST3DIR)/$$d"; \
|
||||
install -m $$m $$f "$(VST3DIR)/$$d"; \
|
||||
done
|
||||
mkdir -p -m 0755 "${VST3DIR}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${VST3DIR}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
install -m 0644 build/${BUNDLE_DIR}/Contents/Info.plist "${VST3DIR}/${BUNDLE_DIR}/Contents/Info.plist"
|
||||
|
||||
install-user: all
|
||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
||||
d=`echo $$d | sed 's:^build/::'` ; \
|
||||
echo mkdir -m 0755 -p "$(VST3DIR_USER)/$$d"; \
|
||||
mkdir -m 0755 -p "$(VST3DIR_USER)/$$d"; \
|
||||
done
|
||||
@for f in `find build/$(BUNDLE_DIR) -type f`; do \
|
||||
m=`[ -x $$f ] && echo 0755 || echo 0644`; \
|
||||
d=`echo $$f | sed 's:^build/::'` ; \
|
||||
d=`dirname $$d`; \
|
||||
echo install -m $$m $$f "$(VST3DIR_USER)/$$d"; \
|
||||
install -m $$m $$f "$(VST3DIR_USER)/$$d"; \
|
||||
done
|
||||
mkdir -p -m 0755 "${VST3DIR_USER}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${VST3DIR_USER}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
install -m 0644 build/${BUNDLE_DIR}/Contents/Info.plist "${VST3DIR_USER}/${BUNDLE_DIR}/Contents/Info.plist"
|
||||
|
||||
-include $(MKINC_DIR)/rules-extra.mk
|
||||
else
|
||||
|
||||
.PHONY: all clean strip $(STRIP_PHONY) install install-user
|
||||
install: all
|
||||
mkdir -p -m 0755 "${VST3DIR}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${VST3DIR}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
|
||||
install-user: all
|
||||
mkdir -p -m 0755 "${VST3DIR_USER}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${VST3DIR_USER}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: all clean install install-user
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
PERCENT := %
|
||||
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
|
||||
$(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$(M_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Tibia
|
||||
#
|
||||
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
# Copyright (C) 2023, 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
|
||||
@ -20,28 +20,13 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.vst3_make?.pluginDir || it.make?.pluginDir)}}
|
||||
PLUGIN_DIR := {{=it.vst3_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.vst3_make?.apiDir || it.make?.apiDir)}}
|
||||
API_DIR := {{=it.vst3_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
||||
{{?}}
|
||||
{{?(it.vst3_make?.mkincDir || it.make?.mkincDir)}}
|
||||
MKINC_DIR := {{=it.vst3_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
||||
{{?}}
|
||||
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.vst3_make && it.vst3_make.cflags ? it.vst3_make.cflags : ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.vst3_make && it.vst3_make.ldflags ? it.vst3_make.ldflags : ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.vst3_make && it.vst3_make.cxxflags ? it.vst3_make.cxxflags : ""}}
|
||||
|
||||
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
||||
HAS_PARAMETER_IN := {{=it.product.parameters.filter(x => x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.vst3_make && it.vst3_make.cSrcs ? it.vst3_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.vst3_make && it.vst3_make.cxxSrcs ? it.vst3_make.cxxSrcs : ""}}
|
||||
|
||||
{{?it.make?.extra}}
|
||||
{{=it.make.extra}}
|
||||
{{?}}
|
||||
{{?it.vst3_make?.extra}}
|
||||
{{=it.vst3_make.extra}}
|
||||
{{?}}
|
||||
COMMON_DIR := {{=it.vst3_make && it.vst3_make.commonDir ? it.vst3_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.vst3_make && it.vst3_make.dataDir ? it.vst3_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.vst3_make && it.vst3_make.pluginDir ? it.vst3_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
|
@ -1 +0,0 @@
|
||||
BNDL????
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
* Copyright (C) 2023, 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
|
||||
@ -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 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.12"
|
||||
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.12") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||
#define DATA_VST3_SDK_VERSION "VST 3.7.9"
|
||||
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.9") :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,15 +123,13 @@ static uint32_t midiInIndex[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||
#endif
|
||||
|
||||
#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
|
||||
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}}
|
||||
{
|
||||
{{?p.isBypass}}
|
||||
/* .id = */ {{=(it.tibia.sdbm("bypass ") & 0x7fffffff) >>> 0}},
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 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 },
|
||||
/* .units = */ { 0 },
|
||||
@ -140,7 +138,7 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
{{??}}
|
||||
/* .id = */ {{=(it.tibia.sdbm(p.id) & 0x7fffffff) >>> 0}},
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(p.name) & 0x7fffffff) >>> 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 },
|
||||
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
@ -153,9 +151,9 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
||||
{{~}}
|
||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}}
|
||||
{
|
||||
/* .id = */ {{=(it.tibia.sdbm(b.id + " channel pressure") & 0x7fffffff) >>> 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").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Channel Pressure") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
@ -163,9 +161,9 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
},
|
||||
{
|
||||
/* .id = */ {{=(it.tibia.sdbm(b.id + " pitch bend") & 0x7fffffff) >>> 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").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.5,
|
||||
@ -173,9 +171,9 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||
},
|
||||
{
|
||||
/* .id = */ {{=(it.tibia.sdbm(b.id + " mod wheel") & 0x7fffffff) >>> 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").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}},
|
||||
/* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { 0 },
|
||||
/* .stepCount = */ 0,
|
||||
/* .defaultNormalizedValue = */ 0.0,
|
||||
@ -192,7 +190,7 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
||||
# define DATA_PARAM_INTEGER (1<<2)
|
||||
# define DATA_PARAM_MAP_LOG (1<<3)
|
||||
|
||||
typedef struct {
|
||||
static struct {
|
||||
size_t index;
|
||||
double min;
|
||||
double max;
|
||||
@ -200,11 +198,8 @@ typedef struct {
|
||||
uint32_t flags;
|
||||
double mapK;
|
||||
// scalePoints?
|
||||
} ParameterData;
|
||||
|
||||
# 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}}
|
||||
} parameterData[DATA_PRODUCT_PARAMETERS_N] = {
|
||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||
{
|
||||
/* .index = */ {{=p.paramIndex}},
|
||||
/* .min = */ {{=p.minimum.toExponential()}},
|
||||
@ -215,30 +210,6 @@ static ParameterData parameterInData[DATA_PRODUCT_PARAMETERS_IN_N] = {
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
# endif
|
||||
|
||||
# if DATA_PRODUCT_PARAMETERS_OUT_N > 0
|
||||
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
|
||||
|
||||
@ -247,23 +218,3 @@ static size_t parameterInfoToDataIndex[DATA_PRODUCT_PARAMETERS_N] = {
|
||||
{{?it.product.parameters.find(x => x.isLatency)}}
|
||||
#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}}
|
||||
{{?}}
|
||||
|
||||
{{?it.product.ui}}
|
||||
#define DATA_UI
|
||||
#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
@ -15,7 +15,7 @@
|
||||
* 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, Paolo Marrone
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
var path = require("path");
|
||||
@ -49,27 +49,20 @@ module.exports = function (data, api, outputCommon, outputData) {
|
||||
"pc": "%",
|
||||
"s": "s",
|
||||
"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;
|
||||
}
|
||||
};
|
||||
|
||||
var inIdx = 0;
|
||||
var outIdx = 0;
|
||||
for (var i = 0; i < data.product.parameters.length; i++) {
|
||||
for (var i = 0; i < data.product.parameters.length; 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.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
||||
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Tibia
|
||||
#
|
||||
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
# Copyright (C) 2023, 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
|
||||
@ -18,16 +18,12 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
build/web/index.html: $(DATA_DIR)/src/index.html | build/web
|
||||
ALL += build/web/index.html build/web/cert.pem build/web/key.pem
|
||||
|
||||
build/web/index.html: ${DATA_DIR}/src/index.html | build
|
||||
cp $^ $@
|
||||
|
||||
build/web/key.pem: build/web/cert.pem
|
||||
|
||||
build/web/cert.pem: | build
|
||||
yes "" | openssl req -x509 -newkey rsa:2048 -keyout build/web/key.pem -out build/web/cert.pem -days 365 -nodes 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)
|
@ -24,7 +24,7 @@
|
||||
<head>
|
||||
<title>{{=it.product.name}}</title>
|
||||
<script type="module">
|
||||
import * as demo from "./{{=it.product.bundleName}}/module.js";
|
||||
import * as demo from "./{{=it.product.bundleName}}.js";
|
||||
window.demo = demo;
|
||||
</script>
|
||||
<script>
|
||||
@ -212,7 +212,7 @@ window.addEventListener("load", function (e) {
|
||||
module = new demo.Module();
|
||||
if (!midi && hasMidiInput)
|
||||
midi = await navigator.requestMIDIAccess();
|
||||
await module.init(audioCtx, "{{=it.product.bundleName}}/processor.js", "{{=it.product.bundleName}}/module.wasm");
|
||||
await module.init(audioCtx, "{{=it.product.bundleName}}_processor.js", "{{=it.product.bundleName}}.wasm");
|
||||
node = new demo.Node(module);
|
||||
node.connect(audioCtx.destination, audioOutputIndex);
|
||||
|
||||
|
@ -23,6 +23,5 @@ var sep = path.sep;
|
||||
|
||||
module.exports = function (data, api) {
|
||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||
api.copyFile(`vars-extra-web-demo.mk`, `vars-extra-web-demo.mk`);
|
||||
api.copyFile(`rules-extra-web-demo.mk`, `rules-extra-web-demo.mk`);
|
||||
api.copyFile(`demo.mk`, `demo.mk`);
|
||||
};
|
||||
|
@ -1,25 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
ALL := $(ALL) build/web/index.html build/web/cert.pem build/web/key.pem
|
||||
|
||||
STRIP_ALL := $(STRIP_ALL) build/web/index.html
|
||||
STRIP_PHONY := $(STRIP_PHONY) strip-web-demo
|
||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Tibia
|
||||
#
|
||||
# Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
# Copyright (C) 2023, 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
|
||||
@ -18,28 +18,19 @@
|
||||
# File author: Stefano D'Angelo
|
||||
#
|
||||
|
||||
TEMPLATE := web
|
||||
|
||||
include vars.mk
|
||||
|
||||
COMMON_DIR ?= .
|
||||
DATA_DIR ?= .
|
||||
PLUGIN_DIR ?= src
|
||||
API_DIR ?= $(PLUGIN_DIR)
|
||||
MKINC_DIR ?= $(COMMON_DIR)
|
||||
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||
DATA_DIR := $(or $(DATA_DIR),.)
|
||||
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||
|
||||
BUILD_BIN_DIR := build/web
|
||||
BUILD_DATA_DIR := build/web
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
|
||||
-include $(MKINC_DIR)/vars-pre.mk
|
||||
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}
|
||||
|
||||
CC := clang
|
||||
CXX := clang++
|
||||
|
||||
CFLAGS := -Ofast -Wall -Wpedantic -Wextra
|
||||
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,--no-entry \
|
||||
-Wl,--lto-O3 \
|
||||
@ -62,75 +53,61 @@ LDFLAGS_ALL := \
|
||||
-Wl,--export=processor_set_parameter \
|
||||
-Wl,-z,stack-size=$$((8*1024*1024)) \
|
||||
-nostdlib
|
||||
ifeq ($(HAS_MIDI_IN), yes)
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,--export=processor_midi_msg_in
|
||||
ifeq (${HAS_MIDI_IN}, yes)
|
||||
LDFLAGS_ALL += -Wl,--export=processor_midi_msg_in
|
||||
endif
|
||||
LDFLAGS_ALL := $(LDFLAGS_ALL) $(LDFLAGS_EXTRA) $(LDFLAGS)
|
||||
LDFLAGS_ALL += ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS_ALL := -I$(COMMON_DIR)/src -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) --target=wasm32 -flto -fvisibility=hidden $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
||||
CXXFLAGS = ${CFLAGS}
|
||||
CXXFLAGS_ALL = -I${COMMON_DIR}/src -I${DATA_DIR}/src -I${PLUGIN_DIR} --target=wasm32 -flto -fvisibility=hidden ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||
|
||||
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_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)))
|
||||
|
||||
ifeq ($(CXX_SRCS_EXTRA),)
|
||||
CXX_SRCS :=
|
||||
CXX_OBJS :=
|
||||
CXX_SRCS =
|
||||
CXX_OBJS =
|
||||
else
|
||||
CXX_SRCS := $(COMMON_DIR)/src/new.cpp $(CXX_SRCS_EXTRA)
|
||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
CXX_SRCS = ${COMMON_DIR}/src/new.cpp ${CXX_SRCS_EXTRA}
|
||||
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||
endif
|
||||
|
||||
DIRS := build build/obj build/web build/web/$(BUNDLE_NAME)
|
||||
ALL = build/web/${BUNDLE_NAME}.wasm build/web/${BUNDLE_NAME}_processor.js build/web/${BUNDLE_NAME}.js
|
||||
|
||||
ALL := build/web/$(BUNDLE_NAME)/module.wasm build/web/$(BUNDLE_NAME)/processor.js build/web/$(BUNDLE_NAME)/module.js
|
||||
default: all
|
||||
|
||||
STRIP_ALL := build/web/$(BUNDLE_NAME)/module.wasm build/web/$(BUNDLE_NAME)/processor.js build/web/$(BUNDLE_NAME)/module.js
|
||||
STRIP_PHONY :=
|
||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
||||
-include ${COMMON_DIR}/demo.mk
|
||||
|
||||
-include $(MKINC_DIR)/vars-extra.mk
|
||||
|
||||
all: $(ALL)
|
||||
all: ${ALL}
|
||||
|
||||
ifeq ($(CXX_OBJS),)
|
||||
build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) | build/web/$(BUNDLE_NAME)
|
||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/web/${BUNDLE_NAME}.wasm: ${C_OBJS} | build/web
|
||||
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
else
|
||||
build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) $(CXX_OBJS) | build/web/$(BUNDLE_NAME)
|
||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
||||
build/web/${BUNDLE_NAME}.wasm: ${C_OBJS} ${CXX_OBJS} | build/web
|
||||
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||
endif
|
||||
|
||||
build/web/$(BUNDLE_NAME)/processor.js: $(DATA_DIR)/src/processor.js | build/web/$(BUNDLE_NAME)
|
||||
build/web/${BUNDLE_NAME}_processor.js: ${DATA_DIR}/src/processor.js | build/web
|
||||
cp $^ $@
|
||||
|
||||
build/web/$(BUNDLE_NAME)/module.js: $(DATA_DIR)/src/module.js | build/web/$(BUNDLE_NAME)
|
||||
build/web/${BUNDLE_NAME}.js: ${DATA_DIR}/src/module.js | build/web
|
||||
cp $^ $@
|
||||
|
||||
$(DIRS):
|
||||
build/web build/obj:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
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
|
||||
|
||||
-include $(MKINC_DIR)/rules-extra.mk
|
||||
|
||||
.PHONY: all clean strip $(STRIP_PHONY)
|
||||
.PHONY: all clean
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
PERCENT := %
|
||||
|
||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
||||
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||
|
||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
||||
|
||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
||||
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||
|
@ -20,27 +20,15 @@
|
||||
|
||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
{{?(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 ?? "")}}
|
||||
{{?}}
|
||||
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.web_make && it.web_make.cflags ? it.web_make.cflags : ""}}
|
||||
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.web_make && it.web_make.ldflags ? it.web_make.ldflags : ""}}
|
||||
CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.web_make && it.web_make.cxxflags ? it.web_make.cxxflags : ""}}
|
||||
|
||||
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.web_make && it.web_make.cSrcs ? it.web_make.cSrcs : ""}}
|
||||
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.web_make && it.web_make.cxxSrcs ? it.web_make.cxxSrcs : ""}}
|
||||
|
||||
COMMON_DIR := {{=it.web_make && it.web_make.commonDir ? it.web_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||
DATA_DIR := {{=it.web_make && it.web_make.dataDir ? it.web_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||
PLUGIN_DIR := {{=it.web_make && it.web_make.pluginDir ? it.web_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||
|
||||
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
|
||||
*
|
||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
||||
* 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
|
||||
@ -44,7 +44,3 @@ static size_t param_out_index[DATA_PRODUCT_PARAMETERS_OUTPUT_N] = {
|
||||
{{~it.product.parameters :p:i}}{{?p.direction == "output"}}{{=i}}, {{?}}{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
{{?it.product.state && it.product.state.dspCustom}}
|
||||
#define DATA_STATE_DSP_CUSTOM
|
||||
{{?}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2022-2025 Orastron Srl unipersonale
|
||||
* Copyright (C) 2022-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
|
||||
@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "plugin_api.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include "string.h"
|
||||
@ -46,22 +45,11 @@ typedef struct {
|
||||
} instance;
|
||||
|
||||
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));
|
||||
if (i == NULL)
|
||||
return NULL;
|
||||
|
||||
plugin_callbacks cbs = {
|
||||
/* .handle = */ NULL,
|
||||
/* .format = */ "web",
|
||||
/* .get_bindir = */ NULL,
|
||||
/* .get_datadir = */ NULL
|
||||
};
|
||||
plugin_init(&i->p, &cbs);
|
||||
plugin_init(&i->p);
|
||||
|
||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
||||
for (size_t j = 0; j < DATA_PRODUCT_PARAMETERS_N; j++)
|
||||
|
@ -127,7 +127,7 @@ void *realloc(void *ptr, size_t size) {
|
||||
}
|
||||
|
||||
void *calloc(size_t nmemb, size_t size) {
|
||||
if (nmemb == 0 || SIZE_MAX / nmemb < size || (SIZE_MAX / nmemb == size && SIZE_MAX % nmemb != 0))
|
||||
if (nmemb == 0 || SIZE_MAX / nmemb > size || (SIZE_MAX / nmemb == size && SIZE_MAX % nmemb != 0))
|
||||
return NULL;
|
||||
size_t s = nmemb * size;
|
||||
void *m = malloc(s);
|
||||
|
21
test/android-make.json
Normal file
21
test/android-make.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"android_make": {
|
||||
"cxxflags": "-I../../../miniaudio",
|
||||
"keyStore": "keystore.jks",
|
||||
"keyAlias": "androidkey",
|
||||
"storePass": "android",
|
||||
"keyPass": "android",
|
||||
"sdkDir": "${HOME}/Android/Sdk",
|
||||
"ndkVersion": "25.2.9519653",
|
||||
"buildToolsVersion": "34.0.0",
|
||||
"androidxDir": "${HOME}/Android/androidx",
|
||||
"kotlinDir": "${HOME}/Android/kotlin",
|
||||
"androidVersion": "34",
|
||||
"androidxCoreVersion": "1.10.1",
|
||||
"androidxLifecycleCommonVersion": "2.6.1",
|
||||
"androidxVersionedparcelableVersion": "1.1.1",
|
||||
"kotlinStdlibVersion": "1.9.0",
|
||||
"kotlinxCoroutinesCoreVersion": "1.7.3",
|
||||
"kotlinxCoroutinesCoreJVMVersion": "1.7.3"
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"android": {
|
||||
"javaPackageName": "com.example.tibia_test",
|
||||
"androidVersion": "36"
|
||||
"javaPackageName": "com.example.tibia_test"
|
||||
}
|
||||
}
|
||||
|
6
test/cmd-make.json
Normal file
6
test/cmd-make.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"cmd_make": {
|
||||
"tinywavDir": "../../../tinywav",
|
||||
"midiParserDir": "../../../midi-parser"
|
||||
}
|
||||
}
|
6
test/cmd.json
Normal file
6
test/cmd.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"cmd": {
|
||||
"busIds": [ "input", "output", "midi_in", "midi_out" ],
|
||||
"parameterIds": [ "gain", "delay", "cutoff", "bypass", "yz1" ]
|
||||
}
|
||||
}
|
5
test/daisy-seed-make.json
Normal file
5
test/daisy-seed-make.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"daisy_seed_make": {
|
||||
"libdaisyDir": "../../../libDaisy"
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ios_make": {
|
||||
"headerSearchPaths": [ "../../../../../miniaudio" ],
|
||||
"deploymentTarget": "16.6"
|
||||
"deploymentTarget": 16.6
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"ios": {
|
||||
"productBundleIdentifier": "com.example.tibia-test"
|
||||
"productBundleIdentifier": "com.example.tibia_test"
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
"uri": "@example:tibia_test",
|
||||
"project": "@example:project",
|
||||
"types": [ "@lv2:AmplifierPlugin" ],
|
||||
"version": "1.0"
|
||||
"version": "1.0",
|
||||
"busSymbols": [ "input", "output", "midi_in", "midi_out" ],
|
||||
"parameterSymbols": [ "gain", "delay", "cutoff", "enabled", "yz1" ]
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Tibia
|
||||
*
|
||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
||||
* Copyright (C) 2023, 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
|
||||
@ -18,8 +18,6 @@
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct plugin {
|
||||
float sample_rate;
|
||||
size_t delay_line_length;
|
||||
@ -36,9 +34,8 @@ typedef struct plugin {
|
||||
float yz1;
|
||||
} plugin;
|
||||
|
||||
static void plugin_init(plugin *instance, const plugin_callbacks *cbs) {
|
||||
static void plugin_init(plugin *instance) {
|
||||
(void)instance;
|
||||
(void)cbs;
|
||||
}
|
||||
|
||||
static void plugin_fini(plugin *instance) {
|
||||
@ -70,16 +67,17 @@ static void plugin_reset(plugin *instance) {
|
||||
|
||||
static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
||||
switch (index) {
|
||||
case plugin_parameter_gain:
|
||||
instance->gain = value;
|
||||
case 0:
|
||||
//approx instance->gain = powf(10.f, 0.05f * value);
|
||||
instance->gain = ((2.6039890429412597e-4f * value + 0.032131027163547855f) * value + 1.f) / ((0.0012705124328080768f * value - 0.0666763481312185f) * value + 1.f);
|
||||
break;
|
||||
case plugin_parameter_delay:
|
||||
instance->delay = value;
|
||||
case 1:
|
||||
instance->delay = 0.001f * value;
|
||||
break;
|
||||
case plugin_parameter_cutoff:
|
||||
case 2:
|
||||
instance->cutoff = value;
|
||||
break;
|
||||
case plugin_parameter_bypass:
|
||||
case 3:
|
||||
instance->bypass = value >= 0.5f;
|
||||
break;
|
||||
}
|
||||
@ -95,10 +93,8 @@ 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) {
|
||||
//approx const float gain = powf(10.f, 0.05f * instance->gain);
|
||||
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);
|
||||
//approx size_t delay = roundf(instance->sample_rate * instance->delay);
|
||||
size_t delay = (size_t)(instance->sample_rate * instance->delay + 0.5f);
|
||||
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++) {
|
||||
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
||||
@ -108,7 +104,7 @@ static void plugin_process(plugin *instance, const float **inputs, float **outpu
|
||||
instance->delay_line_cur = 0;
|
||||
const float y = x + mA1 * (instance->z1 - x);
|
||||
instance->z1 = y;
|
||||
outputs[0][i] = instance->bypass ? inputs[0][i] : gain * y;
|
||||
outputs[0][i] = instance->bypass ? inputs[0][i] : instance->gain * y;
|
||||
instance->yz1 = outputs[0][i];
|
||||
}
|
||||
}
|
||||
@ -119,63 +115,3 @@ 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));
|
||||
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;
|
||||
}
|
||||
|
247
test/plugin_ui.h
247
test/plugin_ui.h
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* 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, Paolo Marrone
|
||||
*/
|
||||
|
||||
#include "vinci.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
void *widget;
|
||||
|
||||
vinci *vinci;
|
||||
window *window;
|
||||
int param_down;
|
||||
|
||||
float gain;
|
||||
float delay;
|
||||
float cutoff;
|
||||
char bypass;
|
||||
float y_z1;
|
||||
|
||||
plugin_ui_callbacks cbs;
|
||||
} plugin_ui;
|
||||
|
||||
#define WIDTH 600.0
|
||||
#define HEIGHT 400.0
|
||||
|
||||
static void plugin_ui_get_default_size(uint32_t *width, uint32_t *height) {
|
||||
*width = WIDTH;
|
||||
*height = HEIGHT;
|
||||
}
|
||||
|
||||
static void draw_rect(window *w, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color) {
|
||||
uint32_t *data = (uint32_t*) malloc(width * height * 4);
|
||||
uint32_t p = 0;
|
||||
for (uint32_t i = 0; i < height; i++)
|
||||
for (uint32_t j = 0; j < width; j++, p++)
|
||||
data[p] = color;
|
||||
window_draw(w, (unsigned char*)data, 0, 0, width, height, x, y, width, height);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void draw_slider(plugin_ui *pui, int id, float value) {
|
||||
const int w = window_get_width(pui->window);
|
||||
const int h = window_get_height(pui->window);
|
||||
draw_rect(pui->window, 0.1 * w, 0.15 * (id + 1) * h, 0.8 * w * value, 0.1 * h, 0x6789ab);
|
||||
draw_rect(pui->window, 0.1 * w + 0.8 * w * value, 0.15 * (id + 1) * h, 0.8 * w * (1.f - value), 0.1 * h, 0x1223bc);
|
||||
}
|
||||
|
||||
static void draw_button(plugin_ui *pui, int id, char value) {
|
||||
const int w = window_get_width(pui->window);
|
||||
const int h = window_get_height(pui->window);
|
||||
draw_rect(pui->window, 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 on_mouse_release (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 (pui->param_down == 4)
|
||||
if (x >= 0.4 * w && x <= 0.6 * w && y >= 0.6 * h && y <= 0.7 * h) {
|
||||
pui->bypass = !pui->bypass;
|
||||
pui->cbs.set_parameter(pui->cbs.handle, 3, pui->bypass ? 1.f : 0.f);
|
||||
draw_button(pui, 3, pui->bypass);
|
||||
}
|
||||
|
||||
if (pui->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_end(pui->cbs.handle, 0, -60.f + 80.f * pui->gain);
|
||||
draw_slider(pui, 0, pui->gain);
|
||||
break;
|
||||
case 1:
|
||||
pui->delay = v;
|
||||
pui->cbs.set_parameter_end(pui->cbs.handle, 1, 1000.f * pui->delay);
|
||||
draw_slider(pui, 1, pui->delay);
|
||||
break;
|
||||
case 2:
|
||||
pui->cutoff = v;
|
||||
pui->cbs.set_parameter_end(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff));
|
||||
draw_slider(pui, 2, pui->cutoff);
|
||||
break;
|
||||
}
|
||||
pui->param_down = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_mouse_move (window *win, int32_t x, int32_t y, uint32_t state) {
|
||||
(void) y;
|
||||
(void) state;
|
||||
|
||||
plugin_ui *pui = (plugin_ui*) window_get_data(win);
|
||||
const int w = window_get_width(win);
|
||||
|
||||
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;
|
||||
case 1:
|
||||
pui->delay = v;
|
||||
pui->cbs.set_parameter(pui->cbs.handle, 1, 1000.f * pui->delay);
|
||||
draw_slider(pui, 1, pui->delay);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
plugin_ui *instance = malloc(sizeof(plugin_ui));
|
||||
if (instance == 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->vinci = vinci_new();
|
||||
instance->window = window_new(instance->vinci, has_parent ? parent : NULL, WIDTH, HEIGHT, &wcbs);
|
||||
instance->widget = window_get_handle(instance->window);
|
||||
window_set_data(instance->window, (void*) instance);
|
||||
window_show(instance->window);
|
||||
|
||||
// just some valid values to allow drawing
|
||||
instance->gain = 0.f;
|
||||
instance->delay = 0.f;
|
||||
instance->cutoff = 0.f;
|
||||
instance->bypass = 0;
|
||||
instance->y_z1 = 0.f;
|
||||
|
||||
on_window_resize(instance->window, window_get_width(instance->window), window_get_height(instance->window));
|
||||
|
||||
instance->cbs = *cbs;
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void plugin_ui_free(plugin_ui *instance) {
|
||||
window_free(instance->window);
|
||||
vinci_destroy(instance->vinci);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void plugin_ui_idle(plugin_ui *instance) {
|
||||
vinci_idle(instance->vinci);
|
||||
}
|
||||
|
||||
static void plugin_ui_set_parameter(plugin_ui *instance, size_t index, float value) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
instance->gain = 0.0125f * value + 0.75f;
|
||||
draw_slider(instance, 0, instance->gain);
|
||||
break;
|
||||
case 1:
|
||||
instance->delay = 0.001f * value;
|
||||
draw_slider(instance, 1, instance->delay);
|
||||
break;
|
||||
case 2:
|
||||
// (bad) approx log unmap
|
||||
instance->cutoff = (1.0326554320337176f * value - 20.65310864067435f) / (value + 632.4555320336754f);
|
||||
draw_slider(instance, 2, instance->cutoff);
|
||||
break;
|
||||
case 3:
|
||||
instance->bypass = value >= 0.5f;
|
||||
draw_button(instance, 3, instance->bypass);
|
||||
break;
|
||||
case 4:
|
||||
instance->y_z1 = 0.5f * value + 0.5f;
|
||||
draw_slider(instance, 4, instance->y_z1);
|
||||
break;
|
||||
}
|
||||
}
|
@ -11,7 +11,6 @@
|
||||
"channels": "mono",
|
||||
"name": "Input",
|
||||
"shortName": "Input",
|
||||
"id": "input",
|
||||
"sidechain": false,
|
||||
"cv": false,
|
||||
"optional": false
|
||||
@ -22,7 +21,6 @@
|
||||
"channels": "mono",
|
||||
"name": "Output",
|
||||
"shortName": "Output",
|
||||
"id": "output",
|
||||
"sidechain": false,
|
||||
"cv": false,
|
||||
"optional": false
|
||||
@ -32,7 +30,6 @@
|
||||
"direction": "input",
|
||||
"name": "MIDI input",
|
||||
"shortName": "MIDI input",
|
||||
"id": "midi_in",
|
||||
"sidechain": true,
|
||||
"control": true,
|
||||
"optional": true
|
||||
@ -42,7 +39,6 @@
|
||||
{
|
||||
"name": "Gain",
|
||||
"shortName": "Gain",
|
||||
"id": "gain",
|
||||
"direction": "input",
|
||||
"isBypass": false,
|
||||
"isLatency": false,
|
||||
@ -64,7 +60,6 @@
|
||||
{
|
||||
"name": "Delay",
|
||||
"shortName": "Delay",
|
||||
"id": "delay",
|
||||
"direction": "input",
|
||||
"isBypass": false,
|
||||
"isLatency": false,
|
||||
@ -81,7 +76,6 @@
|
||||
{
|
||||
"name": "Cutoff",
|
||||
"shortName": "Cutoff",
|
||||
"id": "cutoff",
|
||||
"direction": "input",
|
||||
"isBypass": false,
|
||||
"isLatency": false,
|
||||
@ -98,7 +92,6 @@
|
||||
{
|
||||
"name": "Bypass",
|
||||
"shortName": "Bypass",
|
||||
"id": "bypass",
|
||||
"direction": "input",
|
||||
"isBypass": true,
|
||||
"isLatency": false,
|
||||
@ -119,7 +112,6 @@
|
||||
{
|
||||
"name": "yz1",
|
||||
"shortName": "yz1",
|
||||
"id": "yz1",
|
||||
"direction": "output",
|
||||
"isBypass": false,
|
||||
"isLatency": false,
|
||||
@ -133,13 +125,6 @@
|
||||
"unit": "",
|
||||
"map": "linear"
|
||||
}
|
||||
],
|
||||
"ui": {
|
||||
"userResizable": true,
|
||||
"selfResizable": false
|
||||
},
|
||||
"state": {
|
||||
"dspCustom": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
include rules-extra-web-demo.mk
|
24
test/run.sh
24
test/run.sh
@ -1,42 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
dir=`dirname $0`
|
||||
|
||||
$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-make $dir/../out/vst3
|
||||
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/vst3.json,$dir/vst3-make.json $dir/../templates/vst3-make $dir/../out/vst3
|
||||
cp $dir/plugin.h $dir/../out/vst3/src
|
||||
|
||||
$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-make $dir/../out/lv2
|
||||
cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src
|
||||
cp $dir/vars-pre.mk $dir/../out/lv2
|
||||
cp $dir/plugin.h $dir/../out/lv2/src
|
||||
|
||||
$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-demo $dir/../out/web
|
||||
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/android.json $dir/../templates/android $dir/../out/android
|
||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android-make $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
|
||||
cp $dir/keystore.jks $dir/../out/android
|
||||
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/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
|
||||
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/cmd $dir/../out/cmd
|
||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd-make $dir/../out/cmd
|
||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/cmd.json $dir/../templates/cmd $dir/../out/cmd
|
||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/cmd.json,$dir/cmd-make.json $dir/../templates/cmd-make $dir/../out/cmd
|
||||
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/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-make $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
|
||||
cp $dir/plugin.h $dir/../out/daisy-seed/src
|
||||
cp $dir/vars-pre.mk $dir/../out/daisy-seed
|
||||
|
@ -1 +0,0 @@
|
||||
include vars-extra-web-demo.mk
|
@ -1,66 +0,0 @@
|
||||
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
|
5
test/vst3-make.json
Normal file
5
test/vst3-make.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"vst3_make": {
|
||||
"cflags": "-I../../../vst3_c_api"
|
||||
}
|
||||
}
|
@ -6,6 +6,6 @@
|
||||
"controller": {
|
||||
"cid": "ecf4f431312f44fbb37b88c545ae9993"
|
||||
},
|
||||
"subCategory": "Fx"
|
||||
"subCategory": "FX"
|
||||
}
|
||||
}
|
||||
|
47
tibia
47
tibia
@ -2,56 +2,37 @@
|
||||
|
||||
function usage() {
|
||||
console.log("Usage:");
|
||||
console.log(" tibia file1.json,file2.json,...filen.json template outDirectory [override1=value1] [override2=value2] ...");
|
||||
console.log(" tibia --common template outDirectory [override1=value1] [override2=value2] ...");
|
||||
console.log(" tibia --data file1.json,file2.json,...filen.json template outDirectory [override1=value1] [override2=value2] ...");
|
||||
console.log(" tibia file1.json,file2.json,...filen.json template outDirectory");
|
||||
console.log(" tibia --common template outDirectory");
|
||||
console.log(" tibia --data file1.json,file2.json,...filen.json template outDirectory");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var jsonFiles, template, outputDir, outputCommon, outputData, i;
|
||||
var jsonFiles, template, outputDir, outputCommon, outputData;
|
||||
if (process.argv[2] == "--common") {
|
||||
if (process.argv.length < 5)
|
||||
if (process.argv.length != 5)
|
||||
usage();
|
||||
jsonFiles = [];
|
||||
template = process.argv[3];
|
||||
outputDir = process.argv[4];
|
||||
outputCommon = true;
|
||||
outputData = false;
|
||||
i = 5;
|
||||
} else if (process.argv[2] == "--data") {
|
||||
if (process.argv.length < 6)
|
||||
if (process.argv.length != 6)
|
||||
usage();
|
||||
jsonFiles = process.argv[3].split(",");
|
||||
template = process.argv[4];
|
||||
outputDir = process.argv[5];
|
||||
outputCommon = false;
|
||||
outputData = true;
|
||||
i = 6;
|
||||
} else {
|
||||
if (process.argv.length < 5)
|
||||
if (process.argv.length != 5)
|
||||
usage();
|
||||
jsonFiles = process.argv[2].split(",");
|
||||
template = process.argv[3];
|
||||
outputDir = process.argv[4];
|
||||
outputCommon = 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");
|
||||
@ -73,13 +54,6 @@ for (var i = 0; i < jsonFiles.length; i++) {
|
||||
for (var k in d)
|
||||
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) {
|
||||
@ -171,13 +145,6 @@ data.tibia = {
|
||||
}
|
||||
}
|
||||
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