-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Video playback for Bitwig Studio using xjadeo. | ||
|
||
A lightweight solution for video playback with [Bitwig Studio](https://www.bitwig.com/de/overview/) using [xjadeo](https://xjadeo.sourceforge.net). A video file can be added per Bitwig project which then will be played back in sync with Bitwig's transport. Also the video will be saved and opened together with the project automatically. | ||
|
||
The implementation makes use of xjadeo's OSC remote control capabilities which are documented [here](https://xjadeo.sourceforge.net/osc.html). | ||
|
||
## Setup | ||
|
||
1. Put the .js into the Bitwig controller script folder | ||
2. Add the controller script in Bitwig Studio | ||
- via *Dashboard -> 'Settings' -> 'Controllers' -> '+ Add Controller'* | ||
- select hardware vendor: 'xjadeo' | ||
- select product: 'xJadeo Video Sync' | ||
- click *'Add'* | ||
3. Click the "?" icon and follow the setup instructions in the help HTML | ||
|
||
## Build | ||
|
||
Nothing to build for the controller script, but the help documentation HTML is generated from the [help.md](./doc/help.md) using the [generate_HTML.ps1](./doc/generate_HTML.ps1) script which requires Powershell 7 to work. | ||
|
||
## Contribution | ||
|
||
Please feel free to create a pull request if you want to add or change something! Also have a look into open issues if you want so. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
html { | ||
font: 14px "Lucida Grande", Lucida, Verdana, sans-serif; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<head> | ||
<title class="title">xjadeo Video Sync</title> | ||
<style type="text/css" media="all">@import "./doc/help.css";</style> | ||
</head> | ||
|
||
# xJadeo Video Synchronization | ||
|
||
## Setup | ||
|
||
- **Download and install xjadeo**, e.g. from [here](https://xjadeo.sourceforge.net/download.html) | ||
- **Launch the *'launch xJadeo.bat'* script**. This opens the xjadeo window. | ||
- In Bitwig Studio, connect the video file for playback like this: | ||
- Open a project. | ||
- In the *Studio I/O panel*, unfold the *xJadeo Video Sync* settings. | ||
- Enter the absolute video file path under *Path*. | ||
- Enter the original frame rate of the video under 'Frame rate'. | ||
|
||
## Features | ||
- If you save the project and open it later, the video will be opened again together with the project. | ||
- You can easily switch Bitwig project tabs with different videos and the xJadeo window will be udpated on the fly! | ||
- There is a *'Keep on top'* checkbox which will ensure that the video window stays in front of Bitwig Studio. (default: on) | ||
- The *'Flush!'* button in the settings will (re-)send all data to the xJadeo window. This is helpful if xJadeo was opened after Bitwig Studio. | ||
|
||
## Tipps & tricks | ||
|
||
- 'Where to quickly find original video frame?' | ||
- When using the *'launch xJadeo.bat'* script, a console window will open as well. Look into the log text! | ||
- How to hear the original sound of the video file in sync with the video? | ||
- If Bitwig supports the file format, you can drag it into the project so that. | ||
- Place it into the Arranger at position 1.1.1.00 | ||
- Make sure that time-stretching is off for that audio clip (*Mode* set to *'Raw'*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
$version = "0.1" | ||
|
||
$targetTempDir = ".\target\tmp" | ||
New-Item -ItemType Directory -Force -Path $targetTempDir | ||
|
||
$docSourceDir = ".\doc" | ||
$md = ConvertFrom-Markdown -Path "$docSourceDir\help.md" | ||
if($md) { | ||
$md.Html | Out-File -Encoding utf8 "$targetTempDir\xJadeo Video Sync.html" | ||
$helpCssFileName = "help.css" | ||
$cssTargetDir = "$targetTempDir\doc" | ||
New-Item -ItemType Directory -Force -Path "$cssTargetDir" | ||
Copy-Item -Path "$docSourceDir\$helpCssFileName" -Destination "$cssTargetDir\$helpCssFileName" | ||
} | ||
|
||
$sourceDir = ".\src" | ||
$controlScriptPath = "xJadeo Video Sync.control.js" | ||
Copy-Item -Path "$sourceDir\$controlScriptPath" -Destination "$targetTempDir\$controlScriptPath" | ||
$launchScriptPath = "launch xjadeo.bat" | ||
Copy-Item -Path "$sourceDir\$launchScriptPath" -Destination "$targetTempDir\$launchScriptPath" | ||
|
||
$targetZipPath = "$PSScriptRoot\target\xJadeo_Video_Sync_" + ($version -replace '\.', '_') + ".zip" | ||
$compress = @{ | ||
Path = "$targetTempDir\*" | ||
CompressionLevel = "Fastest" | ||
DestinationPath = $targetZipPath | ||
} | ||
Compress-Archive @compress -Force |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"C:\Program Files\xjadeo\xjadeo.exe" -O 12345 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
loadAPI(17); | ||
|
||
host.setShouldFailOnDeprecatedUse(true); | ||
|
||
host.defineController("xjadeo", "xJadeo Video Sync", "0.1", "295c10cb-b8d6-416b-9be5-dc2375936ac0", "Trinitou"); | ||
|
||
var oscConnection; | ||
|
||
var lastOnTopState; | ||
function invalidateLastOnTopState() { | ||
lastOnTopState = null; | ||
} | ||
function updateOnTop(onTop) { | ||
if(onTop == lastOnTopState) | ||
return; | ||
oscConnection.sendMessage("/jadeo/cmd", "window ontop " + (onTop ? "on" : "off")); | ||
lastOnTopState = onTop; | ||
host.println("Sent 'Keep on top' state: " + (onTop ? "on" : "off")); | ||
} | ||
|
||
var lastVideoPath; | ||
function invalidateLastVideoPath() { | ||
lastVideoPath = null; | ||
} | ||
function updateVideo(path) { | ||
if (path === lastVideoPath) | ||
return false; | ||
oscConnection.sendMessage("/jadeo/load", path); // sending an empty path will close current video file | ||
host.println("Sent video path: '" + path + "'"); | ||
lastVideoPath = path; | ||
return true; | ||
} | ||
|
||
var lastFrame; | ||
function invalidateLastFrame() { | ||
lastFrame = -1; | ||
} | ||
function updateFrame(frame) { | ||
if (oscConnection == null) { | ||
invalidateLastFrame(); | ||
return; | ||
} | ||
if (frame != lastFrame) { | ||
oscConnection.sendMessage("/jadeo/seek", frame); | ||
lastFrame = frame; | ||
// host.println("Sent frame: " + lastFrame); | ||
} | ||
} | ||
|
||
function invalidateAll() { | ||
invalidateLastOnTopState(); | ||
invalidateLastVideoPath(); | ||
invalidateLastFrame(); | ||
} | ||
|
||
var onTopSetting; | ||
var pathSetting; | ||
var frameRateSetting; | ||
var pos; | ||
|
||
function init() { | ||
oscConnection = host.getOscModule().connectToUdpServer("localhost", 12345, null); | ||
|
||
let prefs = host.getPreferences(); | ||
|
||
onTopSetting = prefs.getBooleanSetting("Keep on top", "Video window", true); | ||
onTopSetting.markInterested(); | ||
|
||
let docState = host.getDocumentState(); | ||
|
||
pathSetting = docState.getStringSetting("Path", "File", 256, ""); | ||
pathSetting.markInterested(); | ||
|
||
frameRateSetting = docState.getNumberSetting("FPS", "File", 24, 60, 0.01, "", 24); | ||
frameRateSetting.markInterested(); | ||
|
||
// add flush command to both the preferences and document state for easy access: | ||
let settings = [prefs, docState]; | ||
for(var i = 0; i < settings.length; i++) { | ||
settings[i].getSignalSetting("Flush", "Video window", "Flush!").addSignalObserver(function () { | ||
invalidateAll(); | ||
}); | ||
} | ||
|
||
pos = host.createTransport().playPositionInSeconds(); | ||
pos.markInterested(); | ||
|
||
invalidateAll(); | ||
|
||
println("xJadeo Connect initialized!"); | ||
} | ||
|
||
function flush() { | ||
updateOnTop(onTopSetting.get()); | ||
if (updateVideo(pathSetting.get())) | ||
invalidateLastFrame(); | ||
updateFrame(Math.floor(pos.get() * frameRateSetting.getRaw())); | ||
} | ||
|
||
function exit() { | ||
updateVideo(""); | ||
} |