Skip to content

Commit

Permalink
add files
Browse files Browse the repository at this point in the history
  • Loading branch information
Trinitou committed Feb 14, 2023
1 parent a8c2462 commit be3bd72
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
23 changes: 23 additions & 0 deletions Readme.md
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.
3 changes: 3 additions & 0 deletions doc/help.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
html {
font: 14px "Lucida Grande", Lucida, Verdana, sans-serif;
}
31 changes: 31 additions & 0 deletions doc/help.md
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'*)
28 changes: 28 additions & 0 deletions generate_release.ps1
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
1 change: 1 addition & 0 deletions src/launch xjadeo.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"C:\Program Files\xjadeo\xjadeo.exe" -O 12345
102 changes: 102 additions & 0 deletions src/xJadeo Video Sync.control.js
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("");
}

0 comments on commit be3bd72

Please sign in to comment.