Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- loadAPI(15);
- host.setShouldFailOnDeprecatedUse(true);
- host.defineController(
- "SA",
- "Song Group Auto Activator",
- "1.0",
- "8f8c6f0e-8f4e-4d88-9f6e-91a19e4c5517"
- );
- host.defineMidiPorts(0, 0);
- // --------------------
- // Configuration
- // --------------------
- var TRACK_BANK_SIZE = 32;
- var MARKER_COUNT = 32;
- var CHECK_INTERVAL_MS = 200;
- // Set true if you want n-1, n, and n+1 active.
- // Useful for long delay/reverb tails.
- var KEEP_PREVIOUS_ACTIVE = false;
- // --------------------
- // State
- // --------------------
- var transport;
- var arranger;
- var cueMarkerBank;
- var trackBank;
- var latestTransportPos = 0;
- var currentSongNumber = -1;
- var isRunning = true;
- var markerCache = [];
- var trackCache = [];
- // --------------------
- // Init
- // --------------------
- function init()
- {
- transport = host.createTransport();
- arranger = host.createArranger();
- cueMarkerBank = arranger.createCueMarkerBank(MARKER_COUNT);
- trackBank = host.createMainTrackBank(TRACK_BANK_SIZE, 0, 0);
- setupMarkerObservers();
- setupTrackObservers();
- setupTransportObserver();
- host.showPopupNotification("Song Group Auto Activator loaded");
- println("Song Group Auto Activator loaded");
- }
- // --------------------
- // Observers
- // --------------------
- function setupMarkerObservers()
- {
- for (var i = 0; i < MARKER_COUNT; i++)
- {
- markerCache[i] = {
- name: "",
- position: -1
- };
- var marker = cueMarkerBank.getItemAt(i);
- observeMarkerName(marker, i);
- observeMarkerPosition(marker, i);
- }
- }
- function observeMarkerName(marker, index)
- {
- marker.name().addValueObserver(function(name)
- {
- markerCache[index].name = name;
- });
- }
- function observeMarkerPosition(marker, index)
- {
- marker.position().addValueObserver(function(position)
- {
- markerCache[index].position = position;
- });
- }
- function setupTrackObservers()
- {
- for (var i = 0; i < TRACK_BANK_SIZE; i++)
- {
- var track = trackBank.getItemAt(i);
- trackCache[i] = {
- name: "",
- songNumber: -1,
- soloed: false,
- track: track
- };
- observeTrackName(track, i);
- observeTrackSolo(track, i);
- }
- }
- function observeTrackName(track, index)
- {
- track.name().addValueObserver(function(name)
- {
- trackCache[index].name = name;
- trackCache[index].songNumber = parseSongNumberFromTrackName(name);
- println(
- "Track slot " +
- index +
- ": '" +
- name +
- "', songNumber=" +
- trackCache[index].songNumber
- );
- });
- }
- function observeTrackSolo(track, index)
- {
- track.solo().addValueObserver(function(soloed)
- {
- trackCache[index].soloed = soloed;
- println(
- "Track slot " +
- index +
- " soloed=" +
- soloed
- );
- });
- }
- function setupTransportObserver()
- {
- // This observer only caches the current position.
- // The actual marker scan happens only every CHECK_INTERVAL_MS.
- transport.getPosition().addValueObserver(function(position)
- {
- latestTransportPos = position;
- });
- schedulePositionCheck();
- }
- // --------------------
- // Throttled marker checking
- // --------------------
- function schedulePositionCheck()
- {
- if (!isRunning)
- return;
- checkSongMarkerPosition();
- host.scheduleTask(function()
- {
- schedulePositionCheck();
- }, CHECK_INTERVAL_MS);
- }
- function checkSongMarkerPosition()
- {
- var songNumber = getCurrentSongNumberFromMarkers(latestTransportPos);
- if (songNumber > 0 && songNumber !== currentSongNumber)
- {
- currentSongNumber = songNumber;
- activateSongWindow(songNumber);
- }
- }
- // --------------------
- // Marker/song logic
- // --------------------
- function getCurrentSongNumberFromMarkers(position)
- {
- var selectedSongNumber = -1;
- var selectedMarkerPosition = -1;
- for (var i = 0; i < markerCache.length; i++)
- {
- var marker = markerCache[i];
- if (marker.position < 0)
- continue;
- var markerSongNumber = parseIntegerMarkerName(marker.name);
- if (markerSongNumber <= 0)
- continue;
- if (marker.position <= position && marker.position > selectedMarkerPosition)
- {
- selectedMarkerPosition = marker.position;
- selectedSongNumber = markerSongNumber;
- }
- }
- return selectedSongNumber;
- }
- function activateSongWindow(songNumber)
- {
- var activeNumbers = {};
- activeNumbers[songNumber] = true;
- if (songNumber + 1 <= TRACK_BANK_SIZE)
- activeNumbers[songNumber + 1] = true;
- if (KEEP_PREVIOUS_ACTIVE && songNumber - 1 >= 1)
- activeNumbers[songNumber - 1] = true;
- println("Marker/song " + songNumber + " reached");
- for (var i = 0; i < trackCache.length; i++)
- {
- var entry = trackCache[i];
- var trackSongNumber = entry.songNumber;
- if (trackSongNumber <= 0)
- continue;
- var shouldBeActive = !!activeNumbers[trackSongNumber];
- if (shouldBeActive)
- {
- println(
- "Setting '" +
- entry.name +
- "' active=true"
- );
- entry.track.isActivated().set(true);
- }
- else
- {
- if (entry.soloed)
- {
- println(
- "Keeping '" +
- entry.name +
- "' active because it is soloed"
- );
- // Ensure the soloed group remains active.
- entry.track.isActivated().set(true);
- }
- else
- {
- println(
- "Setting '" +
- entry.name +
- "' active=false"
- );
- entry.track.isActivated().set(false);
- }
- }
- }
- host.showPopupNotification(
- "Active songs: " +
- songNumber +
- (songNumber + 1 <= TRACK_BANK_SIZE ? " + " + (songNumber + 1) : "")
- );
- }
- // --------------------
- // Parsing helpers
- // --------------------
- function parseIntegerMarkerName(name)
- {
- if (!name)
- return -1;
- name = String(name).trim();
- // Marker must be exactly "1", "2", "3", ...
- if (!/^[0-9]+$/.test(name))
- return -1;
- return parseInt(name, 10);
- }
- function parseSongNumberFromTrackName(name)
- {
- if (!name)
- return -1;
- name = String(name).trim();
- // Matches:
- // "1 - Song Name", "2 - Song Name" .. "n - Song Name"
- var match = /^([0-9]+)\s*-\s*/.exec(name);
- if (!match)
- return -1;
- return parseInt(match[1], 10);
- }
- // --------------------
- // Bitwig lifecycle
- // --------------------
- function flush()
- {
- // Nothing to do here
- }
- function exit()
- {
- isRunning = false;
- println("Song Group Auto Activator exited");
- }
Advertisement
Add Comment
Please, Sign In to add comment