Compare commits
No commits in common. "main" and "v0.0.3" 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
|
## Legal
|
||||||
|
|
||||||
Copyright (C) 2021-2025 Orastron Srl unipersonale.
|
Copyright (C) 2021-2024 Orastron Srl unipersonale.
|
||||||
|
|
||||||
Authors: Stefano D'Angelo, Paolo Marrone.
|
Authors: Stefano D'Angelo, Paolo Marrone.
|
||||||
|
|
||||||
|
46
notes
46
notes
@ -5,21 +5,18 @@ company {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
url:
|
url:
|
||||||
VST3: PFactoryInfo.url
|
VST3: PFactoryInfo.url
|
||||||
LV2: manifest.ttl doap:maintainer rdfs:seeAlso
|
LV2: manifest.ttl doap:maintainer rdfs:seeAlso
|
||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
email:
|
email:
|
||||||
VST3: PFactoryInfo.email
|
VST3: PFactoryInfo.email
|
||||||
LV2: manifest.ttl doap:maintainer foaf:mbox
|
LV2: manifest.ttl doap:maintainer foaf:mbox
|
||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
}
|
}
|
||||||
|
|
||||||
product {
|
product {
|
||||||
@ -29,28 +26,24 @@ product {
|
|||||||
web: web-demo <title> and <h1>
|
web: web-demo <title> and <h1>
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: index.html <title>, AndroidManifest.xml <application> <activity> android:label
|
android: index.html <title>, AndroidManifest.xml <application> <activity> android:label
|
||||||
ios: index.html <title>
|
|
||||||
version:
|
version:
|
||||||
VST3: PClassInfo{2,W}.version (first 3 numbers)
|
VST3: PClassInfo{2,W}.version (first 3 numbers)
|
||||||
LV2: not used
|
LV2: not used
|
||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
buildVersion:
|
buildVersion:
|
||||||
VST3: PClassInfo{2,W}.version (last number)
|
VST3: PClassInfo{2,W}.version (last number)
|
||||||
LV2: not used
|
LV2: not used
|
||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
bundleName:
|
bundleName:
|
||||||
VST3: plugin folder name, plugin .dll name, Info.plist
|
VST3: plugin folder name, plugin .dll name, Info.plist
|
||||||
LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary
|
LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary
|
||||||
web: registerProcessor(), output file names
|
web: registerProcessor(), output file names
|
||||||
cmd: executable file name
|
cmd: executable file name
|
||||||
android: .so/.apk filenames
|
android: .so/.apk filenames
|
||||||
ios: xcodegen name and target name, xcodeproj filename
|
|
||||||
buses: [
|
buses: [
|
||||||
{
|
{
|
||||||
name:
|
name:
|
||||||
@ -60,7 +53,6 @@ product {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
shortName:
|
shortName:
|
||||||
bus short name string, required
|
bus short name string, required
|
||||||
VST3: not used
|
VST3: not used
|
||||||
@ -68,15 +60,6 @@ product {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: 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:
|
direction:
|
||||||
"input" or "output", required
|
"input" or "output", required
|
||||||
VST3: BusInfo flags - lots of implications
|
VST3: BusInfo flags - lots of implications
|
||||||
@ -84,7 +67,6 @@ product {
|
|||||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
|
||||||
type:
|
type:
|
||||||
"audio" or "midi", required
|
"audio" or "midi", required
|
||||||
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications
|
||||||
@ -92,7 +74,6 @@ product {
|
|||||||
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
web: AudioWorkletNode.{numberOfInputs,numberOfOutputs,outputChannelCount} - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
|
||||||
channels:
|
channels:
|
||||||
"mono" or "stereo", audio type only, required
|
"mono" or "stereo", audio type only, required
|
||||||
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
VST3: BusInfo channelCount, plugin get/set bus arrangements
|
||||||
@ -100,7 +81,6 @@ product {
|
|||||||
web: AudioWorkletNode.outputChannelCount - lots of implications
|
web: AudioWorkletNode.outputChannelCount - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
|
||||||
sidechain:
|
sidechain:
|
||||||
bus is not part of main audio path (sidechain)? boolean, default false
|
bus is not part of main audio path (sidechain)? boolean, default false
|
||||||
VST3: BusInfo busType
|
VST3: BusInfo busType
|
||||||
@ -115,7 +95,6 @@ product {
|
|||||||
web: web-demo choice of audio I/O buses
|
web: web-demo choice of audio I/O buses
|
||||||
cmd: choice of audio I/O buses
|
cmd: choice of audio I/O buses
|
||||||
android: choice of audio I/O buses
|
android: choice of audio I/O buses
|
||||||
ios: choice of audio I/O buses
|
|
||||||
control:
|
control:
|
||||||
bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false
|
bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false
|
||||||
VST3: not used
|
VST3: not used
|
||||||
@ -123,7 +102,6 @@ product {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
optional:
|
optional:
|
||||||
bus is optionally connected? boolean, default false
|
bus is optionally connected? boolean, default false
|
||||||
VST3: BusInfo flags, plugin initialize, activate bus, set active
|
VST3: BusInfo flags, plugin initialize, activate bus, set active
|
||||||
@ -131,7 +109,6 @@ product {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: whether to pass NULLs if not chosen audio I/O buses
|
cmd: whether to pass NULLs if not chosen audio I/O buses
|
||||||
android: 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: [
|
parameters: [
|
||||||
@ -143,7 +120,6 @@ product {
|
|||||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <label>
|
web: AudioWorkletProcessor.parameterDescriptors, web-demo <label>
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: index.html <label>
|
android: index.html <label>
|
||||||
ios: index.html <label>
|
|
||||||
shortName:
|
shortName:
|
||||||
parameter short name string, required
|
parameter short name string, required
|
||||||
VST3: ParameterInfo shortTitle
|
VST3: ParameterInfo shortTitle
|
||||||
@ -151,15 +127,6 @@ product {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: 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:
|
direction:
|
||||||
"input" or "output", required
|
"input" or "output", required
|
||||||
VST3: ParameterInfo flags - lots of implications
|
VST3: ParameterInfo flags - lots of implications
|
||||||
@ -167,7 +134,6 @@ product {
|
|||||||
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
web: AudioWorkletProcessor.parameterDescriptors, web-demo <range> readonly/input listener - lots of implications
|
||||||
cmd: lots of places
|
cmd: lots of places
|
||||||
android: lots of places
|
android: lots of places
|
||||||
ios: lots of places
|
|
||||||
isBypass:
|
isBypass:
|
||||||
parameter is bypass/enabled? boolean - lots of implications, default false
|
parameter is bypass/enabled? boolean - lots of implications, default false
|
||||||
VST3: ParameterInfo, controller get/set parameter/state
|
VST3: ParameterInfo, controller get/set parameter/state
|
||||||
@ -175,7 +141,6 @@ product {
|
|||||||
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
|
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
|
||||||
cmd: set parameter
|
cmd: set parameter
|
||||||
android: JNI set parameter, index.html <range> min/max/step
|
android: JNI set parameter, index.html <range> min/max/step
|
||||||
ios: native set parameter, index.html <range> min/max/step
|
|
||||||
isLatency:
|
isLatency:
|
||||||
parameter is latency output? boolean - lots of implications, default false
|
parameter is latency output? boolean - lots of implications, default false
|
||||||
VST3: TBD
|
VST3: TBD
|
||||||
@ -183,7 +148,6 @@ product {
|
|||||||
web: not (yet) used
|
web: not (yet) used
|
||||||
cmd: not (yet) used
|
cmd: not (yet) used
|
||||||
android: not (yet) used
|
android: not (yet) used
|
||||||
ios: not (yet) used
|
|
||||||
defaultValue:
|
defaultValue:
|
||||||
default value, number, mapped, required for non-bypass
|
default value, number, mapped, required for non-bypass
|
||||||
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
VST3: ParameterInfo defaultNormalizedValue, controller initialize
|
||||||
@ -191,7 +155,6 @@ product {
|
|||||||
web: AudioWorkletProcessor.parameterDescriptors, processor_new(), web-demo initial <range> value and value <span> innerText
|
web: AudioWorkletProcessor.parameterDescriptors, processor_new(), web-demo initial <range> value and value <span> innerText
|
||||||
cmd: default parameter value
|
cmd: default parameter value
|
||||||
android: JNI set parameter initial value, index.html initial <range> 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:
|
||||||
minimum value, number, mapped, required for non-bypass
|
minimum value, number, mapped, required for non-bypass
|
||||||
VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped)
|
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
|
web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping
|
||||||
cmd: set parameter (value clamped)
|
cmd: set parameter (value clamped)
|
||||||
android: JNI set parameter (value clamped), index.html <range> mapping
|
android: JNI set parameter (value clamped), index.html <range> mapping
|
||||||
ios: native set parameter (value clamped), index.html <range> mapping
|
|
||||||
maximum:
|
maximum:
|
||||||
maximum value, number, mapped, required for non-bypass
|
maximum value, number, mapped, required for non-bypass
|
||||||
VST3: ParameterInfo stepCount, defaultNormalizedValue, controller get/set parameter (value clamped)
|
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
|
web: AudioWorkletProcessor.parameterDescriptors, AudioWorkletProcessor.process() (value clamped), web-demo <range> mapping
|
||||||
cmd: set parameter (value clamped)
|
cmd: set parameter (value clamped)
|
||||||
android: JNI set parameter (value clamped), index.html <range> mapping
|
android: JNI set parameter (value clamped), index.html <range> mapping
|
||||||
ios: native set parameter (value clamped), index.html <range> mapping
|
|
||||||
toggled:
|
toggled:
|
||||||
parameter is on/off? boolean, default false
|
parameter is on/off? boolean, default false
|
||||||
VST3: ParameterInfo stepCount, controller set parameter/state
|
VST3: ParameterInfo stepCount, controller set parameter/state
|
||||||
@ -215,7 +176,6 @@ product {
|
|||||||
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
|
web: AudoWorkletProcessor.process(), web-demo <range> min/max/step
|
||||||
cmd: set parameter
|
cmd: set parameter
|
||||||
android: JNI set parameter, index.html <range> min/max/step
|
android: JNI set parameter, index.html <range> min/max/step
|
||||||
ios: native set parameter, index.html <range> min/max/step
|
|
||||||
optional:
|
optional:
|
||||||
parameter is optionally connected? boolean, default false
|
parameter is optionally connected? boolean, default false
|
||||||
VST3: not used
|
VST3: not used
|
||||||
@ -223,7 +183,6 @@ product {
|
|||||||
web: not used
|
web: not used
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: not used
|
android: not used
|
||||||
ios: not used
|
|
||||||
integer:
|
integer:
|
||||||
parameter values are integers? boolean, default false
|
parameter values are integers? boolean, default false
|
||||||
VST3: ParameterInfo stepCount, controller set parameter/state
|
VST3: ParameterInfo stepCount, controller set parameter/state
|
||||||
@ -231,7 +190,6 @@ product {
|
|||||||
web: AudoWorkletProcessor.process(), web-demo <range> step
|
web: AudoWorkletProcessor.process(), web-demo <range> step
|
||||||
cmd: set parameter
|
cmd: set parameter
|
||||||
android: JNI set parameter, index.html <range> step
|
android: JNI set parameter, index.html <range> step
|
||||||
ios: native set parameter, index.html <range> step
|
|
||||||
scalePoints:
|
scalePoints:
|
||||||
{ "label1": value1, "label2", value2, ... }
|
{ "label1": value1, "label2", value2, ... }
|
||||||
labeled values, default none
|
labeled values, default none
|
||||||
@ -240,7 +198,6 @@ product {
|
|||||||
web: not (yet) used
|
web: not (yet) used
|
||||||
cmd: not (yet) used
|
cmd: not (yet) used
|
||||||
android: not (yet) used
|
android: not (yet) used
|
||||||
ios: not (yet) used
|
|
||||||
list:
|
list:
|
||||||
parameter is a list (using scalePoints values)? default false
|
parameter is a list (using scalePoints values)? default false
|
||||||
VST3: TBD (+approx to closest?)
|
VST3: TBD (+approx to closest?)
|
||||||
@ -248,7 +205,6 @@ product {
|
|||||||
web: TBD (approx to closest? dropdown? both?)
|
web: TBD (approx to closest? dropdown? both?)
|
||||||
cmd: not (yet) used
|
cmd: not (yet) used
|
||||||
android: not (yet) used
|
android: not (yet) used
|
||||||
ios: not (yet) used
|
|
||||||
unit:
|
unit:
|
||||||
unit of measure (from predefined list, see tibia-index.js), default ""
|
unit of measure (from predefined list, see tibia-index.js), default ""
|
||||||
VST3: ParameterInfo units
|
VST3: ParameterInfo units
|
||||||
@ -256,7 +212,6 @@ product {
|
|||||||
web: web-demo value <span> innerText
|
web: web-demo value <span> innerText
|
||||||
cmd: not (yet) used
|
cmd: not (yet) used
|
||||||
android: not (yet) used
|
android: not (yet) used
|
||||||
ios: not (yet) used
|
|
||||||
map:
|
map:
|
||||||
"linear" vs "logarithmic"
|
"linear" vs "logarithmic"
|
||||||
VST3: many places (requires libm)
|
VST3: many places (requires libm)
|
||||||
@ -264,7 +219,6 @@ product {
|
|||||||
web: web-demo <range> values
|
web: web-demo <range> values
|
||||||
cmd: not used
|
cmd: not used
|
||||||
android: index.html <range> values
|
android: index.html <range> values
|
||||||
ios: index.html <range> values
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -18,143 +18,104 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := android
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
ifeq (${HAS_MIDI_IN}, yes)
|
||||||
DATA_DIR ?= .
|
MIN_API := 29
|
||||||
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)
|
|
||||||
MIN_API := 29
|
|
||||||
else
|
else
|
||||||
MIN_API := 26
|
MIN_API := 26
|
||||||
endif
|
endif
|
||||||
|
|
||||||
NDK_DIR := $(SDK_DIR)/ndk/$(NDK_VERSION)
|
CC = ${ANDROID_NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi${MIN_API}-clang
|
||||||
BUILD_TOOLS_DIR := $(SDK_DIR)/build-tools/$(BUILD_TOOLS_VERSION)
|
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
|
APKSIGNER = ${BUILD_TOOLS_DIR}/apksigner
|
||||||
ANDROIDX_CORE_FILE := $(ANDROIDX_DIR)/core-$(ANDROIDX_CORE_VERSION).jar
|
ZIPALIGN = ${BUILD_TOOLS_DIR}/zipalign
|
||||||
ANDROIDX_LIFECYCLE_COMMON_FILE := $(ANDROIDX_DIR)/lifecycle-common-$(ANDROIDX_LIFECYCLE_COMMON_VERSION).jar
|
AAPT = ${BUILD_TOOLS_DIR}/aapt
|
||||||
ANDROIDX_VERSIONEDPARCELABLE_FILE := $(ANDROIDX_DIR)/versionedparcelable-$(ANDROIDX_VERSIONEDPARCELABLE_VERSION).jar
|
D8 = ${BUILD_TOOLS_DIR}/d8
|
||||||
KOTLIN_STDLIB_FILE := $(KOTLIN_DIR)/kotlin-stdlib-$(KOTLIN_STDLIB_VERSION).jar
|
ADB = ${ANDROID_SDK_DIR}/platform-tools/adb
|
||||||
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
|
|
||||||
|
|
||||||
JARS := \
|
JARS := \
|
||||||
$(ANDROID_JAR_FILE) \
|
${ANDROID_JAR_FILE} \
|
||||||
$(ANDROIDX_CORE_FILE) \
|
${ANDROIDX_CORE_FILE} \
|
||||||
$(ANDROIDX_LIFECYCLE_COMMON_FILE) \
|
${ANDROIDX_LIFECYCLE_COMMON_FILE} \
|
||||||
$(ANDROIDX_VERSIONEDPARCELABLE_FILE) \
|
${ANDROIDX_VERSIONEDPARCELABLE_FILE} \
|
||||||
$(KOTLIN_STDLIB_FILE) \
|
${KOTLIN_STDLIB_FILE} \
|
||||||
$(KOTLINX_COROUTINES_CORE_FILE) \
|
${KOTLINX_COROUTINES_CORE_FILE} \
|
||||||
$(KOTLINX_COROUTINES_CORE_JVM_FILE)
|
${KOTLINX_COROUTINES_CORE_JVM_FILE}
|
||||||
|
|
||||||
CLASSES_PATH := $(subst .,/,$(JAVA_PACKAGE_NAME))
|
CLASSES_PATH := $(subst .,/,$(JAVA_PACKAGE_NAME))
|
||||||
|
|
||||||
CLASSES := \
|
CLASSES := \
|
||||||
MainActivity \
|
MainActivity \
|
||||||
MainActivity$$WebAppInterface
|
MainActivity$$WebAppInterface
|
||||||
ifeq ($(HAS_MIDI_IN), yes)
|
ifeq (${HAS_MIDI_IN}, yes)
|
||||||
CLASSES += MainActivity$$WebAppInterface$$MidiDeviceCallback MainActivity$$WebAppInterface$$1
|
CLASSES += MainActivity$$WebAppInterface$$MidiDeviceCallback MainActivity$$WebAppInterface$$1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CFLAGS_EXTRA) $(CFLAGS)
|
DATA_DIR := $(or $(DATA_DIR),.)
|
||||||
|
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CFLAGS = -O3 -Wall -Wpedantic -Wextra
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -std=c++11 $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
CFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CFLAGS} ${CFLAGS_EXTRA}
|
||||||
|
|
||||||
LDFLAGS :=
|
CXXFLAGS = ${CFLAGS}
|
||||||
LDFLAGS_ALL := -shared -static-libstdc++ -landroid
|
CXXFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC -std=c++11 ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||||
ifeq ($(HAS_MIDI_IN), yes)
|
|
||||||
|
LDFLAGS =
|
||||||
|
LDFLAGS_ALL = -shared -static-libstdc++ -landroid
|
||||||
|
ifeq (${HAS_MIDI_IN}, yes)
|
||||||
LDFLAGS += -lamidi
|
LDFLAGS += -lamidi
|
||||||
endif
|
endif
|
||||||
LDFLAGS_ALL += $(LDFLAGS_EXTRA) $(LDFLAGS)
|
LDFLAGS_ALL += ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||||
|
|
||||||
JFLAGS :=
|
JFLAGS =
|
||||||
JFLAGS_ALL := $(JFLAGS_EXTRA) $(JFLAGS)
|
JFLAGS_ALL = ${JFLAGS} ${JFLAGS_EXTRA}
|
||||||
|
|
||||||
C_SRCS := $(C_SRCS_EXTRA)
|
C_SRCS = ${C_SRCS_EXTRA}
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
|
|
||||||
CXX_SRCS := $(COMMON_DIR)/src/jni.cpp $(CXX_SRCS_EXTRA)
|
CXX_SRCS = ${COMMON_DIR}/src/jni.cpp ${CXX_SRCS_EXTRA}
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
DIRS := build build/gen build/apk build/obj build/apk/lib build/apk/lib/armeabi-v7a build/assets
|
all: build/${BUNDLE_NAME}.apk
|
||||||
|
|
||||||
ALL := build/$(BUNDLE_NAME).apk
|
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/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/$(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/apk/classes.dex: build/apk/my_classes.jar
|
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
|
build/apk/my_classes.jar: $(foreach class,$(CLASSES),build/obj/$(CLASSES_PATH)/$(class).class) | build/apk
|
||||||
@echo $(CLASSES_PATH)
|
@echo ${CLASSES_PATH}
|
||||||
$(D8) $(foreach class,$(CLASSES),'build/obj/$(CLASSES_PATH)/$(class).class') --min-api $(MIN_API) --output $@ --no-desugaring
|
${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
|
build/obj/${CLASSES_PATH}/MainActivity.class: ${DATA_DIR}/src/MainActivity.java | build/obj
|
||||||
$(JC) $(JFLAGS_ALL) -classpath "$(subst $() $(),:,$(JARS))" -d 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
|
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)
|
${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 $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
$(DIRS):
|
build/gen build/apk build/obj build/apk/lib/armeabi-v7a build/assets:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
install: build/$(BUNDLE_NAME).apk
|
install: build/${BUNDLE_NAME}.apk
|
||||||
[ -n "`$(ADB) shell pm list packages | grep ^package:$(JAVA_PACKAGE_NAME)`" ] && $(ADB) uninstall $(JAVA_PACKAGE_NAME); exit 0
|
[ -n "`${ADB} shell pm list packages | grep ^package:${JAVA_PACKAGE_NAME}`" ] && ${ADB} uninstall ${JAVA_PACKAGE_NAME}; exit 0
|
||||||
$(ADB) install $^
|
${ADB} install $^
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-extra.mk
|
|
||||||
|
|
||||||
.PHONY: all clean install
|
.PHONY: all clean install
|
||||||
|
|
||||||
@ -163,9 +124,7 @@ install: build/$(BUNDLE_NAME).apk
|
|||||||
PERCENT := %
|
PERCENT := %
|
||||||
|
|
||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(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_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
|
||||||
|
@ -20,29 +20,36 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
JAVA_PACKAGE_NAME := {{=it.android.javaPackageName}}
|
||||||
ANDROID_VERSION := {{=it.android.androidVersion}}
|
|
||||||
|
|
||||||
{{?(it.android_make?.commonDir || it.make?.commonDir)}}
|
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.android_make && it.android_make.cflags ? it.android_make.cflags : ""}}
|
||||||
COMMON_DIR := {{=it.android_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
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 : ""}}
|
||||||
{{?(it.android_make?.dataDir || it.make?.dataDir)}}
|
LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.android_make && it.android_make.ldflags ? it.android_make.ldflags : ""}}
|
||||||
DATA_DIR := {{=it.android_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
|
||||||
{{?}}
|
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.android_make && it.android_make.cSrcs ? it.android_make.cSrcs : ""}}
|
||||||
{{?(it.android_make?.pluginDir || it.make?.pluginDir)}}
|
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.android_make && it.android_make.cxxSrcs ? it.android_make.cxxSrcs : ""}}
|
||||||
PLUGIN_DIR := {{=it.android_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
|
||||||
{{?}}
|
COMMON_DIR := {{=it.android_make && it.android_make.commonDir ? it.android_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||||
{{?(it.android_make?.apiDir || it.make?.apiDir)}}
|
DATA_DIR := {{=it.android_make && it.android_make.dataDir ? it.android_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}}
|
||||||
API_DIR := {{=it.android_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
PLUGIN_DIR := {{=it.android_make && it.android_make.pluginDir ? it.android_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||||
{{?}}
|
|
||||||
{{?(it.android_make?.mkincDir || it.make?.mkincDir)}}
|
KEY_STORE := {{=it.android_make.keyStore}}
|
||||||
MKINC_DIR := {{=it.android_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
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"}}
|
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
{{?it.make?.extra}}
|
|
||||||
{{=it.make.extra}}
|
|
||||||
{{?}}
|
|
||||||
{{?it.android_make?.extra}}
|
|
||||||
{{=it.android_make.extra}}
|
|
||||||
{{?}}
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
{{??}}
|
{{??}}
|
||||||
<uses-sdk android:minSdkVersion="26" /> <!-- for androidx core and AAudio -->
|
<uses-sdk android:minSdkVersion="26" /> <!-- for androidx core and AAudio -->
|
||||||
{{?}}
|
{{?}}
|
||||||
<uses-sdk android:targetSdkVersion="{{=it.android.androidVersion}}" />
|
<uses-sdk android:targetSdkVersion="34" />
|
||||||
<application android:label="{{=it.product.name}}">
|
<application android:label="{{=it.product.name}}">
|
||||||
<activity android:name=".MainActivity" android:label="{{=it.product.name}}" android:exported="true">
|
<activity android:name=".MainActivity" android:label="{{=it.product.name}}" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
* Copyright (C) 2024 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -83,7 +83,3 @@ static struct {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
#define JNI_FUNC(x) Java_{{=it.android.javaPackageName.replaceAll("_", "_1").replaceAll(".", "_")}}_MainActivity_##x
|
||||||
|
|
||||||
{{?it.product.state && it.product.state.dspCustom}}
|
|
||||||
#define STATE_DSP_CUSTOM
|
|
||||||
{{?}}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "plugin_api.h"
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -189,10 +188,6 @@ JNIEXPORT jboolean JNICALL
|
|||||||
JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
||||||
(void)env;
|
(void)env;
|
||||||
(void)thiz;
|
(void)thiz;
|
||||||
#ifdef STATE_DSP_CUSTOM
|
|
||||||
(void)plugin_state_load;
|
|
||||||
(void)plugin_state_save;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
||||||
# if NUM_CHANNELS_IN == 0
|
# if NUM_CHANNELS_IN == 0
|
||||||
@ -230,13 +225,7 @@ JNI_FUNC(nativeAudioStart)(JNIEnv* env, jobject thiz) {
|
|||||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
|
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
plugin_init(&instance);
|
||||||
/* .handle = */ NULL,
|
|
||||||
/* .format = */ "android",
|
|
||||||
/* .get_bindir = */ NULL,
|
|
||||||
/* .get_datadir = */ NULL
|
|
||||||
};
|
|
||||||
plugin_init(&instance, &cbs);
|
|
||||||
|
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||||
|
@ -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
|
# 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
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,114 +18,85 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := cmd
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
|
||||||
DATA_DIR ?= .
|
|
||||||
PLUGIN_DIR ?= src
|
|
||||||
API_DIR ?= $(PLUGIN_DIR)
|
|
||||||
MKINC_DIR ?= $(COMMON_DIR)
|
|
||||||
|
|
||||||
BUILD_BIN_DIR := build
|
|
||||||
BUILD_DATA_DIR := build
|
|
||||||
|
|
||||||
-include $(MKINC_DIR)/vars-pre.mk
|
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
EXE_SUFFIX := .exe
|
EXE_SUFFIX = .exe
|
||||||
else
|
else
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S = $(shell uname -s)
|
||||||
EXE_SUFFIX :=
|
EXE_SUFFIX =
|
||||||
PREFIX := /usr/local
|
PREFIX = /usr/local
|
||||||
BINDIR := $(PREFIX)/bin
|
BINDIR = ${PREFIX}/bin
|
||||||
endif
|
endif
|
||||||
|
|
||||||
TINYWAV_DIR ?= ../tinywav
|
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||||
MIDI_PARSER_DIR ?= ../midi-parser
|
DATA_DIR := $(or $(DATA_DIR),.)
|
||||||
|
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||||
|
|
||||||
CC := gcc
|
CC = gcc
|
||||||
CXX := g++
|
CXX = g++
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
CFLAGS = -O3 -Wall -Wpedantic -Wextra
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -I$(TINYWAV_DIR) -I$(MIDI_PARSER_DIR)/include $(CFLAGS_EXTRA) $(CFLAGS)
|
CFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -I${TINYWAV_DIR} -I${MIDI_PARSER_DIR}/include -fPIC ${CFLAGS} ${CFLAGS_EXTRA}
|
||||||
|
|
||||||
LDFLAGS :=
|
LDFLAGS =
|
||||||
LDFLAGS_ALL := $(LDFLAGS_EXTRA) $(LDFLAGS)
|
LDFLAGS_ALL = ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
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_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -I${TINYWAV_DIR} -I${MIDI_PARSER_DIR}/include -fPIC ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
CFLAGS_ALL := ${CFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
LDFLAGS_ALL := ${LDFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
CXXFLAGS_ALL := ${CXXFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PROGRAM := $(BUNDLE_NAME)$(EXE_SUFFIX)
|
PROGRAM = ${BUNDLE_NAME}${EXE_SUFFIX}
|
||||||
|
|
||||||
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)
|
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
|
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_SRCS = ${CXX_SRCS_EXTRA}
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
DIRS := build build/obj
|
all: build/${PROGRAM}
|
||||||
|
|
||||||
ALL := build/$(PROGRAM)
|
|
||||||
|
|
||||||
STRIP_ALL := build/$(PROGRAM)
|
|
||||||
STRIP_PHONY :=
|
|
||||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
|
||||||
|
|
||||||
-include $(MKINC_DIR)/vars-extra.mk
|
|
||||||
|
|
||||||
all: $(ALL)
|
|
||||||
|
|
||||||
ifeq ($(CXX_OBJS),)
|
ifeq ($(CXX_OBJS),)
|
||||||
build/$(PROGRAM): $(C_OBJS) build/obj/tinywav.o | build
|
build/${PROGRAM}: ${C_OBJS} build/obj/tinywav.o | build
|
||||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
else
|
else
|
||||||
build/$(PROGRAM): $(C_OBJS) $(CXX_OBJS) build/obj/tinywav.o | build
|
build/${PROGRAM}: ${C_OBJS} ${CXX_OBJS} build/obj/tinywav.o | build
|
||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(DIRS):
|
build build/obj:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
strip: $(STRIP_PREREQS)
|
|
||||||
strip build/$(PROGRAM)
|
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
.PHONY: all clean strip $(STRIP_PHONY)
|
.PHONY: all clean
|
||||||
else
|
else
|
||||||
install: all
|
install: all
|
||||||
mkdir -m 0755 -p $(BINDIR)
|
mkdir -p -m 0755 ${BINDIR}
|
||||||
install -m 0755 build/$(PROGRAM) $(BINDIR)
|
install -m 0755 build/${PROGRAM} ${BINDIR}
|
||||||
|
|
||||||
.PHONY: all clean strip $(STRIP_PHONY) install
|
.PHONY: all clean install
|
||||||
endif
|
endif
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-extra.mk
|
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
PERCENT := %
|
PERCENT := %
|
||||||
|
|
||||||
build/obj/tinywav.o: $(TINYWAV_DIR)/tinywav.c
|
build/obj/tinywav.o: ${TINYWAV_DIR}/tinywav.c
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL) -Wno-unused-result
|
${CC} $^ -o $@ -c ${CFLAGS_ALL} -Wno-unused-result
|
||||||
|
|
||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(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_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
|
||||||
|
@ -20,27 +20,18 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
{{?(it.cmd_make?.commonDir || it.make?.commonDir)}}
|
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.cmd_make.cflags ? it.cmd_make.cflags : ""}}
|
||||||
COMMON_DIR := {{=it.cmd_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
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 : ""}}
|
||||||
{{?(it.cmd_make?.dataDir || it.make?.dataDir)}}
|
|
||||||
DATA_DIR := {{=it.cmd_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
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 : ""}}
|
||||||
{{?(it.cmd_make?.pluginDir || it.make?.pluginDir)}}
|
|
||||||
PLUGIN_DIR := {{=it.cmd_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
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 : "")}}
|
||||||
{{?(it.cmd_make?.apiDir || it.make?.apiDir)}}
|
PLUGIN_DIR := {{=it.cmd_make && it.cmd_make.pluginDir ? it.cmd_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||||
API_DIR := {{=it.cmd_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
|
||||||
{{?}}
|
TINYWAV_DIR := {{=it.cmd_make.tinywavDir}}
|
||||||
{{?(it.cmd_make?.mkincDir || it.make?.mkincDir)}}
|
MIDI_PARSER_DIR := {{=it.cmd_make.midiParserDir}}
|
||||||
MKINC_DIR := {{=it.cmd_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
{{?it.make?.extra}}
|
|
||||||
{{=it.make.extra}}
|
|
||||||
{{?}}
|
|
||||||
{{?it.cmd_make?.extra}}
|
|
||||||
{{=it.cmd_make.extra}}
|
|
||||||
{{?}}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
* Copyright (C) 2024 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -73,7 +73,7 @@ static struct {
|
|||||||
} param_data[PARAMETERS_N] = {
|
} param_data[PARAMETERS_N] = {
|
||||||
{{~it.product.parameters :p:i}}
|
{{~it.product.parameters :p:i}}
|
||||||
{
|
{
|
||||||
/* .id = */ "{{=p.id}}",
|
/* .id = */ "{{=it.cmd.parameterIds[i]}}",
|
||||||
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
/* .out = */ {{=p.direction == "output" ? 1 : 0}},
|
||||||
/* .def = */ {{=p.defaultValue.toExponential()}}f,
|
/* .def = */ {{=p.defaultValue.toExponential()}}f,
|
||||||
/* .min = */ {{=p.minimum.toExponential()}}f,
|
/* .min = */ {{=p.minimum.toExponential()}}f,
|
||||||
@ -83,7 +83,3 @@ static struct {
|
|||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{{?it.product.state && it.product.state.dspCustom}}
|
|
||||||
#define STATE_DSP_CUSTOM
|
|
||||||
{{?}}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "plugin_api.h"
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -162,11 +161,6 @@ float clampf(float x, float m, float M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
#ifdef STATE_DSP_CUSTOM
|
|
||||||
(void)plugin_state_load;
|
|
||||||
(void)plugin_state_save;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++)
|
for (size_t i = 0; i < PARAMETERS_N; i++)
|
||||||
param_values[i] = param_data[i].def;
|
param_values[i] = param_data[i].def;
|
||||||
@ -358,13 +352,7 @@ int main(int argc, char * argv[]) {
|
|||||||
printf(" %s: %g\n", param_data[i].id, param_values[i]);
|
printf(" %s: %g\n", param_data[i].id, param_values[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
plugin_init(&instance);
|
||||||
/* .handle = */ NULL,
|
|
||||||
/* .format = */ "cmd",
|
|
||||||
/* .get_bindir = */ NULL,
|
|
||||||
/* .get_datadir = */ NULL
|
|
||||||
};
|
|
||||||
plugin_init(&instance, &cbs);
|
|
||||||
|
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++)
|
for (size_t i = 0; i < PARAMETERS_N; i++)
|
||||||
|
@ -18,32 +18,22 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := daisy-seed
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
TARGET = ${BUNDLE_NAME}
|
||||||
DATA_DIR ?= .
|
|
||||||
PLUGIN_DIR ?= src
|
|
||||||
API_DIR ?= $(PLUGIN_DIR)
|
|
||||||
MKINC_DIR ?= $(COMMON_DIR)
|
|
||||||
|
|
||||||
-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
|
CFLAGS += -I${DATA_DIR}/src -I${PLUGIN_DIR} ${CFLAGS_EXTRA}
|
||||||
|
LDFLAGS += ${LDFLAGS_EXTRA}
|
||||||
C_SOURCES += $(C_SRCS_EXTRA)
|
CXXFLAGS += -I${DATA_DIR}/src -I${PLUGIN_DIR} ${CXXFLAGS_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
|
|
||||||
|
@ -20,25 +20,14 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
{{?(it.daisy_seed_make?.commonDir || it.make?.commonDir)}}
|
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.daisy_seed_make.cflags ? it.daisy_seed_make.cflags : ""}}
|
||||||
COMMON_DIR := {{=it.daisy_seed_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
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.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 ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
{{?it.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 : ""}}
|
||||||
{{=it.make.extra}}
|
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 : ""}}
|
||||||
{{?}}
|
|
||||||
{{?it.daisy_seed_make?.extra}}
|
COMMON_DIR := {{=it.daisy_seed_make && it.daisy_seed_make.commonDir ? it.daisy_seed_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||||
{{=it.daisy_seed_make.extra}}
|
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
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -98,7 +98,3 @@ static int midi_cc_maps[NUM_PARAMETERS] = { {{~it.daisy_seed.midiCCMaps :p}}{{=p
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{{?it.product.state && it.product.state.dspCustom}}
|
|
||||||
#define STATE_DSP_CUSTOM
|
|
||||||
{{?}}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023-2025 Orastron Srl unipersonale
|
* Copyright (C) 2023, 2024 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "plugin_api.h"
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -150,11 +149,6 @@ static void AudioCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
#ifdef STATE_DSP_CUSTOM
|
|
||||||
(void)plugin_state_load;
|
|
||||||
(void)plugin_state_save;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hardware.Configure();
|
hardware.Configure();
|
||||||
hardware.Init();
|
hardware.Init();
|
||||||
|
|
||||||
@ -174,13 +168,7 @@ int main() {
|
|||||||
hardware.SetAudioBlockSize(BLOCK_SIZE);
|
hardware.SetAudioBlockSize(BLOCK_SIZE);
|
||||||
float sample_rate = hardware.AudioSampleRate();
|
float sample_rate = hardware.AudioSampleRate();
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
plugin_init(&instance);
|
||||||
/* .handle = */ NULL,
|
|
||||||
/* .format = */ "daisy-seed",
|
|
||||||
/* .get_bindir = */ NULL,
|
|
||||||
/* .get_datadir = */ NULL
|
|
||||||
};
|
|
||||||
plugin_init(&instance, &cbs);
|
|
||||||
|
|
||||||
plugin_set_sample_rate(&instance, sample_rate);
|
plugin_set_sample_rate(&instance, sample_rate);
|
||||||
if (plugin_mem_req(&instance) != 0)
|
if (plugin_mem_req(&instance) != 0)
|
||||||
|
@ -18,70 +18,35 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := ios
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||||
DATA_DIR ?= .
|
DATA_DIR := $(or $(DATA_DIR),.)
|
||||||
PLUGIN_DIR ?= src
|
PLUGIN_DIR := $(or $(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)
|
|
||||||
|
|
||||||
SOURCES := \
|
SOURCES := \
|
||||||
$(C_SRCS_EXTRA) \
|
${DATA_DIR}/src/data.h \
|
||||||
$(M_SRCS_EXTRA) \
|
${DATA_DIR}/src/index.html \
|
||||||
$(CXX_SRCS_EXTRA) \
|
${COMMON_DIR}/src/app.swift \
|
||||||
$(SRCS_EXTRA) \
|
${COMMON_DIR}/src/native.mm \
|
||||||
$(DATA_DIR)/src/data.h \
|
${COMMON_DIR}/src/app-Bridging-Header.h \
|
||||||
$(COMMON_DIR)/src/app.swift \
|
${PLUGIN_DIR}/plugin.h \
|
||||||
$(COMMON_DIR)/src/native.mm \
|
${C_SRCS_EXTRA} \
|
||||||
$(COMMON_DIR)/src/app-Bridging-Header.h \
|
${CXX_SRCS_EXTRA} \
|
||||||
$(PLUGIN_DIR)/plugin.h \
|
${SRCS_EXTRA}
|
||||||
$(API_DIR)/plugin_api.h
|
SOURCES_OUT = $(addprefix build/gen/src/, $(notdir $(SOURCES)))
|
||||||
SOURCES_OUT := $(addprefix build/gen/src/, $(notdir $(SOURCES)))
|
|
||||||
|
|
||||||
RESOURCES := $(PLUGIN_DIR)/index.html
|
all: build/gen/${BUNDLE_NAME}.xcodeproj
|
||||||
RESOURCES_OUT := $(addprefix build/gen/res/, $(notdir $(RESOURCES)))
|
|
||||||
|
|
||||||
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
|
build/gen/src:
|
||||||
|
|
||||||
-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):
|
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-extra.mk
|
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
@ -90,8 +55,3 @@ PERCENT := %
|
|||||||
|
|
||||||
$(SOURCES_OUT): build/gen/src/%: $$(filter $$(PERCENT)/%,$$(SOURCES)) | build/gen/src
|
$(SOURCES_OUT): build/gen/src/%: $$(filter $$(PERCENT)/%,$$(SOURCES)) | build/gen/src
|
||||||
cp -R $^ $@
|
cp -R $^ $@
|
||||||
|
|
||||||
$(RESOURCES_OUT): build/gen/res/%: $$(filter $$(PERCENT)/%,$$(RESOURCES)) | build/gen/res
|
|
||||||
cp -R $^ $@
|
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
|
||||||
|
@ -30,26 +30,9 @@ targets:
|
|||||||
type: application
|
type: application
|
||||||
sources:
|
sources:
|
||||||
- path: src
|
- path: src
|
||||||
- path: res
|
|
||||||
type: folder
|
|
||||||
|
|
||||||
{{?it.ios_make.dependencies}}
|
|
||||||
dependencies:
|
|
||||||
{{~it.ios_make.dependencies :d}}
|
|
||||||
- target: {{=d}}{{~}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
base:
|
base:
|
||||||
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
PRODUCT_BUNDLE_IDENTIFIER: {{=it.ios.productBundleIdentifier}}
|
||||||
|
|
||||||
{{?it.ios_make.development_team}}
|
|
||||||
CODE_SIGN_STYLE: Automatic
|
|
||||||
DEVELOPMENT_TEAM: {{=it.ios_make.development_team}}
|
|
||||||
{{?}}
|
|
||||||
OTHER_CFLAGS: "$(inherited) @CFLAGS_ALL@"
|
|
||||||
OTHER_CPLUSPLUSFLAGS: "$(inherited) @CXXFLAGS_ALL@"
|
|
||||||
OTHER_LDFLAGS: "$(inherited) @LDFLAGS_ALL@"
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h
|
SWIFT_OBJC_BRIDGING_HEADER: src/app-Bridging-Header.h
|
||||||
{{?it.ios_make.headerSearchPaths}}
|
{{?it.ios_make.headerSearchPaths}}
|
||||||
HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}}
|
HEADER_SEARCH_PATHS: {{~it.ios_make.headerSearchPaths :p}}
|
||||||
|
@ -20,25 +20,10 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
{{?(it.ios_make?.commonDir || it.make?.commonDir)}}
|
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.ios_make && it.ios_make.cSrcs ? it.ios_make.cSrcs : ""}}
|
||||||
COMMON_DIR := {{=it.ios_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.ios_make && it.ios_make.cxxSrcs ? it.ios_make.cxxSrcs : ""}}
|
||||||
{{?}}
|
SRCS_EXTRA := {{=it.ios_make && it.ios_make.srcsExtra ? it.ios_make.srcsExtra : ""}}
|
||||||
{{?(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 ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
{{?it.make?.extra}}
|
COMMON_DIR := {{=it.ios_make && it.ios_make.commonDir ? it.ios_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||||
{{=it.make.extra}}
|
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 : "")}}
|
||||||
{{?it.ios_make?.extra}}
|
|
||||||
{{=it.ios_make.extra}}
|
|
||||||
{{?}}
|
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
@preconcurrency import WebKit
|
import WebKit
|
||||||
import AVFoundation
|
import AVFoundation
|
||||||
|
|
||||||
struct WebView: UIViewRepresentable {
|
struct WebView: UIViewRepresentable {
|
||||||
class Coordinator: NSObject, WKScriptMessageHandlerWithReply, WKNavigationDelegate {
|
class Coordinator: NSObject, WKScriptMessageHandlerWithReply {
|
||||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
|
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
|
||||||
guard let body = message.body as? [String : Any] else { return }
|
guard let body = message.body as? [String : Any] else { return }
|
||||||
guard let name = body["name"] as? String else { return }
|
guard let name = body["name"] as? String else { return }
|
||||||
@ -57,15 +57,6 @@ struct WebView: UIViewRepresentable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
|
||||||
if let url = navigationAction.request.url, navigationAction.navigationType == .linkActivated {
|
|
||||||
UIApplication.shared.open(url)
|
|
||||||
decisionHandler(.cancel)
|
|
||||||
} else {
|
|
||||||
decisionHandler(.allow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCoordinator() -> Coordinator {
|
func makeCoordinator() -> Coordinator {
|
||||||
@ -76,10 +67,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
|
|
||||||
func makeUIView(context: Context) -> WKWebView {
|
func makeUIView(context: Context) -> WKWebView {
|
||||||
let configuration = WKWebViewConfiguration()
|
let configuration = WKWebViewConfiguration()
|
||||||
configuration.userContentController.addScriptMessageHandler(Coordinator(), contentWorld: .page, name: "messageHandler")
|
configuration.userContentController.addScriptMessageHandler(Coordinator(), contentWorld: .page, name: "listener")
|
||||||
configuration.setValue(true, forKey: "allowUniversalAccessFromFileURLs")
|
|
||||||
let webView = WKWebView(frame: .zero, configuration: configuration)
|
let webView = WKWebView(frame: .zero, configuration: configuration)
|
||||||
webView.navigationDelegate = context.coordinator
|
|
||||||
//webView.isInspectable = true
|
//webView.isInspectable = true
|
||||||
return webView
|
return webView
|
||||||
}
|
}
|
||||||
@ -92,8 +81,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "res")
|
let url = Bundle.main.url(forResource: "index", withExtension: "html")
|
||||||
WebView(url: url!).ignoresSafeArea().preferredColorScheme(.dark)
|
WebView(url: url!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,12 +97,12 @@ struct templateApp: App {
|
|||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView()
|
||||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
|
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
|
||||||
audioPause()
|
audioPause()
|
||||||
}
|
}
|
||||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
||||||
audioResume()
|
audioResume()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -81,7 +81,3 @@ static struct {
|
|||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{{?it.product.state && it.product.state.dspCustom}}
|
|
||||||
#define STATE_DSP_CUSTOM
|
|
||||||
{{?}}
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<title>{{=it.product.name}}</title>
|
<title>{{=it.product.name}}</title>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function request(data) {
|
function request(data) {
|
||||||
return window.webkit.messageHandlers.messageHandler.postMessage(data);
|
return window.webkit.messageHandlers.listener.postMessage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function needAudioPermission() {
|
function needAudioPermission() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "plugin_api.h"
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -190,11 +189,6 @@ void (^midiReceiveBlock)(const MIDIEventList *evtlist, void *srcConnRefCon) = ^(
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
char audioStart() {
|
char audioStart() {
|
||||||
#ifdef STATE_DSP_CUSTOM
|
|
||||||
(void)plugin_state_load;
|
|
||||||
(void)plugin_state_save;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
#if NUM_CHANNELS_IN + NUM_CHANNELS_OUT > 0
|
||||||
# if NUM_CHANNELS_IN == 0
|
# if NUM_CHANNELS_IN == 0
|
||||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
@ -257,15 +251,9 @@ char audioStart() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
plugin_init(&instance);
|
||||||
/* .handle = */ NULL,
|
|
||||||
/* .format = */ "ios",
|
|
||||||
/* .get_bindir = */ NULL,
|
|
||||||
/* .get_datadir = */ NULL
|
|
||||||
};
|
|
||||||
plugin_init(&instance, &cbs);
|
|
||||||
|
|
||||||
#if PARAMETERS_N > 0
|
#if PARAMETERS_N > 0
|
||||||
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
for (size_t i = 0; i < PARAMETERS_N; i++) {
|
||||||
if (!param_data[i].out)
|
if (!param_data[i].out)
|
||||||
@ -368,7 +356,7 @@ void audioPause() {
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
void audioResume() {
|
void audioResume() {
|
||||||
// TODO: could this fail?...
|
// TODO: couldn't this could fail?...
|
||||||
if (device_inited) {
|
if (device_inited) {
|
||||||
ma_device_init(NULL, &deviceConfig, &device);
|
ma_device_init(NULL, &deviceConfig, &device);
|
||||||
ma_device_start(&device);
|
ma_device_start(&device);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# 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
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,157 +18,98 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := lv2
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
|
||||||
DATA_DIR ?= .
|
|
||||||
PLUGIN_DIR ?= src
|
|
||||||
API_DIR ?= $(PLUGIN_DIR)
|
|
||||||
MKINC_DIR ?= $(COMMON_DIR)
|
|
||||||
|
|
||||||
BUNDLE_DIR := $(BUNDLE_NAME).lv2
|
|
||||||
|
|
||||||
BUILD_BIN_DIR := build/$(BUNDLE_DIR)
|
|
||||||
BUILD_DATA_DIR := build/$(BUNDLE_DIR)
|
|
||||||
|
|
||||||
-include $(MKINC_DIR)/vars-pre.mk
|
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
DLL_SUFFIX := .dll
|
DLL_SUFFIX = .dll
|
||||||
UI_TYPE := WindowsUI
|
LV2DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/LV2
|
||||||
LV2DIR := $(subst \,/,$(COMMONPROGRAMFILES))/LV2
|
LV2DIR_USER = $(shell echo '${APPDATA}' | sed 's:\\:/:g')/LV2
|
||||||
LV2DIR_USER := $(subst \,/,$(APPDATA))/LV2
|
CC = gcc
|
||||||
CC := gcc
|
CXX = g++
|
||||||
CXX := g++
|
|
||||||
else
|
else
|
||||||
UNAME_S = $(shell uname -s)
|
UNAME_S = $(shell uname -s)
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
DLL_SUFFIX := .dylib
|
DLL_SUFFIX = .dylib
|
||||||
UI_TYPE := CocoaUI
|
LV2DIR = /Library/Audio/Plug-Ins/LV2
|
||||||
LV2DIR := /Library/Audio/Plug-Ins/LV2
|
LV2DIR_USER = ${HOME}/Library/Audio/Plug-Ins/LV2
|
||||||
LV2DIR_USER := $(HOME)/Library/Audio/Plug-Ins/LV2
|
CC = clang
|
||||||
CC := clang
|
CXX = clang++
|
||||||
CXX := clang++
|
|
||||||
else
|
else
|
||||||
DLL_SUFFIX := .so
|
DLL_SUFFIX = .so
|
||||||
UI_TYPE := X11UI
|
PREFIX = /usr/local
|
||||||
PREFIX := /usr/local
|
LV2DIR = ${PREFIX}/lib/lv2
|
||||||
LV2DIR := $(PREFIX)/lib/lv2
|
LV2DIR_USER = ${HOME}/.lv2
|
||||||
LV2DIR_USER := $(HOME)/.lv2
|
CC = gcc
|
||||||
CC := gcc
|
CXX = g++
|
||||||
CXX := g++
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS := -O3 -Wall -Wpedantic -Wextra
|
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(shell pkg-config --cflags lv2) -fPIC $(CFLAGS_EXTRA) $(CFLAGS)
|
DATA_DIR := $(or $(DATA_DIR),.)
|
||||||
|
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||||
|
|
||||||
LDFLAGS :=
|
CFLAGS = -O3 -Wall -Wpedantic -Wextra
|
||||||
LDFLAGS_ALL := -shared $(shell pkg-config --libs lv2) $(LDFLAGS_EXTRA) $(LDFLAGS)
|
CFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CFLAGS} ${CFLAGS_EXTRA}
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
LDFLAGS =
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
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)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
CFLAGS_ALL := ${CFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
LDFLAGS_ALL := ${LDFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
CXXFLAGS_ALL := ${CXXFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DLL_FILE := $(BUNDLE_NAME)$(DLL_SUFFIX)
|
BUNDLE_DIR = ${BUNDLE_NAME}.lv2
|
||||||
|
|
||||||
C_SRCS := $(COMMON_DIR)/src/lv2.c $(C_SRCS_EXTRA)
|
DLL_FILE = ${BUNDLE_NAME}${DLL_SUFFIX}
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
|
||||||
|
|
||||||
M_SRCS := $(M_SRCS_EXTRA)
|
C_SRCS = ${COMMON_DIR}/src/lv2.c ${C_SRCS_EXTRA}
|
||||||
M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
|
|
||||||
CXX_SRCS := $(CXX_SRCS_EXTRA)
|
CXX_SRCS = ${CXX_SRCS_EXTRA}
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
|
|
||||||
DIRS := build build/$(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)
|
build/${BUNDLE_DIR}/manifest.ttl: ${DATA_DIR}/data/manifest.ttl.in | build/${BUNDLE_DIR}
|
||||||
|
cat $^ | sed s/@DLL_SUFFIX@/${DLL_SUFFIX}/g > $@
|
||||||
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 > $@
|
|
||||||
|
|
||||||
ifeq ($(CXX_OBJS),)
|
ifeq ($(CXX_OBJS),)
|
||||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) | build/$(BUNDLE_DIR)
|
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} | build/${BUNDLE_DIR}
|
||||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
else
|
else
|
||||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)
|
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} ${CXX_OBJS} | build/${BUNDLE_DIR}
|
||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(DIRS):
|
build/${BUNDLE_DIR} build/obj:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
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
|
install: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
mkdir -p -m 0755 "${LV2DIR}/${BUNDLE_DIR}"
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
install -m 0644 build/${BUNDLE_DIR}/manifest.ttl "${LV2DIR}/${BUNDLE_DIR}"
|
||||||
echo mkdir -m 0755 -p "$(LV2DIR)/$$d"; \
|
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${LV2DIR}/${BUNDLE_DIR}"
|
||||||
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
|
|
||||||
|
|
||||||
install-user: all
|
install-user: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
mkdir -p -m 0755 "${LV2DIR_USER}/${BUNDLE_DIR}"
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
install -m 0644 build/${BUNDLE_DIR}/manifest.ttl "${LV2DIR_USER}/${BUNDLE_DIR}"
|
||||||
echo mkdir -m 0755 -p "$(LV2DIR_USER)/$$d"; \
|
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${LV2DIR_USER}/${BUNDLE_DIR}"
|
||||||
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
|
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-extra.mk
|
.PHONY: all clean install install-user
|
||||||
|
|
||||||
.PHONY: all clean strip $(STRIP_PHONY) install install-user
|
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
PERCENT := %
|
PERCENT := %
|
||||||
|
|
||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||||
|
|
||||||
$(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$(M_SRCS)) | build/obj
|
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
|
||||||
|
|
||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
|
||||||
|
@ -20,25 +20,13 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
{{?(it.lv2_make?.commonDir || it.make?.commonDir)}}
|
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.lv2_make && it.lv2_make.cflags ? it.lv2_make.cflags : ""}}
|
||||||
COMMON_DIR := {{=it.lv2_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
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.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 ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
{{?it.make?.extra}}
|
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.lv2_make && it.lv2_make.cSrcs ? it.lv2_make.cSrcs : ""}}
|
||||||
{{=it.make.extra}}
|
CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.lv2_make && it.lv2_make.cxxSrcs ? it.lv2_make.cxxSrcs : ""}}
|
||||||
{{?}}
|
|
||||||
{{?it.lv2_make?.extra}}
|
COMMON_DIR := {{=it.lv2_make && it.lv2_make.commonDir ? it.lv2_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||||
{{=it.lv2_make.extra}}
|
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 [
|
doap:maintainer [
|
||||||
a foaf:Organization ;
|
a foaf:Organization ;
|
||||||
foaf:name "{{=it.company.name}}" ;
|
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)}}
|
rdfs:seeAlso {{=it.tibia.lv2.ttlURI(it.company.url)}}
|
||||||
] ;
|
] ;
|
||||||
lv2:minorVersion {{=/^([0-9]+)\./.exec(it.lv2.version)[1]}} ;
|
lv2:minorVersion {{=/^([0-9]+)\./.exec(it.lv2.version)[1]}} ;
|
||||||
lv2:microVersion {{=/^[0-9]+\.([0-9]+)/.exec(it.lv2.version)[1]}} ;
|
lv2:microVersion {{=/^[0-9]+\.([0-9]+)/.exec(it.lv2.version)[1]}} ;
|
||||||
{{?(it.tibia.lv2.ports.find(p => p.type == "midi" && !p.optional))}}
|
{{?it.tibia.lv2.ports.find(p => p.type == "midi")}}
|
||||||
lv2:requiredFeature urid:map ;
|
lv2:requiredFeature urid:map ;
|
||||||
{{??}}
|
|
||||||
lv2:optionalFeature urid:map ;
|
|
||||||
{{?}}
|
|
||||||
lv2:optionalFeature log:log ;
|
lv2:optionalFeature log:log ;
|
||||||
|
{{?}}
|
||||||
lv2:optionalFeature lv2:hardRTCapable ;
|
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 [
|
lv2:port [
|
||||||
{{~it.tibia.lv2.ports :p:i}}
|
{{~it.tibia.lv2.ports :p:i}}
|
||||||
{{?p.isBypass}}
|
{{?p.isBypass}}
|
||||||
@ -44,7 +33,7 @@
|
|||||||
lv2:designation lv2:enabled ;
|
lv2:designation lv2:enabled ;
|
||||||
lv2:name "Enabled" ;
|
lv2:name "Enabled" ;
|
||||||
lv2:shortName "Enabled" ;
|
lv2:shortName "Enabled" ;
|
||||||
lv2:symbol "enabled" ;
|
lv2:symbol "{{=p.symbol}}" ;
|
||||||
lv2:default 1 ;
|
lv2:default 1 ;
|
||||||
lv2:minimum 0 ;
|
lv2:minimum 0 ;
|
||||||
lv2:maximum 1 ;
|
lv2:maximum 1 ;
|
||||||
@ -64,7 +53,7 @@
|
|||||||
lv2:designation lv2:latency ;
|
lv2:designation lv2:latency ;
|
||||||
lv2:name "Latency" ;
|
lv2:name "Latency" ;
|
||||||
lv2:shortName "Latency" ;
|
lv2:shortName "Latency" ;
|
||||||
lv2:symbol "{{=p.id}}" ;
|
lv2:symbol "{{=p.symbol}}" ;
|
||||||
lv2:portProperty lv2:connectionOptional ;
|
lv2:portProperty lv2:connectionOptional ;
|
||||||
lv2:portProperty lv2:integer ;
|
lv2:portProperty lv2:integer ;
|
||||||
lv2:portProperty lv2:reportsLatency ;
|
lv2:portProperty lv2:reportsLatency ;
|
||||||
@ -75,7 +64,7 @@
|
|||||||
{{?"shortName" in p}}
|
{{?"shortName" in p}}
|
||||||
lv2:shortName "{{=p.shortName.substring(0, 16)}}" ;
|
lv2:shortName "{{=p.shortName.substring(0, 16)}}" ;
|
||||||
{{?}}
|
{{?}}
|
||||||
lv2:symbol "{{=p.id}}" ;
|
lv2:symbol "{{=p.symbol}}" ;
|
||||||
{{?p.type == "control"}}
|
{{?p.type == "control"}}
|
||||||
lv2:minimum {{=p.minimum.toExponential()}} ;
|
lv2:minimum {{=p.minimum.toExponential()}} ;
|
||||||
lv2:maximum {{=p.maximum.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
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -27,10 +27,6 @@
|
|||||||
#define DATA_PRODUCT_CONTROL_INPUTS_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
#define DATA_PRODUCT_CONTROL_INPUTS_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
||||||
#define DATA_PRODUCT_CONTROL_OUTPUTS_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
#define DATA_PRODUCT_CONTROL_OUTPUTS_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
||||||
|
|
||||||
{{?it.product.buses.find(x => x.type == "midi" && !x.optional)}}
|
|
||||||
#define DATA_PRODUCT_MIDI_REQUIRED
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
static uint32_t midi_in_index[DATA_PRODUCT_MIDI_INPUTS_N] = {
|
static uint32_t midi_in_index[DATA_PRODUCT_MIDI_INPUTS_N] = {
|
||||||
{{~it.tibia.lv2.ports.filter(x => x.type == "midi" && x.direction == "input") :p}}{{=p.busIndex}}, {{~}}
|
{{~it.tibia.lv2.ports.filter(x => x.type == "midi" && x.direction == "input") :p}}{{=p.busIndex}}, {{~}}
|
||||||
@ -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}}, {{~}}
|
{{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "output") :p}}{{=p.paramIndex}}, {{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#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
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,78 +22,26 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "plugin_api.h"
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#ifdef DATA_UI
|
|
||||||
# include "plugin_ui.h"
|
|
||||||
#endif
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
#include <lv2/core/lv2.h>
|
#include "lv2/core/lv2.h"
|
||||||
#include <lv2/core/lv2_util.h>
|
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
#include <lv2/log/log.h>
|
#include "lv2/core/lv2_util.h"
|
||||||
#include <lv2/log/logger.h>
|
#include "lv2/atom/util.h"
|
||||||
#include <lv2/urid/urid.h>
|
#include "lv2/atom/atom.h"
|
||||||
#if (DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0) || defined(DATA_STATE_DSP_CUSTOM)
|
#include "lv2/log/log.h"
|
||||||
# include <lv2/atom/atom.h>
|
#include "lv2/log/logger.h"
|
||||||
# if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
#include "lv2/midi/midi.h"
|
||||||
# include <lv2/atom/util.h>
|
#include "lv2/urid/urid.h"
|
||||||
# include <lv2/midi/midi.h>
|
|
||||||
# endif
|
|
||||||
#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__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
# include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
# include <pmmintrin.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
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plugin p;
|
plugin p;
|
||||||
float sample_rate;
|
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
const float * x[DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N];
|
||||||
#endif
|
#endif
|
||||||
@ -111,77 +59,26 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
|
||||||
# ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
float params_sync[DATA_PRODUCT_CONTROL_INPUTS_N];
|
|
||||||
atomic_flag sync_lock_flag;
|
|
||||||
char synced;
|
|
||||||
char loaded;
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
void * mem;
|
void * mem;
|
||||||
char * bundle_path;
|
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
|
||||||
LV2_Log_Logger logger;
|
|
||||||
LV2_URID_Map * map;
|
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;
|
LV2_URID uri_midi_MidiEvent;
|
||||||
#endif
|
#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;
|
} 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) {
|
static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double sample_rate, const char * bundle_path, const LV2_Feature * const * features) {
|
||||||
(void)descriptor;
|
(void)descriptor;
|
||||||
(void)bundle_path;
|
(void)bundle_path;
|
||||||
|
|
||||||
plugin_instance *instance = malloc(sizeof(plugin_instance));
|
plugin_instance *instance = malloc(sizeof(plugin_instance));
|
||||||
if (instance == NULL)
|
if (instance == NULL)
|
||||||
goto err_instance;
|
return NULL;
|
||||||
|
|
||||||
instance->bundle_path = strdup(bundle_path);
|
|
||||||
if (instance->bundle_path == NULL)
|
|
||||||
goto err_bundle_path;
|
|
||||||
|
|
||||||
|
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
|
||||||
// from https://lv2plug.in/book
|
// from https://lv2plug.in/book
|
||||||
const char * missing = lv2_features_query(features,
|
const char* missing = lv2_features_query(features,
|
||||||
LV2_LOG__log, &instance->logger.log, false,
|
LV2_LOG__log, &instance->logger.log, false,
|
||||||
LV2_URID__map, &instance->map, true,
|
LV2_URID__map, &instance->map, true,
|
||||||
NULL);
|
NULL);
|
||||||
@ -189,38 +86,24 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
|||||||
lv2_log_logger_set_map(&instance->logger, instance->map);
|
lv2_log_logger_set_map(&instance->logger, instance->map);
|
||||||
if (missing) {
|
if (missing) {
|
||||||
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
|
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
|
||||||
#ifdef DATA_PRODUCT_MIDI_REQUIRED
|
free(instance);
|
||||||
goto err_urid;
|
return NULL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#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);
|
||||||
if (instance->map)
|
#else
|
||||||
instance->uri_midi_MidiEvent = instance->map->map(instance->map->handle, LV2_MIDI__MidiEvent);
|
(void)features;
|
||||||
#endif
|
|
||||||
#ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
if (instance->map) {
|
|
||||||
instance->uri_atom_Chunk = instance->map->map(instance->map->handle, LV2_ATOM__Chunk);
|
|
||||||
instance->uri_state_data = instance->map->map(instance->map->handle, DATA_LV2_URI "#state_data");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
plugin_init(&instance->p);
|
||||||
/* .handle = */ (void *)instance,
|
|
||||||
/* .format = */ "lv2",
|
|
||||||
/* .get_bindir = */ get_bundle_path_cb,
|
|
||||||
/* .get_datadir = */ get_bundle_path_cb
|
|
||||||
};
|
|
||||||
plugin_init(&instance->p, &cbs);
|
|
||||||
|
|
||||||
instance->sample_rate = (float)sample_rate;
|
plugin_set_sample_rate(&instance->p, sample_rate);
|
||||||
plugin_set_sample_rate(&instance->p, instance->sample_rate);
|
|
||||||
size_t req = plugin_mem_req(&instance->p);
|
size_t req = plugin_mem_req(&instance->p);
|
||||||
if (req != 0) {
|
if (req != 0) {
|
||||||
instance->mem = malloc(req);
|
instance->mem = malloc(req);
|
||||||
if (instance->mem == NULL) {
|
if (instance->mem == NULL) {
|
||||||
lv2_log_error(&instance->logger, "Not enough memory\n");
|
plugin_fini(&instance->p);
|
||||||
goto err_mem;
|
return NULL;
|
||||||
}
|
}
|
||||||
plugin_mem_set(&instance->p, instance->mem);
|
plugin_mem_set(&instance->p, instance->mem);
|
||||||
} else
|
} else
|
||||||
@ -248,17 +131,6 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
return instance;
|
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) {
|
static void connect_port(LV2_Handle instance, uint32_t port, void * data_location) {
|
||||||
@ -303,19 +175,14 @@ static void activate(LV2_Handle instance) {
|
|||||||
i->params[j] = i->c[j] != NULL ? *i->c[j] : param_data[j].def;
|
i->params[j] = i->c[j] != NULL ? *i->c[j] : param_data[j].def;
|
||||||
plugin_set_parameter(&i->p, param_data[j].index, i->params[j]);
|
plugin_set_parameter(&i->p, param_data[j].index, i->params[j]);
|
||||||
}
|
}
|
||||||
# ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++)
|
|
||||||
i->params_sync[j] = i->params[j];
|
|
||||||
// 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
|
#endif
|
||||||
plugin_reset(&i->p);
|
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) {
|
static void run(LV2_Handle instance, uint32_t sample_count) {
|
||||||
plugin_instance * i = (plugin_instance *)instance;
|
plugin_instance * i = (plugin_instance *)instance;
|
||||||
|
|
||||||
@ -332,65 +199,40 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
||||||
# ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
_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++) {
|
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) {
|
||||||
if (i->c[j] == NULL)
|
if (i->c[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
float v = adjust_param(j, *i->c[j]);
|
float v;
|
||||||
|
if (param_data[j].flags & DATA_PARAM_BYPASS)
|
||||||
|
v = *i->c[j] > 0.f ? 0.f : 1.f;
|
||||||
|
else if (param_data[j].flags & DATA_PARAM_TOGGLED)
|
||||||
|
v = *i->c[j] > 0.f ? 1.f : 0.f;
|
||||||
|
else if (param_data[j].flags & DATA_PARAM_INTEGER)
|
||||||
|
v = (int32_t)(*i->c[j] + (*i->c[j] >= 0.f ? 0.5f : -0.5f));
|
||||||
|
else
|
||||||
|
v = *i->c[j];
|
||||||
|
|
||||||
|
v = clampf(v, param_data[j].min, param_data[j].max);
|
||||||
if (v != i->params[j]) {
|
if (v != i->params[j]) {
|
||||||
i->params[j] = v;
|
i->params[j] = v;
|
||||||
# ifdef DATA_STATE_DSP_CUSTOM
|
plugin_set_parameter(&i->p, param_data[j].index, v);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
if (locked)
|
|
||||||
atomic_flag_clear(&i->sync_lock_flag);
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
|
||||||
// from https://lv2plug.in/book
|
// 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++) {
|
for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) {
|
||||||
if (i->x_midi[j] == NULL)
|
if (i->x_midi[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
LV2_ATOM_SEQUENCE_FOREACH(i->x_midi[j], ev) {
|
LV2_ATOM_SEQUENCE_FOREACH(i->x_midi[j], ev) {
|
||||||
if (ev->body.type == i->uri_midi_MidiEvent) {
|
if (ev->body.type == i->uri_midi_MidiEvent) {
|
||||||
const uint8_t * data = (const uint8_t *)(ev + 1);
|
const uint8_t * data = (const uint8_t *)(ev + 1);
|
||||||
if ((data[0] & 0xf0) != 0xf0)
|
if ((data[0] & 0xf0) != 0xf0)
|
||||||
plugin_midi_msg_in(&i->p, midi_in_index[j], data);
|
plugin_midi_msg_in(&i->p, midi_in_index[j], data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
|
||||||
@ -421,6 +263,7 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
|
|||||||
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
_MM_SET_FLUSH_ZERO_MODE(flush_zero_mode);
|
||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(LV2_Handle instance) {
|
static void cleanup(LV2_Handle instance) {
|
||||||
@ -428,70 +271,9 @@ static void cleanup(LV2_Handle instance) {
|
|||||||
plugin_fini(&i->p);
|
plugin_fini(&i->p);
|
||||||
if (i->mem)
|
if (i->mem)
|
||||||
free(i->mem);
|
free(i->mem);
|
||||||
free(i->bundle_path);
|
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature * const * features) {
|
|
||||||
(void)flags;
|
|
||||||
(void)features;
|
|
||||||
|
|
||||||
plugin_instance * i = (plugin_instance *)instance;
|
|
||||||
if (!i->map) {
|
|
||||||
lv2_log_error(&i->logger, "Host is trying to store state but didn't provide URID map\n");
|
|
||||||
return LV2_STATE_ERR_UNKNOWN; // evidently buggy host, we don't have an errcode for it, LV2_STATE_ERR_NO_FEATURE has a different meaning
|
|
||||||
}
|
|
||||||
i->state_store = store;
|
|
||||||
i->state_handle = handle;
|
|
||||||
plugin_state_callbacks cbs = {
|
|
||||||
/* .handle = */ (void *)i,
|
|
||||||
/* .lock = */ state_lock_cb,
|
|
||||||
/* .unlock = */ state_unlock_cb,
|
|
||||||
/* .write = */ state_write_cb,
|
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
|
||||||
/* .set_parameter = */ NULL
|
|
||||||
# endif
|
|
||||||
};
|
|
||||||
return plugin_state_save(&i->p, &cbs, i->sample_rate) == 0 ? LV2_STATE_SUCCESS : LV2_STATE_ERR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature * const * features) {
|
|
||||||
(void)flags;
|
|
||||||
(void)features;
|
|
||||||
|
|
||||||
plugin_instance * i = (plugin_instance *)instance;
|
|
||||||
if (!i->map) {
|
|
||||||
lv2_log_error(&i->logger, "Host is trying to restore state but didn't provide URID map\n");
|
|
||||||
return LV2_STATE_ERR_UNKNOWN; // evidently buggy host, we don't have an errcode for it, LV2_STATE_ERR_NO_FEATURE has a different meaning
|
|
||||||
}
|
|
||||||
size_t length;
|
|
||||||
uint32_t type, xflags; // jalv 1.6.6 crashes using NULL as per spec, so we have these two
|
|
||||||
const char * data = retrieve(handle, i->uri_state_data, &length, &type, &xflags);
|
|
||||||
if (data == NULL) {
|
|
||||||
lv2_log_error(&i->logger, "Cannot restore state since property <%s> could not be retrieved\n", DATA_LV2_URI "#state_data");
|
|
||||||
return LV2_STATE_ERR_NO_PROPERTY;
|
|
||||||
}
|
|
||||||
plugin_state_callbacks cbs = {
|
|
||||||
/* .handle = */ (void *)i,
|
|
||||||
/* .lock = */ state_lock_cb,
|
|
||||||
/* .unlock = */ state_unlock_cb,
|
|
||||||
/* .write = */ NULL,
|
|
||||||
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
|
|
||||||
/* .set_parameter = */ state_set_parameter_cb
|
|
||||||
# endif
|
|
||||||
};
|
|
||||||
return plugin_state_load(&cbs, i->sample_rate, data, length) == 0 ? LV2_STATE_SUCCESS : LV2_STATE_ERR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const void * extension_data(const char * uri) {
|
|
||||||
static const LV2_State_Interface state = { state_save, state_restore };
|
|
||||||
if (!strcmp(uri, LV2_STATE__interface))
|
|
||||||
return &state;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const LV2_Descriptor descriptor = {
|
static const LV2_Descriptor descriptor = {
|
||||||
/* .URI = */ DATA_LV2_URI,
|
/* .URI = */ DATA_LV2_URI,
|
||||||
/* .instantiate = */ instantiate,
|
/* .instantiate = */ instantiate,
|
||||||
@ -500,181 +282,9 @@ static const LV2_Descriptor descriptor = {
|
|||||||
/* .run = */ run,
|
/* .run = */ run,
|
||||||
/* .deactivate = */ NULL,
|
/* .deactivate = */ NULL,
|
||||||
/* .cleanup = */ cleanup,
|
/* .cleanup = */ cleanup,
|
||||||
#ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
/* .extension_data = */ extension_data
|
|
||||||
#else
|
|
||||||
/* .extension_data = */ NULL
|
/* .extension_data = */ NULL
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
|
||||||
return index == 0 ? &descriptor : NULL;
|
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
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -34,8 +34,6 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
||||||
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
||||||
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
|
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
|
||||||
{ id: "state", uri: "http://lv2plug.in/ns/extensions/state#" },
|
|
||||||
{ id: "ui", uri: "http://lv2plug.in/ns/extensions/ui#" },
|
|
||||||
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
|
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
|
||||||
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
|
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
|
||||||
],
|
],
|
||||||
@ -68,12 +66,7 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
ports: [],
|
ports: [],
|
||||||
|
|
||||||
ttlURI: function (uri) {
|
ttlURI: function (uri) {
|
||||||
if (uri.charAt(0) == "@") {
|
return uri.charAt(0) == "@" ? uri.substring(1) : "<" + uri + ">";
|
||||||
if (uri.indexOf("#") == -1)
|
|
||||||
return uri.substring(1);
|
|
||||||
uri = data.tibia.lv2.expandURI(uri);
|
|
||||||
}
|
|
||||||
return "<" + uri + ">";
|
|
||||||
},
|
},
|
||||||
|
|
||||||
expandURI: function (uri) {
|
expandURI: function (uri) {
|
||||||
@ -88,8 +81,6 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
for (var id in data.lv2.prefixes)
|
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: 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 buses = data.product.buses;
|
||||||
var audioPorts = [];
|
var audioPorts = [];
|
||||||
var midiPorts = [];
|
var midiPorts = [];
|
||||||
@ -97,16 +88,20 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
var b = buses[bi];
|
var b = buses[bi];
|
||||||
if (b.type == "audio") {
|
if (b.type == "audio") {
|
||||||
if (b.channels == "mono") {
|
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);
|
audioPorts.push(e);
|
||||||
} else {
|
} 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);
|
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);
|
audioPorts.push(e);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
midiPorts.push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,6 +115,7 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
var p = data.product.parameters[i];
|
var p = data.product.parameters[i];
|
||||||
var e = Object.create(p);
|
var e = Object.create(p);
|
||||||
e.type = "control";
|
e.type = "control";
|
||||||
|
e.symbol = data.lv2.parameterSymbols[i];
|
||||||
e.paramIndex = i;
|
e.paramIndex = i;
|
||||||
ports.push(e);
|
ports.push(e);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# 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
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,177 +18,119 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := vst3
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
|
||||||
DATA_DIR ?= .
|
|
||||||
PLUGIN_DIR ?= src
|
|
||||||
API_DIR ?= $(PLUGIN_DIR)
|
|
||||||
MKINC_DIR ?= $(COMMON_DIR)
|
|
||||||
|
|
||||||
BUNDLE_DIR := $(BUNDLE_NAME).vst3
|
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
DLL_SUFFIX := .vst3
|
DLL_SUFFIX = .vst3
|
||||||
VST3DIR := $(subst \,/,$(COMMONPROGRAMFILES))/VST3
|
PLATFORM = x86_64-win
|
||||||
VST3DIR_USER := $(subst \,/,$(LOCALAPPDATA))/Programs/Common/VST3
|
VST3DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/VST3
|
||||||
CC := gcc
|
VST3DIR_USER = $(shell echo '${LOCALAPPDATA}' | sed 's:\\:/:g')/Programs/Common/VST3
|
||||||
CXX := g++
|
CC = gcc
|
||||||
MACHINE := $(shell $(CC) -dumpmachine | sed 's:-.*::g')
|
CXX = g++
|
||||||
ifeq ($(MACHINE), x86_64)
|
|
||||||
VST3_PLATFORM := x86_64-win
|
|
||||||
endif
|
|
||||||
ifeq ($(MACHINE), aarch64)
|
|
||||||
VST3_PLATFORM := arm64-win
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S = $(shell uname -s)
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
DLL_SUFFIX :=
|
DLL_SUFFIX =
|
||||||
VST3DIR := /Library/Audio/Plug-Ins/VST3
|
PLATFORM = MacOS
|
||||||
VST3DIR_USER := $(HOME)/Library/Audio/Plug-Ins/VST3
|
VST3DIR = /Library/Audio/Plug-Ins/VST3
|
||||||
CC := clang
|
VST3DIR_USER = ${HOME}/Library/Audio/Plug-Ins/VST3
|
||||||
CXX := clang++
|
CC = clang
|
||||||
VST3_PLATFORM := MacOS
|
CXX = clang++
|
||||||
else
|
else
|
||||||
DLL_SUFFIX := .so
|
DLL_SUFFIX = .so
|
||||||
VST3DIR := /usr/local/lib/vst3
|
PLATFORM = $(shell uname -m)-linux
|
||||||
VST3DIR_USER := $(HOME)/.vst3
|
VST3DIR = /usr/local/lib/vst3
|
||||||
CC := gcc
|
VST3DIR_USER = ${HOME}/.vst3
|
||||||
CXX := g++
|
CC = gcc
|
||||||
VST3_PLATFORM := $(shell uname -m)-linux
|
CXX = g++
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
DLL_DIR := Contents/$(VST3_PLATFORM)
|
|
||||||
|
|
||||||
BUILD_BIN_DIR := build/$(BUNDLE_DIR)/$(DLL_DIR)
|
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||||
BUILD_DATA_DIR := build/$(BUNDLE_DIR)/Contents/Resources
|
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
|
LDFLAGS =
|
||||||
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CFLAGS_EXTRA) $(CFLAGS)
|
LDFLAGS_ALL = -shared -lm ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||||
|
|
||||||
LDFLAGS :=
|
CXXFLAGS = ${CFLAGS}
|
||||||
LDFLAGS_ALL := -shared -lm $(LDFLAGS_EXTRA) $(LDFLAGS)
|
CXXFLAGS_ALL = -I${DATA_DIR}/src -I${PLUGIN_DIR} -fPIC ${CXXFLAGS} ${CXXFLAGS_EXTRA}
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
|
||||||
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CXXFLAGS_EXTRA) $(CXXFLAGS)
|
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64
|
CFLAGS_ALL := ${CFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -arch arm64 -arch x86_64
|
LDFLAGS_ALL := ${LDFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
CXXFLAGS_ALL := $(CXXFLAGS_ALL) -arch arm64 -arch x86_64
|
CXXFLAGS_ALL := ${CXXFLAGS_ALL} -arch arm64 -arch x86_64
|
||||||
ifeq ($(HAS_UI), yes)
|
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,-framework,Foundation -Wl,-framework,Cocoa -Wl,-framework,Corevideo
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Linux)
|
BUNDLE_DIR = ${BUNDLE_NAME}.vst3
|
||||||
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
|
|
||||||
|
|
||||||
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_SRCS = ${COMMON_DIR}/src/vst3.c ${C_SRCS_EXTRA}
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
|
|
||||||
M_SRCS := $(M_SRCS_EXTRA)
|
CXX_SRCS = ${CXX_SRCS_EXTRA}
|
||||||
M_OBJS := $(addprefix build/obj/, $(notdir $(M_SRCS:.m=.o)))
|
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)
|
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
|
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),)
|
ifeq ($(CXX_OBJS),)
|
||||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} | build/${BUNDLE_DIR}/${DLL_DIR}
|
||||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
else
|
else
|
||||||
build/$(BUNDLE_DIR)/$(DLL_FILE): $(C_OBJS) $(M_OBJS) $(CXX_OBJS) | build/$(BUNDLE_DIR)/$(DLL_DIR)
|
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} ${CXX_OBJS} | build/${BUNDLE_DIR}/${DLL_DIR}
|
||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(UNAME_S), Darwin)
|
build/${BUNDLE_DIR}/${DLL_DIR} build/obj:
|
||||||
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):
|
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
strip: $(STRIP_PREREQS)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
strip build/$(BUNDLE_DIR)/$(DLL_FILE)
|
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
mkdir -p -m 0755 "${VST3DIR}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${VST3DIR}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||||
echo mkdir -m 0755 -p "$(VST3DIR)/$$d"; \
|
install -m 0644 build/${BUNDLE_DIR}/Contents/Info.plist "${VST3DIR}/${BUNDLE_DIR}/Contents/Info.plist"
|
||||||
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
|
|
||||||
|
|
||||||
install-user: all
|
install-user: all
|
||||||
@for d in `find build/$(BUNDLE_DIR) -type d`; do \
|
mkdir -p -m 0755 "${VST3DIR_USER}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||||
d=`echo $$d | sed 's:^build/::'` ; \
|
install -m 0755 build/${BUNDLE_DIR}/${DLL_FILE} "${VST3DIR_USER}/${BUNDLE_DIR}/${DLL_DIR}"
|
||||||
echo mkdir -m 0755 -p "$(VST3DIR_USER)/$$d"; \
|
install -m 0644 build/${BUNDLE_DIR}/Contents/Info.plist "${VST3DIR_USER}/${BUNDLE_DIR}/Contents/Info.plist"
|
||||||
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
|
|
||||||
|
|
||||||
-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:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
PERCENT := %
|
PERCENT := %
|
||||||
|
|
||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
${CC} $^ -o $@ -c ${CFLAGS_ALL}
|
||||||
|
|
||||||
$(M_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).m,$$(M_SRCS)) | build/obj
|
|
||||||
$(CC) $^ -o $@ -c $(CFLAGS_ALL)
|
|
||||||
|
|
||||||
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# 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
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -20,28 +20,13 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
{{?(it.vst3_make?.commonDir || it.make?.commonDir)}}
|
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.vst3_make && it.vst3_make.cflags ? it.vst3_make.cflags : ""}}
|
||||||
COMMON_DIR := {{=it.vst3_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
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 : ""}}
|
||||||
{{?(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 ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
HAS_UI := {{=it.product.ui ? "yes" : "no"}}
|
C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.vst3_make && it.vst3_make.cSrcs ? it.vst3_make.cSrcs : ""}}
|
||||||
HAS_PARAMETER_IN := {{=it.product.parameters.filter(x => x.direction == "input").length > 0 ? "yes" : "no"}}
|
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}}
|
COMMON_DIR := {{=it.vst3_make && it.vst3_make.commonDir ? it.vst3_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}}
|
||||||
{{=it.make.extra}}
|
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 : "")}}
|
||||||
{{?it.vst3_make?.extra}}
|
|
||||||
{{=it.vst3_make.extra}}
|
|
||||||
{{?}}
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
BNDL????
|
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -28,8 +28,8 @@
|
|||||||
static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
static Steinberg_char16 dataProductNameW[64] = { {{~Array.from(it.product.name).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||||
static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
static Steinberg_char16 dataProductVersionW[64] = { {{~Array.from(it.product.version + "." + it.product.buildVersion).slice(0, 63) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
||||||
|
|
||||||
#define DATA_VST3_SDK_VERSION "VST 3.7.12"
|
#define DATA_VST3_SDK_VERSION "VST 3.7.9"
|
||||||
static Steinberg_char16 dataVST3SDKVersionW[64] = { {{~Array.from("VST 3.7.12") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 };
|
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 };
|
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
|
#endif
|
||||||
|
|
||||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
||||||
#define DATA_PRODUCT_PARAMETERS_IN_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
|
||||||
#define DATA_PRODUCT_PARAMETERS_OUT_N {{=it.product.parameters.filter(x => !x.isLatency && x.direction == "output").length}}
|
|
||||||
|
|
||||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||||
{
|
{
|
||||||
{{?p.isBypass}}
|
{{?p.isBypass}}
|
||||||
/* .id = */ {{=(it.tibia.sdbm("bypass ") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.vst3.sdbm("Bypass") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from("Bypass") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
@ -140,7 +138,7 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
/* .unitId = */ 0,
|
/* .unitId = */ 0,
|
||||||
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||||
{{??}}
|
{{??}}
|
||||||
/* .id = */ {{=(it.tibia.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 },
|
/* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .units = */ { {{~Array.from(p.unit in it.tibia.vst3.units ? it.tibia.vst3.units[p.unit] : "") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
@ -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}}
|
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}}
|
||||||
{
|
{
|
||||||
/* .id = */ {{=(it.tibia.sdbm(b.id + " channel pressure") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Channel Pressure") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(b.name + " Channel Pressure").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(b.name + " Channel Pressure") :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 },
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " Chan Pres") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
/* .stepCount = */ 0,
|
/* .stepCount = */ 0,
|
||||||
/* .defaultNormalizedValue = */ 0.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
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* .id = */ {{=(it.tibia.sdbm(b.id + " pitch bend") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Pitch Bend") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(b.name + " Pitch Bend").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(b.name + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " Pitch Bend") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
/* .stepCount = */ 0,
|
/* .stepCount = */ 0,
|
||||||
/* .defaultNormalizedValue = */ 0.5,
|
/* .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
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* .id = */ {{=(it.tibia.sdbm(b.id + " mod wheel") & 0x7fffffff) >>> 0}},
|
/* .id = */ {{=(it.tibia.vst3.sdbm(b.name + " Mod Wheel") & 0x7fffffff) >>> 0}},
|
||||||
/* .title = */ { {{~Array.from(b.name + " Mod Wheel").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .title = */ { {{~Array.from(b.name + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel").slice(0, 127) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " Mod Wheel") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .units = */ { 0 },
|
/* .units = */ { 0 },
|
||||||
/* .stepCount = */ 0,
|
/* .stepCount = */ 0,
|
||||||
/* .defaultNormalizedValue = */ 0.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_INTEGER (1<<2)
|
||||||
# define DATA_PARAM_MAP_LOG (1<<3)
|
# define DATA_PARAM_MAP_LOG (1<<3)
|
||||||
|
|
||||||
typedef struct {
|
static struct {
|
||||||
size_t index;
|
size_t index;
|
||||||
double min;
|
double min;
|
||||||
double max;
|
double max;
|
||||||
@ -200,11 +198,8 @@ typedef struct {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
double mapK;
|
double mapK;
|
||||||
// scalePoints?
|
// scalePoints?
|
||||||
} ParameterData;
|
} parameterData[DATA_PRODUCT_PARAMETERS_N] = {
|
||||||
|
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||||
# if DATA_PRODUCT_PARAMETERS_IN_N > 0
|
|
||||||
static ParameterData parameterInData[DATA_PRODUCT_PARAMETERS_IN_N] = {
|
|
||||||
{{~it.product.parameters.filter(x => x.direction == "input") :p:i}}
|
|
||||||
{
|
{
|
||||||
/* .index = */ {{=p.paramIndex}},
|
/* .index = */ {{=p.paramIndex}},
|
||||||
/* .min = */ {{=p.minimum.toExponential()}},
|
/* .min = */ {{=p.minimum.toExponential()}},
|
||||||
@ -215,55 +210,11 @@ 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
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{{?it.product.parameters.find(x => x.isLatency)}}
|
{{?it.product.parameters.find(x => x.isLatency)}}
|
||||||
#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}}
|
#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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Tibia. If not, see <http://www.gnu.org/licenses/>.
|
* 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");
|
var path = require("path");
|
||||||
@ -49,27 +49,20 @@ module.exports = function (data, api, outputCommon, outputData) {
|
|||||||
"pc": "%",
|
"pc": "%",
|
||||||
"s": "s",
|
"s": "s",
|
||||||
"semitone12TET": "semi"
|
"semitone12TET": "semi"
|
||||||
|
},
|
||||||
|
|
||||||
|
sdbm: function (s) {
|
||||||
|
var hash = 0;
|
||||||
|
for (var i = 0; i < s.length; i++)
|
||||||
|
hash = s.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
|
||||||
|
return hash >>> 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var inIdx = 0;
|
for (var i = 0; i < data.product.parameters.length; i++)
|
||||||
var outIdx = 0;
|
|
||||||
for (var i = 0; i < data.product.parameters.length; i++) {
|
|
||||||
data.product.parameters[i].paramIndex = i;
|
data.product.parameters[i].paramIndex = i;
|
||||||
if (data.product.parameters[i].isLatency)
|
|
||||||
continue;
|
|
||||||
data.product.parameters[i].paramInfoIndex = inIdx + outIdx;
|
|
||||||
if (data.product.parameters[i].direction == "input") {
|
|
||||||
data.product.parameters[i].paramDataIndex = inIdx;
|
|
||||||
inIdx++;
|
|
||||||
} else {
|
|
||||||
data.product.parameters[i].paramDataIndex = outIdx;
|
|
||||||
outIdx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
api.copyFile(`data${sep}PkgInfo`, `data${sep}PkgInfo`);
|
|
||||||
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
||||||
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
||||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>{{=it.product.name}}</title>
|
<title>{{=it.product.name}}</title>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as demo from "./{{=it.product.bundleName}}/module.js";
|
import * as demo from "./{{=it.product.bundleName}}.js";
|
||||||
window.demo = demo;
|
window.demo = demo;
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
@ -212,7 +212,7 @@ window.addEventListener("load", function (e) {
|
|||||||
module = new demo.Module();
|
module = new demo.Module();
|
||||||
if (!midi && hasMidiInput)
|
if (!midi && hasMidiInput)
|
||||||
midi = await navigator.requestMIDIAccess();
|
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 = new demo.Node(module);
|
||||||
node.connect(audioCtx.destination, audioOutputIndex);
|
node.connect(audioCtx.destination, audioOutputIndex);
|
||||||
|
|
||||||
|
@ -23,6 +23,5 @@ var sep = path.sep;
|
|||||||
|
|
||||||
module.exports = function (data, api) {
|
module.exports = function (data, api) {
|
||||||
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
api.generateFileFromTemplateFile(`src${sep}index.html`, `src${sep}index.html`, data);
|
||||||
api.copyFile(`vars-extra-web-demo.mk`, `vars-extra-web-demo.mk`);
|
api.copyFile(`web-extra.mk`, `web-extra.mk`);
|
||||||
api.copyFile(`rules-extra-web-demo.mk`, `rules-extra-web-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
|
# 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
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,16 +18,12 @@
|
|||||||
# File author: Stefano D'Angelo
|
# 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/web
|
||||||
cp $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
build/web/key.pem: build/web/cert.pem
|
build/web/key.pem: build/web/cert.pem
|
||||||
|
|
||||||
build/web/cert.pem: | build
|
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
|
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)
|
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Tibia
|
# 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
|
# Tibia is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -18,28 +18,19 @@
|
|||||||
# File author: Stefano D'Angelo
|
# File author: Stefano D'Angelo
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE := web
|
|
||||||
|
|
||||||
include vars.mk
|
include vars.mk
|
||||||
|
|
||||||
COMMON_DIR ?= .
|
COMMON_DIR := $(or $(COMMON_DIR),.)
|
||||||
DATA_DIR ?= .
|
DATA_DIR := $(or $(DATA_DIR),.)
|
||||||
PLUGIN_DIR ?= src
|
PLUGIN_DIR := $(or $(PLUGIN_DIR),src)
|
||||||
API_DIR ?= $(PLUGIN_DIR)
|
|
||||||
MKINC_DIR ?= $(COMMON_DIR)
|
|
||||||
|
|
||||||
BUILD_BIN_DIR := build/web
|
CC = clang
|
||||||
BUILD_DATA_DIR := build/web
|
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
|
LDFLAGS_ALL = \
|
||||||
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 := \
|
|
||||||
-Wl,--allow-undefined \
|
-Wl,--allow-undefined \
|
||||||
-Wl,--no-entry \
|
-Wl,--no-entry \
|
||||||
-Wl,--lto-O3 \
|
-Wl,--lto-O3 \
|
||||||
@ -62,75 +53,61 @@ LDFLAGS_ALL := \
|
|||||||
-Wl,--export=processor_set_parameter \
|
-Wl,--export=processor_set_parameter \
|
||||||
-Wl,-z,stack-size=$$((8*1024*1024)) \
|
-Wl,-z,stack-size=$$((8*1024*1024)) \
|
||||||
-nostdlib
|
-nostdlib
|
||||||
ifeq ($(HAS_MIDI_IN), yes)
|
ifeq (${HAS_MIDI_IN}, yes)
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) -Wl,--export=processor_midi_msg_in
|
LDFLAGS_ALL += -Wl,--export=processor_midi_msg_in
|
||||||
endif
|
endif
|
||||||
LDFLAGS_ALL := $(LDFLAGS_ALL) $(LDFLAGS_EXTRA) $(LDFLAGS)
|
LDFLAGS_ALL += ${LDFLAGS} ${LDFLAGS_EXTRA}
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
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_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_SRCS = ${COMMON_DIR}/src/processor.c ${COMMON_DIR}/src/walloc.c ${COMMON_DIR}/src/string.c
|
||||||
C_OBJS := $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o)))
|
||||||
|
|
||||||
ifeq ($(CXX_SRCS_EXTRA),)
|
ifeq ($(CXX_SRCS_EXTRA),)
|
||||||
CXX_SRCS :=
|
CXX_SRCS =
|
||||||
CXX_OBJS :=
|
CXX_OBJS =
|
||||||
else
|
else
|
||||||
CXX_SRCS := $(COMMON_DIR)/src/new.cpp $(CXX_SRCS_EXTRA)
|
CXX_SRCS = ${COMMON_DIR}/src/new.cpp ${CXX_SRCS_EXTRA}
|
||||||
CXX_OBJS := $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
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
|
-include ${COMMON_DIR}/web-extra.mk
|
||||||
STRIP_PHONY :=
|
|
||||||
STRIP_PREREQS := $(STRIP_ALL) $(STRIP_PHONY)
|
|
||||||
|
|
||||||
-include $(MKINC_DIR)/vars-extra.mk
|
all: ${ALL}
|
||||||
|
|
||||||
all: $(ALL)
|
|
||||||
|
|
||||||
ifeq ($(CXX_OBJS),)
|
ifeq ($(CXX_OBJS),)
|
||||||
build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) | build/web/$(BUNDLE_NAME)
|
build/web/${BUNDLE_NAME}.wasm: ${C_OBJS} | build/web
|
||||||
$(CC) $^ -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL)
|
${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
else
|
else
|
||||||
build/web/$(BUNDLE_NAME)/module.wasm: $(C_OBJS) $(CXX_OBJS) | build/web/$(BUNDLE_NAME)
|
build/web/${BUNDLE_NAME}.wasm: ${C_OBJS} ${CXX_OBJS} | build/web
|
||||||
$(CXX) $^ -o $@ $(CFLAGS_ALL) $(CXXFLAGS_ALL) $(LDFLAGS_ALL)
|
${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build/web/$(BUNDLE_NAME)/processor.js: $(DATA_DIR)/src/processor.js | build/web/$(BUNDLE_NAME)
|
build/web/${BUNDLE_NAME}_processor.js: ${DATA_DIR}/src/processor.js | build/web
|
||||||
cp $^ $@
|
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 $^ $@
|
cp $^ $@
|
||||||
|
|
||||||
$(DIRS):
|
build/web build/obj:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build
|
rm -fr build
|
||||||
|
|
||||||
strip: $(STRIP_PREREQS)
|
.PHONY: all clean
|
||||||
#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)
|
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
PERCENT := %
|
PERCENT := %
|
||||||
|
|
||||||
$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj
|
$(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_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj
|
||||||
$(CXX) $^ -o $@ -c $(CXXFLAGS_ALL)
|
${CXX} $^ -o $@ -c ${CXXFLAGS_ALL}
|
||||||
|
|
||||||
-include $(MKINC_DIR)/rules-secondexp-extra.mk
|
|
||||||
|
@ -20,27 +20,15 @@
|
|||||||
|
|
||||||
BUNDLE_NAME := {{=it.product.bundleName}}
|
BUNDLE_NAME := {{=it.product.bundleName}}
|
||||||
|
|
||||||
{{?(it.web_make?.commonDir || it.make?.commonDir)}}
|
CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.web_make && it.web_make.cflags ? it.web_make.cflags : ""}}
|
||||||
COMMON_DIR := {{=it.web_make?.commonDir ?? (it.make?.commonDir ?? "")}}
|
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 : ""}}
|
||||||
{{?(it.web_make?.dataDir || it.make?.dataDir)}}
|
|
||||||
DATA_DIR := {{=it.web_make?.dataDir ?? (it.make?.dataDir ?? "")}}
|
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 : ""}}
|
||||||
{{?(it.web_make?.pluginDir || it.make?.pluginDir)}}
|
|
||||||
PLUGIN_DIR := {{=it.web_make?.pluginDir ?? (it.make?.pluginDir ?? "")}}
|
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 : "")}}
|
||||||
{{?(it.web_make?.apiDir || it.make?.apiDir)}}
|
PLUGIN_DIR := {{=it.web_make && it.web_make.pluginDir ? it.web_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}}
|
||||||
API_DIR := {{=it.web_make?.apiDir ?? (it.make?.apiDir ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
{{?(it.web_make?.mkincDir || it.make?.mkincDir)}}
|
|
||||||
MKINC_DIR := {{=it.web_make?.mkincDir ?? (it.make?.mkincDir ?? "")}}
|
|
||||||
{{?}}
|
|
||||||
|
|
||||||
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}}
|
||||||
|
|
||||||
{{?it.make?.extra}}
|
|
||||||
{{=it.make.extra}}
|
|
||||||
{{?}}
|
|
||||||
{{?it.web_make?.extra}}
|
|
||||||
{{=it.web_make.extra}}
|
|
||||||
{{?}}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024, 2025 Orastron Srl unipersonale
|
* Copyright (C) 2024 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -44,7 +44,3 @@ static size_t param_out_index[DATA_PRODUCT_PARAMETERS_OUTPUT_N] = {
|
|||||||
{{~it.product.parameters :p:i}}{{?p.direction == "output"}}{{=i}}, {{?}}{{~}}
|
{{~it.product.parameters :p:i}}{{?p.direction == "output"}}{{=i}}, {{?}}{{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{{?it.product.state && it.product.state.dspCustom}}
|
|
||||||
#define DATA_STATE_DSP_CUSTOM
|
|
||||||
{{?}}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* Tibia
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022-2025 Orastron Srl unipersonale
|
* Copyright (C) 2022-2024 Orastron Srl unipersonale
|
||||||
*
|
*
|
||||||
* Tibia is free software: you can redistribute it and/or modify
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "plugin_api.h"
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
@ -46,22 +45,11 @@ typedef struct {
|
|||||||
} instance;
|
} instance;
|
||||||
|
|
||||||
instance * processor_new(float sample_rate) {
|
instance * processor_new(float sample_rate) {
|
||||||
#ifdef DATA_STATE_DSP_CUSTOM
|
|
||||||
(void)plugin_state_load;
|
|
||||||
(void)plugin_state_save;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
instance * i = malloc(sizeof(instance));
|
instance * i = malloc(sizeof(instance));
|
||||||
if (i == NULL)
|
if (i == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
plugin_callbacks cbs = {
|
plugin_init(&i->p);
|
||||||
/* .handle = */ NULL,
|
|
||||||
/* .format = */ "web",
|
|
||||||
/* .get_bindir = */ NULL,
|
|
||||||
/* .get_datadir = */ NULL
|
|
||||||
};
|
|
||||||
plugin_init(&i->p, &cbs);
|
|
||||||
|
|
||||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
#if DATA_PRODUCT_PARAMETERS_N > 0
|
||||||
for (size_t j = 0; j < DATA_PRODUCT_PARAMETERS_N; j++)
|
for (size_t j = 0; j < DATA_PRODUCT_PARAMETERS_N; j++)
|
||||||
|
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": {
|
"android": {
|
||||||
"javaPackageName": "com.example.tibia_test",
|
"javaPackageName": "com.example.tibia_test"
|
||||||
"androidVersion": "36"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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": {
|
"ios_make": {
|
||||||
"headerSearchPaths": [ "../../../../../miniaudio" ],
|
"headerSearchPaths": [ "../../../../../miniaudio" ],
|
||||||
"deploymentTarget": "16.6"
|
"deploymentTarget": 16.6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"uri": "@example:tibia_test",
|
"uri": "@example:tibia_test",
|
||||||
"project": "@example:project",
|
"project": "@example:project",
|
||||||
"types": [ "@lv2:AmplifierPlugin" ],
|
"types": [ "@lv2:AmplifierPlugin" ],
|
||||||
"version": "1.0"
|
"version": "1.0",
|
||||||
|
"busSymbols": [ "input", "output", "midi_in", "midi_out" ],
|
||||||
|
"parameterSymbols": [ "gain", "delay", "cutoff", "enabled", "yz1" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
110
test/plugin.h
110
test/plugin.h
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tibia
|
* 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
|
* Tibia is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -18,27 +18,24 @@
|
|||||||
* File author: Stefano D'Angelo
|
* File author: Stefano D'Angelo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct plugin {
|
typedef struct plugin {
|
||||||
float sample_rate;
|
float sample_rate;
|
||||||
size_t delay_line_length;
|
size_t delay_line_length;
|
||||||
|
|
||||||
float gain;
|
float gain;
|
||||||
float delay;
|
float delay;
|
||||||
float cutoff;
|
float cutoff;
|
||||||
char bypass;
|
char bypass;
|
||||||
|
|
||||||
float * delay_line;
|
float * delay_line;
|
||||||
size_t delay_line_cur;
|
size_t delay_line_cur;
|
||||||
float z1;
|
float z1;
|
||||||
float cutoff_k;
|
float cutoff_k;
|
||||||
float yz1;
|
float yz1;
|
||||||
} plugin;
|
} plugin;
|
||||||
|
|
||||||
static void plugin_init(plugin *instance, const plugin_callbacks *cbs) {
|
static void plugin_init(plugin *instance) {
|
||||||
(void)instance;
|
(void)instance;
|
||||||
(void)cbs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_fini(plugin *instance) {
|
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) {
|
static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case plugin_parameter_gain:
|
case 0:
|
||||||
instance->gain = value;
|
//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;
|
break;
|
||||||
case plugin_parameter_delay:
|
case 1:
|
||||||
instance->delay = value;
|
instance->delay = 0.001f * value;
|
||||||
break;
|
break;
|
||||||
case plugin_parameter_cutoff:
|
case 2:
|
||||||
instance->cutoff = value;
|
instance->cutoff = value;
|
||||||
break;
|
break;
|
||||||
case plugin_parameter_bypass:
|
case 3:
|
||||||
instance->bypass = value >= 0.5f;
|
instance->bypass = value >= 0.5f;
|
||||||
break;
|
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) {
|
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);
|
//approx size_t delay = roundf(instance->sample_rate * instance->delay);
|
||||||
const float gain = ((2.6039890429412597e-4f * instance->gain + 0.032131027163547855f) * instance->gain + 1.f) / ((0.0012705124328080768f * instance->gain - 0.0666763481312185f) * instance->gain + 1.f);
|
size_t delay = (size_t)(instance->sample_rate * instance->delay + 0.5f);
|
||||||
//approx const size_t delay = roundf(instance->sample_rate * 0.001f * instance->delay);
|
|
||||||
const size_t delay = (size_t)(instance->sample_rate * 0.001f * instance->delay + 0.5f);
|
|
||||||
const float mA1 = instance->sample_rate / (instance->sample_rate + 6.283185307179586f * instance->cutoff * instance->cutoff_k);
|
const float mA1 = instance->sample_rate / (instance->sample_rate + 6.283185307179586f * instance->cutoff * instance->cutoff_k);
|
||||||
for (size_t i = 0; i < n_samples; i++) {
|
for (size_t i = 0; i < n_samples; i++) {
|
||||||
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
||||||
@ -108,7 +104,7 @@ static void plugin_process(plugin *instance, const float **inputs, float **outpu
|
|||||||
instance->delay_line_cur = 0;
|
instance->delay_line_cur = 0;
|
||||||
const float y = x + mA1 * (instance->z1 - x);
|
const float y = x + mA1 * (instance->z1 - x);
|
||||||
instance->z1 = y;
|
instance->z1 = y;
|
||||||
outputs[0][i] = instance->bypass ? inputs[0][i] : gain * y;
|
outputs[0][i] = instance->bypass ? inputs[0][i] : instance->gain * y;
|
||||||
instance->yz1 = outputs[0][i];
|
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));
|
//approx instance->cutoff_k = powf(2.f, (1.f / 12.f) * (note - 60));
|
||||||
instance->cutoff_k = data[1] < 64 ? (-0.19558034980097166f * data[1] - 2.361735109225749f) / (data[1] - 75.57552349522389f) : (393.95397927344214f - 7.660826245588588f * data[1]) / (data[1] - 139.0755234952239f);
|
instance->cutoff_k = data[1] < 64 ? (-0.19558034980097166f * data[1] - 2.361735109225749f) / (data[1] - 75.57552349522389f) : (393.95397927344214f - 7.660826245588588f * data[1]) / (data[1] - 139.0755234952239f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialize_float(uint8_t *dest, float f) {
|
|
||||||
union { float f; uint32_t u; } v;
|
|
||||||
v.f = f;
|
|
||||||
dest[0] = v.u & 0xff;
|
|
||||||
dest[1] = (v.u & 0xff00) >> 8;
|
|
||||||
dest[2] = (v.u & 0xff0000) >> 16;
|
|
||||||
dest[3] = (v.u & 0xff000000) >> 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float parse_float(const uint8_t *data) {
|
|
||||||
union { float f; uint32_t u; } v;
|
|
||||||
v.u = data[0];
|
|
||||||
v.u |= data[1] << 8;
|
|
||||||
v.u |= data[2] << 16;
|
|
||||||
v.u |= data[3] << 24;
|
|
||||||
return v.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int plugin_state_save(plugin *instance, const plugin_state_callbacks *cbs, float last_sample_rate) {
|
|
||||||
(void)last_sample_rate;
|
|
||||||
uint8_t data[13];
|
|
||||||
cbs->lock(cbs->handle);
|
|
||||||
const float gain = instance->gain;
|
|
||||||
const float delay = instance->delay;
|
|
||||||
const float cutoff = instance->cutoff;
|
|
||||||
const char bypass = instance->bypass;
|
|
||||||
cbs->unlock(cbs->handle);
|
|
||||||
serialize_float(data, gain);
|
|
||||||
serialize_float(data + 4, delay);
|
|
||||||
serialize_float(data + 8, cutoff);
|
|
||||||
data[12] = bypass ? 1 : 0;
|
|
||||||
return cbs->write(cbs->handle, (const char *)data, 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char x_isnan(float x) {
|
|
||||||
union { uint32_t u; float f; } v;
|
|
||||||
v.f = x;
|
|
||||||
return ((v.u & 0x7f800000) == 0x7f800000) && (v.u & 0x7fffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int plugin_state_load(const plugin_state_callbacks *cbs, float cur_sample_rate, const char *data, size_t length) {
|
|
||||||
(void)cur_sample_rate;
|
|
||||||
if (length != 13)
|
|
||||||
return -1;
|
|
||||||
const uint8_t *d = (const uint8_t *)data;
|
|
||||||
const float gain = parse_float(d);
|
|
||||||
const float delay = parse_float(d + 4);
|
|
||||||
const float cutoff = parse_float(d + 8);
|
|
||||||
const float bypass = d[12] ? 1.f : 0.f;
|
|
||||||
if (x_isnan(gain) || x_isnan(delay) || x_isnan(cutoff))
|
|
||||||
return -1;
|
|
||||||
cbs->lock(cbs->handle);
|
|
||||||
cbs->set_parameter(cbs->handle, plugin_parameter_gain, gain);
|
|
||||||
cbs->set_parameter(cbs->handle, plugin_parameter_delay, delay);
|
|
||||||
cbs->set_parameter(cbs->handle, plugin_parameter_cutoff, cutoff);
|
|
||||||
cbs->set_parameter(cbs->handle, plugin_parameter_bypass, bypass);
|
|
||||||
cbs->unlock(cbs->handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
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",
|
"channels": "mono",
|
||||||
"name": "Input",
|
"name": "Input",
|
||||||
"shortName": "Input",
|
"shortName": "Input",
|
||||||
"id": "input",
|
|
||||||
"sidechain": false,
|
"sidechain": false,
|
||||||
"cv": false,
|
"cv": false,
|
||||||
"optional": false
|
"optional": false
|
||||||
@ -22,7 +21,6 @@
|
|||||||
"channels": "mono",
|
"channels": "mono",
|
||||||
"name": "Output",
|
"name": "Output",
|
||||||
"shortName": "Output",
|
"shortName": "Output",
|
||||||
"id": "output",
|
|
||||||
"sidechain": false,
|
"sidechain": false,
|
||||||
"cv": false,
|
"cv": false,
|
||||||
"optional": false
|
"optional": false
|
||||||
@ -32,7 +30,6 @@
|
|||||||
"direction": "input",
|
"direction": "input",
|
||||||
"name": "MIDI input",
|
"name": "MIDI input",
|
||||||
"shortName": "MIDI input",
|
"shortName": "MIDI input",
|
||||||
"id": "midi_in",
|
|
||||||
"sidechain": true,
|
"sidechain": true,
|
||||||
"control": true,
|
"control": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
@ -42,7 +39,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Gain",
|
"name": "Gain",
|
||||||
"shortName": "Gain",
|
"shortName": "Gain",
|
||||||
"id": "gain",
|
|
||||||
"direction": "input",
|
"direction": "input",
|
||||||
"isBypass": false,
|
"isBypass": false,
|
||||||
"isLatency": false,
|
"isLatency": false,
|
||||||
@ -64,7 +60,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Delay",
|
"name": "Delay",
|
||||||
"shortName": "Delay",
|
"shortName": "Delay",
|
||||||
"id": "delay",
|
|
||||||
"direction": "input",
|
"direction": "input",
|
||||||
"isBypass": false,
|
"isBypass": false,
|
||||||
"isLatency": false,
|
"isLatency": false,
|
||||||
@ -81,7 +76,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Cutoff",
|
"name": "Cutoff",
|
||||||
"shortName": "Cutoff",
|
"shortName": "Cutoff",
|
||||||
"id": "cutoff",
|
|
||||||
"direction": "input",
|
"direction": "input",
|
||||||
"isBypass": false,
|
"isBypass": false,
|
||||||
"isLatency": false,
|
"isLatency": false,
|
||||||
@ -98,7 +92,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Bypass",
|
"name": "Bypass",
|
||||||
"shortName": "Bypass",
|
"shortName": "Bypass",
|
||||||
"id": "bypass",
|
|
||||||
"direction": "input",
|
"direction": "input",
|
||||||
"isBypass": true,
|
"isBypass": true,
|
||||||
"isLatency": false,
|
"isLatency": false,
|
||||||
@ -119,7 +112,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yz1",
|
"name": "yz1",
|
||||||
"shortName": "yz1",
|
"shortName": "yz1",
|
||||||
"id": "yz1",
|
|
||||||
"direction": "output",
|
"direction": "output",
|
||||||
"isBypass": false,
|
"isBypass": false,
|
||||||
"isLatency": false,
|
"isLatency": false,
|
||||||
@ -133,13 +125,6 @@
|
|||||||
"unit": "",
|
"unit": "",
|
||||||
"map": "linear"
|
"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
|
#!/bin/sh
|
||||||
|
|
||||||
dir=`dirname $0`
|
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 $dir/../out/vst3
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3-make $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/plugin_ui.h $dir/../out/vst3/src
|
cp $dir/plugin.h $dir/../out/vst3/src
|
||||||
cp $dir/vars-pre.mk $dir/../out/vst3
|
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2-make $dir/../out/lv2
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2-make $dir/../out/lv2
|
||||||
cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src
|
cp $dir/plugin.h $dir/../out/lv2/src
|
||||||
cp $dir/vars-pre.mk $dir/../out/lv2
|
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-make $dir/../out/web
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-make $dir/../out/web
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-demo $dir/../out/web
|
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web-demo $dir/../out/web
|
||||||
cp $dir/plugin.h $dir/../out/web/src
|
cp $dir/plugin.h $dir/../out/web/src
|
||||||
cp $dir/vars-pre.mk $dir/vars-extra.mk $dir/rules-extra.mk $dir/../out/web
|
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android $dir/../out/android
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../templates/android $dir/../out/android
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/android.json $dir/../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/keystore.jks $dir/../out/android
|
||||||
cp $dir/plugin.h $dir/../out/android/src
|
cp $dir/plugin.h $dir/../out/android/src
|
||||||
cp $dir/vars-pre.mk $dir/../out/android
|
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json $dir/../templates/ios $dir/../out/ios
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json $dir/../templates/ios $dir/../out/ios
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json,$dir/ios-make.json $dir/../templates/ios-make $dir/../out/ios
|
$dir/../tibia $dir/product.json,$dir/company.json,$dir/ios.json,$dir/ios-make.json $dir/../templates/ios-make $dir/../out/ios
|
||||||
cp $dir/plugin.h $dir/../out/ios/src
|
cp $dir/plugin.h $dir/../out/ios/src
|
||||||
cp $dir/vars-pre.mk $dir/../out/ios
|
|
||||||
|
|
||||||
$dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/cmd $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/../templates/cmd-make $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/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 $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/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": {
|
"controller": {
|
||||||
"cid": "ecf4f431312f44fbb37b88c545ae9993"
|
"cid": "ecf4f431312f44fbb37b88c545ae9993"
|
||||||
},
|
},
|
||||||
"subCategory": "Fx"
|
"subCategory": "FX"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
47
tibia
47
tibia
@ -2,56 +2,37 @@
|
|||||||
|
|
||||||
function usage() {
|
function usage() {
|
||||||
console.log("Usage:");
|
console.log("Usage:");
|
||||||
console.log(" tibia 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 [override1=value1] [override2=value2] ...");
|
console.log(" tibia --common template outDirectory");
|
||||||
console.log(" tibia --data file1.json,file2.json,...filen.json template outDirectory [override1=value1] [override2=value2] ...");
|
console.log(" tibia --data file1.json,file2.json,...filen.json template outDirectory");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonFiles, template, outputDir, outputCommon, outputData, i;
|
var jsonFiles, template, outputDir, outputCommon, outputData;
|
||||||
if (process.argv[2] == "--common") {
|
if (process.argv[2] == "--common") {
|
||||||
if (process.argv.length < 5)
|
if (process.argv.length != 5)
|
||||||
usage();
|
usage();
|
||||||
jsonFiles = [];
|
jsonFiles = [];
|
||||||
template = process.argv[3];
|
template = process.argv[3];
|
||||||
outputDir = process.argv[4];
|
outputDir = process.argv[4];
|
||||||
outputCommon = true;
|
outputCommon = true;
|
||||||
outputData = false;
|
outputData = false;
|
||||||
i = 5;
|
|
||||||
} else if (process.argv[2] == "--data") {
|
} else if (process.argv[2] == "--data") {
|
||||||
if (process.argv.length < 6)
|
if (process.argv.length != 6)
|
||||||
usage();
|
usage();
|
||||||
jsonFiles = process.argv[3].split(",");
|
jsonFiles = process.argv[3].split(",");
|
||||||
template = process.argv[4];
|
template = process.argv[4];
|
||||||
outputDir = process.argv[5];
|
outputDir = process.argv[5];
|
||||||
outputCommon = false;
|
outputCommon = false;
|
||||||
outputData = true;
|
outputData = true;
|
||||||
i = 6;
|
|
||||||
} else {
|
} else {
|
||||||
if (process.argv.length < 5)
|
if (process.argv.length != 5)
|
||||||
usage();
|
usage();
|
||||||
jsonFiles = process.argv[2].split(",");
|
jsonFiles = process.argv[2].split(",");
|
||||||
template = process.argv[3];
|
template = process.argv[3];
|
||||||
outputDir = process.argv[4];
|
outputDir = process.argv[4];
|
||||||
outputCommon = true;
|
outputCommon = true;
|
||||||
outputData = true;
|
outputData = true;
|
||||||
i = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
var overrides = [];
|
|
||||||
for (; i < process.argv.length; i++) {
|
|
||||||
var o = process.argv[i];
|
|
||||||
var r = o.match(/^([_a-zA-Z][_a-zA-Z0-9]*(\.[_a-zA-Z][_a-zA-Z0-9]*)*)=/);
|
|
||||||
if (!r)
|
|
||||||
usage();
|
|
||||||
var p = r[1].split(".");
|
|
||||||
var v = o.substring(r[0].length);
|
|
||||||
try {
|
|
||||||
v = JSON.parse(v);
|
|
||||||
} catch (e) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
overrides.push({ property: p, value: v });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
@ -73,13 +54,6 @@ for (var i = 0; i < jsonFiles.length; i++) {
|
|||||||
for (var k in d)
|
for (var k in d)
|
||||||
data[k] = d[k];
|
data[k] = d[k];
|
||||||
}
|
}
|
||||||
for (var i = 0; i < overrides.length; i++) {
|
|
||||||
var p = data;
|
|
||||||
var o = overrides[i];
|
|
||||||
for (var j = 0; j < o.property.length - 1; j++)
|
|
||||||
p = p[o.property[j]];
|
|
||||||
p[o.property[o.property.length - 1]] = o.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (outputData) {
|
if (outputData) {
|
||||||
@ -171,13 +145,6 @@ data.tibia = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
},
|
|
||||||
|
|
||||||
sdbm: function (s) {
|
|
||||||
var hash = 0;
|
|
||||||
for (var i = 0; i < s.length; i++)
|
|
||||||
hash = s.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
|
|
||||||
return hash >>> 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user