Skip to content

Commit

Permalink
Merge pull request #53 from matejsemancik/feature/processing4
Browse files Browse the repository at this point in the history
Processing 4
  • Loading branch information
matejsemancik committed Sep 12, 2022
2 parents 7ff766a + 64d498a commit 3f2bd02
Show file tree
Hide file tree
Showing 22 changed files with 174 additions and 99 deletions.
14 changes: 14 additions & 0 deletions .run/PlaygroundApp.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="PlaygroundApp" type="JetRunConfigurationType" nameIsGenerated="true">
<option name="ALTERNATIVE_JRE_PATH" value="azul-11" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="MAIN_CLASS_NAME" value="dev.matsem.astral.playground.PlaygroundApp" />
<module name="astral-visuals.playground.main" />
<option name="PROGRAM_PARAMETERS" value="--sketch-path=$PROJECT_DIR$" />
<shortenClasspath name="NONE" />
<option name="VM_PARAMETERS" value="-Djava.library.path=/Applications/Processing.app/Contents/Java/core/library/macos-x86_64" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
14 changes: 14 additions & 0 deletions .run/VisualsApp.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="VisualsApp" type="JetRunConfigurationType" nameIsGenerated="true">
<option name="ALTERNATIVE_JRE_PATH" value="azul-11" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="MAIN_CLASS_NAME" value="dev.matsem.astral.visuals.VisualsApp" />
<module name="astral-visuals.visuals.main" />
<option name="PROGRAM_PARAMETERS" value="--sketch-path=$PROJECT_DIR$" />
<shortenClasspath name="NONE" />
<option name="VM_PARAMETERS" value="-Djava.library.path=/Applications/Processing.app/Contents/Java/core/library/macos-x86_64" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
3 changes: 3 additions & 0 deletions .sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=11.0.11-zulu
57 changes: 33 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,56 +13,62 @@ The `:visuals` module is meant to be used in live environment at the parties. Th

## How to build

This project depends on local [Processing](https://processing.org) installation, so go ahead and install it if you haven't already. Then create a `local.properties` file in project's root directory and configure the core library and contributed libraries' paths:
This project depends on local [Processing 4](https://processing.org) installation, so go ahead and install it if you haven't already. Then create a `local.properties` file in project's root directory and configure the core library and contributed libraries' paths:

```
processingLibsDir=/path/to/your/processing/libraries/dir
processingCoreDir=/path/to/core/processing/libraries
processing.core.jars=/path/to/your/processing/libraries/dir
processing.core.natives=/path/to/your/processing/libraries/dir/<os-architecture>
processing.libs.jars=/path/to/core/processing/libraries
```

On macOS it might look like this:

```
processingLibsDir=/Users/username/Documents/Processing/libraries
processingCoreDir=/Applications/Processing.app/Contents/Java/core/library
processing.core.jars=/Applications/Processing.app/Contents/Java/core/library
processing.core.natives=/Applications/Processing.app/Contents/Java/core/library/macos-x86_64
processing.libs.jars=/Users/matsem/Documents/Processing/libraries
```

The Gradle buildscript will look for Processing dependencies at these two paths. Dependencies are defined in CommonDependencies gradle plugin. Open it up, and you can notice that this project depends on some 3rd party libraries, which need to be installed at `processingLibsDir` path. Open your Processing library manager (Sketch > Import Library > Add library) and install whatever libraries are specified in the `build.gradle` file.
The Gradle buildscript will look for Processing dependencies at these two paths. Dependencies are defined in CommonDependencies gradle plugin. Open it up, and you can notice that this project depends on some 3rd party libraries, which need to be installed at `processing.libs.jars` path. Open your Processing library manager (Sketch > Import Library > Add library) and install whatever libraries are specified in the `build.gradle` file.

Current list of library dependencies is

```
Minim // audio processing
The MidiBus // for remote control
Video Export // I use this to export video teasers synced with external audio file
Box2D for Processing // for physics (look for BoxesSketch)
Video // video playback
extruder // 2d shape -> 3d shape extrusion
geomerative // for generating shapes from text
PostFX for Processing // can apply post-processing shaders
```

If you've set up everything correctly, you should be able to build the project using Gradle `build` task.

```
./gradlew build
```kotlin
val processingLibs = listOf(
"minim", // audio input everything (input source, fft analysis, etc.)
"themidibus", // MIDI control protocol implementation
"VideoExport", // I use this to export video teasers synced with external audio file
"box2d_processing", // for physics (look for Gravity sketch in playground module)
"video", // video playback
"extruder", // 2d shape -> 3d shape extrusion
"geomerative", // text -> shape, svg -> shape conversion
"peasycam", // adds camera handling to the sketches, nice to have when prototyping
"PostFX", // can apply post-processing shaders to video output
"oscP5", // OSC control protocol implementation
"blobDetection" // library to find "blobs" on image
)
```

## How to run

You can run the project with Gradle `run` task. Be sure to include the `--sketch-path` argument so sketches can properly resolve the data folder with resources.
You can run the project with Gradle `run` task. Be sure to include the `--sketch-path` argument so sketches can properly resolve the data folder containing resources needed by some Sketches.

```
./gradlew playground:run --args='--sketch-path=/path/to/project/'
./gradlew visuals:run --args='--sketch-path=/path/to/project/'
```

There are also IntelliJ Run configurations in `.run` folder which you can use to run the app from IDE. Just be sure to edit their configuration to match your setup.

Note: Due to the fragileness of Processing dependencies (namely JogAmp), the project currently works only with some JDK versions, specifically `11.0.11-zulu`. You can find `.sdkmanrc` file in project folder
that sets up the current SDK for you if you use [SDKMAN!](https://sdkman.io/). (`11.0.12` does not work yet, causing [this](https://github.com/processing/processing4/issues/249) issue).

## Remote control
Currently, the project supports 3 remote control options:

- If you own Traktor Kontrol F1, the `KontrolF1` class is for you - I use it for quick prototyping. It handles most of KontrolF1's hardware features, like pad buttons (with colors feature), encoder, knobs and faders.
- If you'd like to try the `:visuals` module, go ahead and get yourself the [TouchOSC](https://hexler.net/products/touchosc) app and load it with `Astral.touchosc` layout that can be found in the `touchosc` folder. This layout uses MIDI and OSC protocol and there is a `Galaxy` class that handles most of TouchOSC MIDI controls. For future, I plan on to get rid of `Galaxy` and migrate everyhing to OSC protocol, which leads us to the last option
- OSC - The most convinient way, though, is to use the [OSC](http://opensoundcontrol.org/introduction-osc) (Open Sound Control) with Delegated Properties
- OSC - The most convenient way, though, is to use the [OSC](http://opensoundcontrol.org/introduction-osc) (Open Sound Control) with Delegated Properties

### Osc Delegated Properties
First, make your sketch/class implement the `OscHandler` interface, which makes you provide the `OscManager` class.
Expand All @@ -87,4 +93,7 @@ Then, you can create all sorts of properties tied to various OSC controls, like
private var fader1: Float by oscFaderDelegate("/1/fader1", defaultValue = 0.5f)
```

Most of the delegated properties support writing, so, if for example you create the fader variable and at some point in time you assing the value into it, the corresponding control in TouchOSC app will reflect that change.
Most of the delegated properties support value assign, so, if for example you create the fader variable and at some point in time you assign the value into it, the corresponding control in TouchOSC app will reflect that change.

## Known bugs after Processing4 migration
- movie library does not work (issues with linking native libs)
9 changes: 4 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("jvm") version "1.4.31"
kotlin("plugin.serialization") version "1.4.31"
kotlin("jvm") version Versions.kotlin
kotlin("plugin.serialization") version Versions.kotlin
}

group = ProjectSettings.group
Expand All @@ -19,15 +19,14 @@ dependencies {

tasks {
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}
}

val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions {
freeCompilerArgs = listOf("-Xinline-classes")
useIR = true
}
8 changes: 4 additions & 4 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
object Dependencies {
const val koin = "org.koin:koin-core:2.1.5"
const val serializationCore = "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC"
const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.4"
const val koin = "org.koin:koin-core:${Versions.koin}"
const val serializationJson = "org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.serializationJson}"
const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}"

val processingLibs = listOf(
"minim",
"themidibus",
Expand All @@ -13,7 +14,6 @@ object Dependencies {
"peasycam",
"PostFX",
"oscP5",
"ControlP5",
"blobDetection"
)
}
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/ProjectSettings.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
object ProjectSettings {
val version = "2.0.0"
val group = "dev.matsem"
const val version = "2.1.0"
const val group = "dev.matsem"
}
6 changes: 6 additions & 0 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object Versions {
const val kotlin = "1.6.10"
const val serializationJson = "1.3.2"
const val coroutines = "1.6.0"
const val koin = "2.1.5"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ internal fun Project.configureCommonDependencies() {
val props = Properties().apply {
load(file("${rootDir}/local.properties").inputStream())
}
val processingCoreDir = props["processingCoreDir"]
val processingLibsDir = props["processingLibsDir"]
val processingCoreDir = props["processing.core.jars"]
val processingLibsDir = props["processing.libs.jars"]

dependencies {
add("implementation", kotlin("bom"))
add("implementation", kotlin("stdlib-jdk8"))
add("implementation", Dependencies.koin)
add("implementation", Dependencies.coroutines)
Expand Down
6 changes: 3 additions & 3 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ repositories {
}

dependencies {
implementation(Dependencies.serializationCore)
implementation(Dependencies.serializationJson)
}

group = ProjectSettings.group
version = ProjectSettings.version

tasks {
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}
}
29 changes: 18 additions & 11 deletions core/src/main/kotlin/dev/matsem/astral/core/di/CoreModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,37 @@ import shiffman.box2d.Box2DProcessing

val coreModule = module {
single { KontrolF1() }
single { Galaxy(get()) }
single { Galaxy(parent = get()) }

single { MidiFileParser(get()) }
factory { MidiRecorder(get()) }
factory { MidiPlayer(get()) }
factory { MidiAutomator(get(), get(), get()) }
single { OscManager(get(), OscManager.INPUT_PORT, OscManager.OUTPUT_IP, OscManager.OUTPUT_PORT) }
single { MidiFileParser(sketch = get()) }
factory { MidiRecorder(sketch = get()) }
factory { MidiPlayer(sketch = get()) }
factory { MidiAutomator(midiRecorder = get(), midiPlayer = get(), galaxy = get()) }
single {
OscManager(
sketch = get(),
inputPort = OscManager.INPUT_PORT,
outputIp = OscManager.OUTPUT_IP,
outputPort = OscManager.OUTPUT_PORT
)
}

// Audio
single { Minim(get() as PApplet) }
single { (get() as Minim).lineOut }
single { (get() as Minim).lineIn }
single { Sink().apply { patch(get() as AudioOutput) } }
single { AudioProcessor(get()) }
factory { BeatCounter(get(), get()) }
single { AudioProcessor(lineIn = get()) }
factory { BeatCounter(parent = get(), audioProcessor = get()) }

// Extrusion
single { extruder.extruder(get()) }
single { ExtrusionCache(get(), get()) }
single { ExtrusionCache(sketch = get(), ex = get()) }

// VideoExporter
single { VideoExport(get()) }
single { FFTSerializer(get(), get()) }
factory { VideoExporter(get(), get(), get(), get()) }
single { FFTSerializer(parent = get(), minim = get()) }
factory { VideoExporter(parent = get(), videoExport = get(), fftSerializer = get(), audioProcessor = get()) }

factory {
Box2DProcessing(get()).apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,6 @@ fun PGraphics.fadeToBlackBy(fadeAmount: Float) {
updatePixels()
}

fun PGraphics.decreaseAlpha(amount: Float) {
loadPixels()
for (i in 0 until pixels.count()) {
pixels[i] = pixels[i].withAlpha(10)
}
updatePixels()
}

fun PGraphics.colorModeHsb() = colorMode(
PConstants.HSB,
ColorConfig.HUE_MAX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class OscManager(
companion object {
const val INPUT_PORT = 7001
const val OUTPUT_PORT = 7001
const val OUTPUT_IP = "192.168.1.17"
const val OUTPUT_IP = "192.168.1.27"
}
private val outputDevice = NetAddress(outputIp, outputPort)
private val oscP5: OscP5 by lazy { OscP5(sketch, inputPort) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,26 @@ class ExtrusionCache(
endShape(PConstants.CLOSE)
}

val depth = 50
mutableListOf<PShape>().apply {
this += ex.extrude(upper, depth, "box")
this += ex.extrude(lower, depth, "box")
forEach { it.translate(-50f, -50f, -depth / 2f) }
this += ex.extrude(upper, 100, "box")
this += ex.extrude(lower, 100, "box")
forEach { it.translate(-50f, -50f) }
}.toTypedArray()
}

private val textCache = mutableMapOf<String, Array<PShape>>()

fun getText(text: String, fontSize: Int = 48, depth: Int = 20): Array<PShape> {
fun getText(text: String): Array<PShape> {
return textCache.getOrPut(text) {

val rShape = RG.getText(text, Files.Font.FFF_FORWARD, fontSize, PApplet.CENTER)
val rShape = RG.getText(text, Files.Font.FFF_FORWARD, 48, PApplet.CENTER)

RG.setPolygonizer(RG.UNIFORMSTEP)
RG.setPolygonizerStep(1f)

val letters = rShape.children

letters
.asSequence()
.map { it.points }
.map { points ->
sketch.createShape().apply {
Expand All @@ -72,9 +70,7 @@ class ExtrusionCache(
endShape(PApplet.CLOSE)
}
}
.flatMap { ex.extrude(it, depth, "box").toList() }
.onEach { it.translate(0f, fontSize / 2f, -depth / 2f) }
.toList()
.flatMap { ex.extrude(it, 20, "box").toList() }
.toTypedArray()
}
}
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
17 changes: 13 additions & 4 deletions playground/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import java.util.*

plugins {
kotlin("jvm")
application
}

apply<dev.matsem.astral.CommonDependencies>()

@Suppress("UnstableApiUsage")
application {
mainClassName = "dev.matsem.astral.playground.PlaygroundApp"
val props = Properties().apply {
load(file("${rootDir}/local.properties").inputStream())
}
val nativesDir = props["processing.core.natives"]

mainClass.set("dev.matsem.astral.playground.PlaygroundApp")
applicationDefaultJvmArgs = listOf(
"-Djava.library.path=$nativesDir"
)
}

repositories {
Expand All @@ -24,9 +33,9 @@ version = ProjectSettings.version

tasks {
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}
}
Loading

0 comments on commit 3f2bd02

Please sign in to comment.