Beta version 4.3

IIRC i just tried to clic on the Background scripts/Settings button. Then the “Plugin is loading …” message appeared.

OK. I can’t see that in the log, meaning that the plugin crashed before that. The very last log entry is that it starts the OnInit function for background script 2. What does that function do?

Log:
7e24746b-cfda-4a8c-946c-4994d44949ac

It seems that something is not working as expected with the port configuration actions in background scripts.

I have four background scripts. I have added an init event with ports action configuration to this four scripts, like this:

Background Script 1: (init) {outputport:GP1} {inputport:GP2}

Background Script 2: (init) {outputport:GP9} {inputport:GP10}

Background Script 3: (init) {outputport:GP5} {inputport:GP6}

Background Script 4: (init) {outputport:#none#} {inputport:#none#}

Steps to test this issue:

  1. I set manually all the ports of this four background scripts to ports GP11 and GP12
  2. I click the “Run(init)commands“ button of Global Settings/Background Scripts of every script
  3. The ports changes as expected. It is working well
  4. I set manually again all the ports of this four background scripts to ports GP11 and GP12
  5. I quit the Stream Deck editor
  6. I open again Stream Deck editor
  7. The ports of the background scripts remain GP11 and GP12, they have not changed according to the port change actions of their (init) events

Step 5,6 - Do you mean “Stream Deck editor” or “Stream Deck software”? Init commands are not run when you open the editor.

Here is the code for Background script 2:

/// <reference path="C:/Users/LPA/AppData/Roaming/Elgato/StreamDeck/Plugins/se.trevligaspel.midi.sdPlugin/ScriptJint/streamdeck-midi.d.ts" />
// ------------------------
// Control Change mapping (same style as sysExList)
// ------------------------

const ccList = [
    // Decrease channel (-1) as compared to midiscript

    [1, 27, "g_dev_on", 0],          // Device On/Off


    [2, 0, "g_t_img_idx", 1],   // Selected Track : Index for selected track image, based on Mute, Solo or Arm status
    [2, 1, "g_sb1_img_idx", 1], // Index for session box 1 track image
    [2, 2, "g_sb2_img_idx", 1], // Index for session box 2 track image
    [2, 3, "g_sb3_img_idx", 1], // Index for session box 3 track image
    [2, 4, "g_sb4_img_idx", 1], // Index for session box 4 track image

    [3, 0, "g_tb", 9],          // Twister Bank

    [3, 1, "g_sr", 9],          // Session Record
    [3, 2, "g_sa", 9],          // Session Automation Record

    [15, 0, "g_trackNum", 0],   // Track Number
    [15, 24, "g_sceneNum", 0]   // Scene Number
];

// Fast lookup for CC
const ccMap = Object.fromEntries(
    ccList.map(([ch, ctrl, name]) => [`${ch}_${ctrl}`, name])
);


// ------------------------
// Initialization
// -------------------------

function OnInit() {
    ccList.forEach(([ch, ctrl, name, init]) => {
        gvar.set(name, init ?? 0);
    });
}

// ------------------------
// CC handler
// ------------------------
function OnControlChangeReceived(channel, control, value) {
    //console.warn(`Received CC ${channel},${control},${value}`);
    const key = `${channel}_${control}`;
    const varName = ccMap[key];
    if (!varName) {
        //console.warn(`No variable mapped for CC ${channel},${control}`);
        return;
    }
    //console.warn("BCC seting variable:" + varName + " from " + gvar.get(varName) + " to " + value);
    gvar.set(varName, value);
    
}

I’m afraid that since OnInit() intializes some variables, it triggers things elsewhere.

If you haven’t reverted to the previous version yet, could you please change “level2” to “level3” in the EnableLogging.txt file and restart the Stream Deck software. Then we will have more details about the variable handling.

When I say “Stream Deck Editor” I mean the app “Elgato Stream Deck“. This:

I use the name “Stream Deck Editor” to differentiate it from “Stream Deck Device”.

Regarding the steps 5 and 6 posted before: you will get the same behaviour if you change steps 5 and 6 to this:

5. I unplug the usb cable from Stream Deck device
6. I plug the usb cable again to Stream Deck device

By the way, when the (init) events of the background scripts are executed?

For me, “Stream Deck Device” is of no interest. When you connect/disconnect a device, just about nothing happens; all buttons and dials remain loaded in the Stream Deck software, and you can still edit everything in the editor.

The important difference is “Stream Deck Editor” vs “Stream Deck Software”. If you open/close the editor (i.e., the window), nothing happens besides the window opening and closing. When you restart the Stream Deck software, “everything” happens.

Init events are executed once, when the script is activated. This is:

  • When the Stream Deck software starts, and the plugin is started (i.e., when the plugin is started, not when a button is loaded). Unless you manually perform one of the actions below, this is the only time they are executed.
  • When you load a new script as a background script.
  • When you check the checkbox to activate a background script.
  • When you press the Run Init button.

Done with the new version.
Here is the log (Beginning removed due to post size limitation) :

2026-05-05 14:50:07.7363     12,40ms DEBUG     5  GenericMidi      Constructor start             [8f393df5fd0c4efc9a672c7c32bc7991 Row:1, Column:0, Device:Stream Deck +]
2026-05-05 14:50:07.7391      2,78ms DEBUG     5  Throttle         ThrottleMode                  [ThrottleMode set to Unlimited]
2026-05-05 14:50:07.7391      0,06ms DEBUG     5  GlobalSettings   Initialize                    [start]
2026-05-05 14:50:07.7392      0,10ms DEBUG     5  GlobalSettings   FolderPath                    [PluginPath:'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin']
2026-05-05 14:50:07.7413      2,10ms DEBUG     5  GlobalSettings   FolderPath                    [DocumentsPath:'C:\Users\LPA\Documents']
2026-05-05 14:50:07.7415      0,16ms DEBUG     5  GlobalSettings   FolderPath                    [TrevligaSpelPath:'C:\Users\LPA\Documents\Trevliga Spel']
2026-05-05 14:50:07.7417      0,19ms DEBUG     5  GlobalSettings   FolderPath                    [MusicPath:'C:\Users\LPA\Music']
2026-05-05 14:50:07.7420      0,38ms DEBUG     5  Test             TestReplacePaths              [Testing file path replacements]
2026-05-05 14:50:07.7483      6,21ms DEBUG     5  Test             TestReplacePaths              ['C\:Users\SomeUser\Documents\Somefile.xml' => 'C:\Users\LPA\Documents\Somefile.xml']
2026-05-05 14:50:07.7488      0,50ms DEBUG     5  Test             TestReplacePaths              ['C\:Users\SomeUser\Documents\Trevliga Spel\Somefile.xml' => 'C:\Users\LPA\Documents\Trevliga Spel\Somefile.xml']
2026-05-05 14:50:07.7489      0,09ms DEBUG     5  Test             TestReplacePaths              ['C:\NotTranslatedPath\Somefile.xml' unchanged]
2026-05-05 14:50:07.7491      0,22ms DEBUG     5  Test             TestReplacePaths              ['~/Documents/Somefile.xml' => 'C:\Users\LPA\Documents\Somefile.xml']
2026-05-05 14:50:07.7491      0,07ms DEBUG     5  Test             TestReplacePaths              ['~/Documents/Trevliga Spel/Somefile.xml' => 'C:\Users\LPA\Documents\Trevliga Spel\Somefile.xml']
2026-05-05 14:50:07.7492      0,06ms DEBUG     5  Test             TestReplacePaths              ['/Users/SomeUser/Documents/Somefile.xml' => 'C:\Users\LPA\Documents\Somefile.xml']
2026-05-05 14:50:07.7493      0,05ms DEBUG     5  Test             TestReplacePaths              ['/Users/SomeUser/Documents/Trevliga Spel/Somefile.xml' => 'C:\Users\LPA\Documents\Trevliga Spel\Somefile.xml']
2026-05-05 14:50:07.7493      0,09ms DEBUG     5  Test             TestReplacePaths              ['/NotTranslatedPath/Somefile.xml' => '\NotTranslatedPath\Somefile.xml']
2026-05-05 14:50:07.7496      0,25ms DEBUG     5  Test             TestReplacePaths              ['%documents%\Somefile.xml' => 'C:\Users\LPA\Documents\Somefile.xml']
2026-05-05 14:50:07.7497      0,10ms DEBUG     5  Test             TestReplacePaths              ['%documents%Somefile.xml' => 'C:\Users\LPA\Documents\Somefile.xml']
2026-05-05 14:50:07.7498      0,06ms DEBUG     5  Test             TestReplacePaths              ['%trevligaspel%\Somefile.xml' => 'C:\Users\LPA\Documents\Trevliga Spel\Somefile.xml']
2026-05-05 14:50:07.7498      0,02ms DEBUG     5  Test             TestReplacePaths              ['%trevligaspel%Somefile.xml' => 'C:\Users\LPA\Documents\Trevliga Spel\Somefile.xml']
2026-05-05 14:50:07.7498      0,04ms DEBUG     5  Test             TestReplacePaths              ['%plugin%\Somefile.xml' => 'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Somefile.xml']
2026-05-05 14:50:07.7498      0,03ms DEBUG     5  Test             TestReplacePaths              ['%plugin%Somefile.xml' => 'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Somefile.xml']
2026-05-05 14:50:07.7499      0,03ms DEBUG     5  Test             TestReplacePaths              ['%appdata%\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Extras\Icons\Generic.png' => 'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Extras\Icons\Generic.png']
2026-05-05 14:50:07.7499      0,00ms DEBUG     5  Test             TestReplacePaths              [Testing file path replacements finished]
2026-05-05 14:50:07.7546      4,70ms DEBUG     5  Throttle         ThrottleMode                  [ThrottleMode set to Unlimited]
2026-05-05 14:50:07.7584      3,85ms DEBUG     5  GlobalSettings   DecipherJson                  [Global settings item count=70]
2026-05-05 14:50:07.7612      2,75ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings newsDisplayedForVersion(newsDisplayedForVersion): '' => '4.2.0.133']
2026-05-05 14:50:07.7613      0,16ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings VersionNumberAcknowledged(VersionNumberAcknowledged): '' => '3.12.1']
2026-05-05 14:50:07.7616      0,26ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedMackieLayout(selectedMackieLayout): '' => 'Generic.xml']
2026-05-05 14:50:07.7650      3,42ms DEBUG     5  TSFile           Initialize                    ['C:\Users\LPA\Documents\Trevliga Spel\StreamDeckMidiUserSettings.xml' not found]
2026-05-05 14:50:07.7653      0,29ms DEBUG     5  UserSettings     CreateDocWatcher              [C:\Users\LPA\Documents]
2026-05-05 14:50:07.7654      0,05ms DEBUG     7  TSFile           CreateFileWatcher             [File watcher created for 'C:\Users\LPA\Documents\Trevliga Spel\StreamDeckMidiUserSettings.xml']
2026-05-05 14:50:07.7654      0,03ms DEBUG     5  UserSettings     CreateDocWatcher              [File watcher created for 'C:\Users\LPA\Documents']
2026-05-05 14:50:07.7659      0,48ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(1), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(False)]
2026-05-05 14:50:07.7679      2,00ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(2), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7679      0,03ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(3), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7679      0,01ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(4), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7679      0,00ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(5), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7679      0,00ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(6), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7679      0,00ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(7), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7679      0,00ms DEBUG     5  MCUDevCtrl       AttachToMCUPorts              [New device nr(8), midiIn(No MIDI Input), midiOut(No MIDI Output), isExtender(True)]
2026-05-05 14:50:07.7686      0,73ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedScriptMidiOutPort(selectedScriptMidiOutPort): 'StreamDeck2Daw' => 'GlobalPort_1']
2026-05-05 14:50:07.7689      0,25ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedScriptMidiInPort(selectedScriptMidiInPort): 'Daw2StreamDeck' => 'GlobalPort_2']
2026-05-05 14:50:07.7691      0,21ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialDisplayType(selectedDialDisplayType): '' => 'horizontal']
2026-05-05 14:50:07.7693      0,16ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialFaderType(selectedDialFaderType): '' => 'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Images\FaderSets\Dials\Blue\Fader.xml']
2026-05-05 14:50:07.7694      0,10ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialVpotType(selectedDialVpotType): '' => 'C:\Users\LPA\Documents\Trevliga Spel\Designs\VPot\Black (Custom).xml']
2026-05-05 14:50:07.7698      0,43ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialFrame(selectedDialFrame): '' => 'AT']
2026-05-05 14:50:07.7699      0,09ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialMCUCommandType(selectedDialMCUCommandType): '' => 'Ch.1Pot']
2026-05-05 14:50:07.7700      0,08ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialMCUFaderType(selectedDialMCUFaderType): '' => 'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Images\FaderSets\Dials\Gradient\Fader.xml']
2026-05-05 14:50:07.7702      0,22ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings selectedDialMCUVpotType(selectedDialMCUVpotType): '' => 'C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\VPot\Black\Black.xml']
2026-05-05 14:50:07.7717      1,46ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings keepSingleSectionOpen(keepSingleSectionOpen): 'True' => 'False']
2026-05-05 14:50:07.7741      2,46ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings showOnlyUsedPorts(showOnlyUsedPorts): 'False' => 'True']
2026-05-05 14:50:07.7744      0,28ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings showOnlyGlobalPorts(showOnlyGlobalPorts): 'False' => 'True']
2026-05-05 14:50:07.7746      0,21ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings keepSingleSectionOpenScript(keepSingleSectionOpenScript): 'True' => 'False']
2026-05-05 14:50:07.7747      0,13ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings LogID(LogID): '' => '565338e9-0d2d-4e9b-800a-c05f1fd103ee']
2026-05-05 14:50:07.7749      0,12ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings GS_SelectedTab(GS_SelectedTab): 'tab4' => 'tab1']
2026-05-05 14:50:07.7752      0,36ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings vW_Local(vW_Local): 'True' => 'False']
2026-05-05 14:50:07.7758      0,58ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings vW_NonrefGlobal(vW_NonrefGlobal): 'False' => 'True']
2026-05-05 14:50:07.7782      2,37ms DEBUG     5  GlobalSettings   DecipherJson                  [GlobalSettings Keywords(Keywords): '' => '']
2026-05-05 14:50:07.7798      1,68ms DEBUG     5  Throttle         ThrottleMode                  [ThrottleMode set to Unlimited]
2026-05-05 14:50:07.7813      1,42ms DEBUG     5  MidiController   EnsureMidiTransport           [changing transport, Unknown => WinRT]
2026-05-05 14:50:07.7816      0,31ms DEBUG     5  MidiController   Stop                          [Stopping ConnectionThread]
2026-05-05 14:50:07.7816      0,02ms DEBUG     5  MidiController   Stop                          [Done stopped=True]
2026-05-05 14:50:07.7975     15,91ms DEBUG     5  MidiFactory      Create                        [Windows transport preflight. BaseDir='C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\PC\', Is64BitProcess=True]
2026-05-05 14:50:07.7979      0,44ms DEBUG     5  MidiFactory      Resolver                      [Default ALC resolver hooked]
2026-05-05 14:50:07.8018      3,90ms DEBUG     5  MidiFactory      Process                       [Process not elevated]
2026-05-05 14:50:07.8037      1,89ms DEBUG     5  MidiFactory      Create                        [Loading 'WinRT.Transport.dll' via custom ALC.]
2026-05-05 14:50:07.8040      0,28ms DEBUG     5  MidiFactory      Create                        [Loaded transport assembly: WinRT.Transport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]
2026-05-05 14:50:07.8064      2,37ms DEBUG     5  MidiFactory      Create                        [Creating instance: 'WinRT.Transport.WinRTTransport'.]
2026-05-05 14:50:07.8104      4,05ms DEBUG     5  MidiFactory      Create                        [Probe: GetInputPorts()]
2026-05-05 14:50:07.9174    107,01ms DEBUG     5  MidiFactory      Create                        [Probe OK]
2026-05-05 14:50:07.9178      0,37ms DEBUG     5  MidiFactory      EnsureMidiTransport           [requested=WinRT, actual=WinRT]
2026-05-05 14:50:08.0446    126,84ms DEBUG     5  MidiController   EnsureMidiTransport           [transportInstance=WinRT.Transport.WinRTTransport]
2026-05-05 14:50:08.0449      0,29ms DEBUG     5  MidiController   EnsureMidiTransport           [inputPorts='BMT 1','BMT 2','BMT 3','BMT 4','BMT 5','BMT 6','RME ARC','UCX Midi Port 1','UCX Midi Port 2']
2026-05-05 14:50:08.0450      0,07ms DEBUG     5  MidiController   EnsureMidiTransport           [outputPorts='BMT 1','BMT 2','BMT 3','BMT 4','BMT 5','BMT 6','RME ARC','Synthé. de table de sons Microsoft GS','UCX Midi Port 1','UCX Midi Port 2']
2026-05-05 14:50:08.0460      0,99ms DEBUG     5  MidiController   HookTransportEvents           [Done, transport WinRT.Transport.WinRTTransport]
2026-05-05 14:50:08.0463      0,35ms DEBUG     5  MidiController   Start                         [Starting ConnectionThread]
2026-05-05 14:50:08.0466      0,28ms DEBUG     5  GlobalSettings   ReadGlobalSettingsFile        [file read]
2026-05-05 14:50:08.0473      0,72ms DEBUG     5  MidiStateCtrl    SetSaveState                  [Save state set: SaveState=(False), SavePeriod=(60), maxAge=(24), filePath=(C:\Users\LPA\Documents\Trevliga Spel\StreamDeckMidiState.json)]
2026-05-05 14:50:08.0477      0,40ms DEBUG    16  MidiController   HandleConnection              [started]
2026-05-05 14:50:08.0487      0,99ms DEBUG     7  SDConnection     SendAsync                     [Sending: {"event":"getGlobalSettings","context":"2f82f92cd71be55c0f9becd7c5a4937b"}]
2026-05-05 14:50:08.0494      0,71ms DEBUG     5  GlobalSettings   Initialize                    [
(InOut:GlobalPort_2/GlobalPort_1/0)
(NOInOut:Daw2StreamDeck/StreamDeck2Daw/0/C4)
(PCInOut:Daw2StreamDeck/StreamDeck2Daw/0)
(MSCInOut:StreamDeck2Daw/0)
(SXInOut:StreamDeck2Daw)
(SCInOut:GlobalPort_2/GlobalPort_1)
(MCUInOut:No MIDI Input/No MIDI Output/1/Generic.xml)
(MCUs:(1:No MIDI Input/No MIDI Output/False/True),(2:No MIDI Input/No MIDI Output/True/True),(3:No MIDI Input/No MIDI Output/True/True),(4:No MIDI Input/No MIDI Output/True/True),(5:No MIDI Input/No MIDI Output/True/True),(6:No MIDI Input/No MIDI Output/True/True),(7:No MIDI Input/No MIDI Output/True/True),(8:No MIDI Input/No MIDI Output/True/True))
(Layout:Generic.xml)
(VPOTTime:700)(Art:)
(news:4.2.0.133)
(dial:horizontal/Fader.xml/Black (Custom).xml/AT/True/100
(BGScripts:(C:/Users/LPA/Documents/Trevliga Spel/JS/B_Common.js/GlobalPort_2/GlobalPort_1/True),(C:/Users/LPA/Documents/Trevliga Spel/JS/B_CC.js/GlobalPort_2/GlobalPort_1/True),(C:/Users/LPA/Documents/Trevliga Spel/JS/B_Sysex.js/GlobalPort_2/GlobalPort_1/True),(/No MIDI Input/No MIDI Output/False),(/No MIDI Input/No MIDI Output/False),(/No MIDI Input/No MIDI Output/False),(/No MIDI Input/No MIDI Output/False),(/No MIDI Input/No MIDI Output/False))
(InternalPorts:2)
(keepSSOpen:False)
(GlobalPorts:(GP1: BMT 4),(GP2: BMT 5),(GP3: Not used),(GP4: Not used),(GP5: Not used),(GP6: Not used),(GP7: Not used),(GP8: Not used),(GP9: Not used),(GP10: Not used),(GP11: Not used),(GP12: Not used),(GP13: Not used),(GP14: Not used),(GP15: Not used),(GP16: Not used),(GP17: Not used),(GP18: Not used),(GP19: Not used),(GP20: Not used),(GP21: Not used),(GP22: Not used),(GP23: Not used),(GP24: Not used),(GP25: Not used),(GP26: Not used),(GP27: Not used),(GP28: Not used),(GP29: Not used),(GP30: Not used),(False),(True)
(DialFrameColor:)
(DialMCUCommandType:Ch.1Pot)
(DialMCUFaderType:C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\Images\FaderSets\Dials\Gradient\Fader.xml)
(DialMCUVpotType:C:\Users\LPA\AppData\Roaming\Elgato\StreamDeck\Plugins\se.trevligaspel.midi.sdPlugin\VPot\Black\Black.xml)
(showOnlyUsedPorts:True)
(keepSingleSectionOpenScript:False)
(LogID:565338e9-0d2d-4e9b-800a-c05f1fd103ee)
(VariableWindow:False/True/True/True/True/False/False)
(VariableWindow_GS:True/True/False/True/True/False/False/True/False)
(Keywords:)
(MidiDriver:WinRT)
]
2026-05-05 14:50:08.0495      0,03ms DEBUG     5  GlobalSettings   Initialize                    [end]
2026-05-05 14:50:08.0499      0,48ms DEBUG     5  OptionsCtrl      Initialize
2026-05-05 14:50:08.0509      0,98ms DEBUG     5  OptionsCtrl      HandleArticulationFile        ['C:\Users\LPA\Documents\Trevliga Spel\ArticulationOptions.xml' not found]
2026-05-05 14:50:08.0511      0,17ms DEBUG     5  OptionsCtrl      CreateTSFolderWatcher         [C:\Users\LPA\Documents\Trevliga Spel]
2026-05-05 14:50:08.0513      0,21ms DEBUG     5  OptionsCtrl      CreateDocumentsFolderWatcher  [C:\Users\LPA\Documents]
2026-05-05 14:50:08.0522      0,90ms DEBUG     5  dBFileCtrl       CreateTSFolderWatcher         [C:\Users\LPA\Documents]
2026-05-05 14:50:08.0689     16,70ms DEBUG     5  dBFileCtrl       CreateDocumentsFolderWatcher  [C:\Users\LPA\Documents]
2026-05-05 14:50:08.0691      0,24ms DEBUG     5  dBFileCtrl       Init                          [Elapsed:17,0099 ms]
2026-05-05 14:50:08.0703      1,14ms DEBUG     5  BgScriptCtrl     Initialize                    []
2026-05-05 14:50:08.0708      0,48ms DEBUG     5  BgScriptCtrl     GlblChanged                   []
2026-05-05 14:50:08.0723      1,50ms DEBUG     5  JavaScript       Instance                      [BackgroundScript1 midiIn=(BMT 5), midiOut=(BMT 4), loadScriptFromFile=(True), scriptPath=(C:/Users/LPA/Documents/Trevliga Spel/JS/B_Common.js), isActive=(True)]
2026-05-05 14:50:08.1653     93,03ms DEBUG    16  MidiController   ListMidiPorts                 [Input ports: 'BMT 1','BMT 2','BMT 3','BMT 4','BMT 5','BMT 6','RME ARC','UCX Midi Port 1','UCX Midi Port 2']
2026-05-05 14:50:08.1654      0,08ms DEBUG    16  MidiController   ListMidiPorts                 [Output ports: 'BMT 1','BMT 2','BMT 3','BMT 4','BMT 5','BMT 6','RME ARC','Synthé. de table de sons Microsoft GS','UCX Midi Port 1','UCX Midi Port 2']
2026-05-05 14:50:08.1655      0,14ms DEBUG    16  MidiController   HandleConnection              [OutPort(BMT 1) existence changed -> True]
2026-05-05 14:50:08.1655      0,01ms DEBUG    16  MidiController   HandleConnection              [OutPort(BMT 2) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(BMT 3) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(BMT 4) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(BMT 5) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(BMT 6) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(RME ARC) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(Synthé. de table de sons Microsoft GS) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [OutPort(UCX Midi Port 1) existence changed -> True]
2026-05-05 14:50:08.1655      0,01ms DEBUG    16  MidiController   HandleConnection              [OutPort(UCX Midi Port 2) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 1) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 2) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 3) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 4) existence changed -> True]
2026-05-05 14:50:08.1655      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 5) existence changed -> True]
2026-05-05 14:50:08.1656      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 6) existence changed -> True]
2026-05-05 14:50:08.1656      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(RME ARC) existence changed -> True]
2026-05-05 14:50:08.1656      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(UCX Midi Port 1) existence changed -> True]
2026-05-05 14:50:08.1656      0,00ms DEBUG    16  MidiController   HandleConnection              [InPort(UCX Midi Port 2) existence changed -> True]
2026-05-05 14:50:08.1698      4,19ms DEBUG     5  TimerCtrl        Constructor                   [TimerController started]
2026-05-05 14:50:08.1707      0,97ms DEBUG     5  JavaScript       ConnectMidi                   [BackgroundScript1 connecting (BMT 5/BMT 4)]
2026-05-05 14:50:08.1710      0,31ms DEBUG     5  Connection       AttachToMidiPorts             [BackgroundScript1 Attaching to ports 'BMT 5'/'BMT 4']
2026-05-05 14:50:08.1711      0,09ms DEBUG     5  MidiController   AttachToMidiInput             [BackgroundScript1 attached to InPort(BMT 5)]
2026-05-05 14:50:08.1712      0,07ms DEBUG     5  MidiController   AttachToMidiOutput            [BackgroundScript1 attached to OutPort(BMT 4)]
2026-05-05 14:50:08.1718      0,61ms DEBUG     5  Connection       AttachToMidiEvents            [BackgroundScript1 Attaching to events]
2026-05-05 14:50:08.1732      1,37ms DEBUG     5  Connection       Instance                      [BackgroundScript1 Connection created]
2026-05-05 14:50:08.1742      1,04ms DEBUG     5  JavaScript       ConnectMidi                   [BackgroundScript1 connected BMT 5/BMT 4]
2026-05-05 14:50:08.1747      0,50ms DEBUG     5  JavaScript       LoadScriptFile                [BackgroundScript1 Attaching to file 'C:/Users/LPA/Documents/Trevliga Spel/JS/B_Common.js']
2026-05-05 14:50:08.1748      0,08ms DEBUG     5  TSFile           Initialize                    ['C:/Users/LPA/Documents/Trevliga Spel/JS/B_Common.js' found]
2026-05-05 14:50:08.1749      0,07ms DEBUG    13  TSFile           CreateFileWatcher             [File watcher created for 'C:/Users/LPA/Documents/Trevliga Spel/JS/B_Common.js']
2026-05-05 14:50:08.2025     27,65ms DEBUG    20  VariableCtrl     SetVariable                   [global:g_dp set to %trevligaspel%/Designs/]
2026-05-05 14:50:08.2031      0,61ms DEBUG    20  JavaScript       OnVariableChanged             [SKIP no-handler ctx=(BackgroundScript1) var=(g_dp)]
2026-05-05 14:50:08.2033      0,11ms DEBUG    20  VariableCtrl     SetVariable                   [global:g_lp set to %trevligaspel%/Layouts/]
2026-05-05 14:50:08.2033      0,01ms DEBUG    20  JavaScript       OnVariableChanged             [SKIP no-handler ctx=(BackgroundScript1) var=(g_lp)]
2026-05-05 14:50:08.2033      0,01ms DEBUG    20  VariableCtrl     SetVariable                   [global:g_pp set to %trevligaspel%/Images/]
2026-05-05 14:50:08.2033      0,00ms DEBUG    20  JavaScript       OnVariableChanged             [SKIP no-handler ctx=(BackgroundScript1) var=(g_pp)]
2026-05-05 14:50:08.2081      4,86ms DEBUG    20  VariableCtrl     SetVariable                   [global:styles set to System.Dynamic.ExpandoObject]
2026-05-05 14:50:08.2082      0,03ms DEBUG    20  JavaScript       OnVariableChanged             [SKIP no-handler ctx=(BackgroundScript1) var=(styles)]
2026-05-05 14:50:08.2082      0,08ms DEBUG    20  VariableCtrl     SetVariable                   [global:g_autofold set to 0]
2026-05-05 14:50:08.2082      0,01ms DEBUG    20  JavaScript       OnVariableChanged             [SKIP no-handler ctx=(BackgroundScript1) var=(g_autofold)]
2026-05-05 14:50:08.2083      0,05ms DEBUG    20  VariableCtrl     SetVariable                   [global:g_showclip set to False]
2026-05-05 14:50:08.2083      0,01ms DEBUG    20  JavaScript       OnVariableChanged             [SKIP no-handler ctx=(BackgroundScript1) var=(g_showClip)]
2026-05-05 14:50:08.2208     12,48ms DEBUG    11  VersionCtrl      ReadSiteVersion               [Found version (3.12)]
2026-05-05 14:50:08.2209      0,16ms DEBUG    11  VersionCtrl      ReadSiteVersion               [Found version (3.12), message(Version 3.12 is now available on Marketplace.)]
2026-05-05 14:50:08.2607     39,74ms DEBUG    20  MidiController   Send_ControlChange            [BackgroundScript1 message successfully sent: ControlChangeMessage, MidiIn:BMT 5, MidiOut:BMT 4, Channel:10, Control,:0, Value:127]
2026-05-05 14:50:08.2621      1,46ms DEBUG    20  MidiStateCtrl    SaveMidiState                 [BackgroundScript1 Saving state for ControlChangeMessage, MidiIn:BMT 5, MidiOut:BMT 4, Channel:10, Control,:0, Value:127, time=05/05/2026 14:50:08]
2026-05-05 14:50:08.2803     18,20ms DEBUG     5  JavaScript       Instance                      [BackgroundScript2 midiIn=(BMT 5), midiOut=(BMT 4), loadScriptFromFile=(True), scriptPath=(C:/Users/LPA/Documents/Trevliga Spel/JS/B_CC.js), isActive=(True)]
2026-05-05 14:50:08.2807      0,31ms DEBUG     5  JavaScript       ConnectMidi                   [BackgroundScript2 connecting (BMT 5/BMT 4)]
2026-05-05 14:50:08.2807      0,01ms DEBUG     5  Connection       AttachToMidiPorts             [BackgroundScript2 Attaching to ports 'BMT 5'/'BMT 4']
2026-05-05 14:50:08.2807      0,04ms DEBUG     5  MidiController   AttachToMidiInput             [BackgroundScript2 attached to InPort(BMT 5)]
2026-05-05 14:50:08.2807      0,01ms DEBUG     5  MidiController   AttachToMidiOutput            [BackgroundScript2 attached to OutPort(BMT 4)]
2026-05-05 14:50:08.2807      0,00ms DEBUG     5  Connection       AttachToMidiEvents            [BackgroundScript2 Attaching to events]
2026-05-05 14:50:08.2815      0,79ms DEBUG     5  Connection       Instance                      [BackgroundScript2 Connection created]
2026-05-05 14:50:08.2815      0,01ms DEBUG     5  JavaScript       ConnectMidi                   [BackgroundScript2 connected BMT 5/BMT 4]
2026-05-05 14:50:08.2815      0,00ms DEBUG     5  JavaScript       LoadScriptFile                [BackgroundScript2 Attaching to file 'C:/Users/LPA/Documents/Trevliga Spel/JS/B_CC.js']
2026-05-05 14:50:08.2816      0,05ms DEBUG     5  TSFile           Initialize                    ['C:/Users/LPA/Documents/Trevliga Spel/JS/B_CC.js' found]
2026-05-05 14:50:08.2817      0,08ms DEBUG    11  TSFile           CreateFileWatcher             [File watcher created for 'C:/Users/LPA/Documents/Trevliga Spel/JS/B_CC.js']
2026-05-05 14:50:08.3002     18,53ms DEBUG     5  JavaScript       Instance                      [BackgroundScript3 midiIn=(BMT 5), midiOut=(BMT 4), loadScriptFromFile=(True), scriptPath=(C:/Users/LPA/Documents/Trevliga Spel/JS/B_Sysex.js), isActive=(True)]
2026-05-05 14:50:08.3003      0,14ms DEBUG    16  MidiController   HandleConnection              [InPort(BMT 5) opened]
2026-05-05 14:50:08.3003      0,02ms DEBUG     5  JavaScript       ConnectMidi                   [BackgroundScript3 connecting (BMT 5/BMT 4)]
2026-05-05 14:50:08.3004      0,01ms DEBUG     5  Connection       AttachToMidiPorts             [BackgroundScript3 Attaching to ports 'BMT 5'/'BMT 4']
2026-05-05 14:50:08.3004      0,01ms DEBUG     5  MidiController   AttachToMidiInput             [BackgroundScript3 attached to InPort(BMT 5)]
2026-05-05 14:50:08.3004      0,00ms DEBUG     5  MidiController   AttachToMidiOutput            [BackgroundScript3 attached to OutPort(BMT 4)]
2026-05-05 14:50:08.3004      0,00ms DEBUG     5  Connection       AttachToMidiEvents            [BackgroundScript3 Attaching to events]
2026-05-05 14:50:08.3004      0,01ms DEBUG     5  Connection       Instance                      [BackgroundScript3 Connection created]
2026-05-05 14:50:08.3004      0,01ms DEBUG     5  JavaScript       ConnectMidi                   [BackgroundScript3 connected BMT 5/BMT 4]
2026-05-05 14:50:08.3004      0,00ms DEBUG     5  JavaScript       LoadScriptFile                [BackgroundScript3 Attaching to file 'C:/Users/LPA/Documents/Trevliga Spel/JS/B_Sysex.js']
2026-05-05 14:50:08.3004      0,05ms DEBUG     5  TSFile           Initialize                    ['C:/Users/LPA/Documents/Trevliga Spel/JS/B_Sysex.js' found]
2026-05-05 14:50:08.3005      0,09ms DEBUG    17  TSFile           CreateFileWatcher             [File watcher created for 'C:/Users/LPA/Documents/Trevliga Spel/JS/B_Sysex.js']
2026-05-05 14:50:08.3008      0,27ms DEBUG    16  Connection       PortexistenceChanged          [BackgroundScript1 Input port 'BMT 5' existence changed to True]
2026-05-05 14:50:08.3010      0,22ms DEBUG    16  Connection       PortexistenceChanged          [BackgroundScript2 Input port 'BMT 5' existence changed to True]
2026-05-05 14:50:08.3073      6,30ms DEBUG    24  VariableCtrl     SetVariable                   [global:g_pqb0 set to 0]
2026-05-05 14:50:08.3077      0,37ms DEBUG    24  JavaScript       OnVariableChanged             [CHAIN ctx=(BackgroundScript1) id=(c10682c6c414417593468b201b4ee8d5) chainCount=(1)]
2026-05-05 14:50:08.3112      3,56ms DEBUG    20  JavaScript       InvokeAsync                   [BackgroundScript1 Calling 'OnGlobalVariableChanged' with args=(g_pqb0, 0)]
2026-05-05 14:50:08.3521     40,86ms DEBUG     7  JavaScript       RunInitCommands               [BackgroundScript2 start]
2026-05-05 14:50:08.3522      0,10ms DEBUG    22  JavaScript       InvokeAsync                   [BackgroundScript2 Calling 'OnInit' with args=()]
2026-05-05 14:50:08.3553      3,10ms DEBUG    22  VariableCtrl     SetVariable                   [global:g_dev_on set to 0]
2026-05-05 14:50:08.3554      0,10ms DEBUG    22  JavaScript       OnVariableChanged             [CHAIN ctx=(BackgroundScript1) id=(cffa7af1caf94d1684b743c5a266382e) chainCount=(1)]

I write again the steps 5 and 6:

  1. I quit the Stream Deck editor: it doesn’t mean that I close a window, it means that I quit the app (or I quit the software)
  2. I open again Stream Deck editor: it means that I launch the Stream Deck app that was quitted in the previous step (or I launch the software)

What does background script 1 look like?

Here it is :



/// <reference path="C:/Users/LPA/AppData/Roaming/Elgato/StreamDeck/Plugins/se.trevligaspel.midi.sdPlugin/ScriptJint/streamdeck-midi.d.ts" />
// -----------------------------
// Hooks (Called BEFORE updates)
// -----------------------------
const NEW_DEVICE_MS = 150;
const ND_TIMER ="t_newDevice";
const VAR_MS = 25;
const VAR_TIMER ="t_varUpdate";
const PNAME_VAR = "g_pname";
const DEV_TYPE = {1: "Instrument", 2: "Audio Effect", 4: "Midi Effect"};
gvar.g_pqb0 = 0;
//
var l_preceived = false; 

// New Device : Reinit Parameters Names after a delay if no parameters received
// Note : For showchain and toggle fold, device counters are resent without updating the parameters
function onNewDevice(map) {
    l_preceived = false; 
    timer.restart(ND_TIMER, NEW_DEVICE_MS);    
    if (map.g_nbp == 0) { gvar.g_pname = []; } // Reset parameters names if no parameters   
    // Reset array staging buffers on new device
    tempArrays[PNAME_VAR] = [];
    
    // Variations
    timer.restart(VAR_TIMER, VAR_MS);
}

// Parameters & variation 
function OnTimerElapsed(tname, isGlobal, time) {
    if (tname == ND_TIMER) { // Kill timer, update parameters names and set quarter bank even when not all parameters are received
        timer.reset(ND_TIMER);
        if (!l_preceived) gvar.set(PNAME_VAR, tempArrays[PNAME_VAR].slice()); // Flush incomplete array  
        setQuarterBank ();
        gvar.g_pupdt = 1; gvar.g_pupdt = 0; // Trigger refresh
        return;
    }
    if (tname == VAR_TIMER) {  // No variation received (timer is killed otherwise)
        timer.reset(VAR_TIMER);                 
        gvar.g_vnum0 = 0;      
        gvar.g_max_var = 0;
        setVarText(0, 0);
        gvar.g_vupdt = 1; gvar.g_vupdt = 0; // Trigger refresh
    }
}

function onSetParameters(array) {
    // Bloc intermediate updates until # of parameters is reached
    if (array.length < gvar.g_nbp) {return false;} 
    else { // Last parameters received
        l_preceived = true;
    }
}

function setQuarterBank () {
    // Set parameters bank
    gvar.g_nhb = Math.floor((gvar.g_nbp + 3) / 4); // Number of half banks
    gvar.g_pqb0 = gvar.g_nbp == 0 ? 0 : 1; // // Current global half bank

    const chainText = (gvar.g_dev_rack == 0 && gvar.g_dev_parent == 0)
        ? DEV_TYPE[gvar.g_dev_type] || "Unknown Device Type"
        : "Ch. " + gvar.g_chnum0 + "/" + gvar.g_max_ch;
    gvar.g_chaintext = chainText;   
}

function onVarReceived(map) { // Called from the hook
    // Update immediately, , as variations can be received alone
    gvar.g_vnum0 = map.g_vnum0;
    gvar.g_max_var = map.g_max_var;
    setVarText(map.g_vnum0, map.g_max_var);
    timer.reset(VAR_TIMER); // Kill Timer
    gvar.g_vupdt = 1; gvar.g_vupdt = 0; // Trigger refresh
    // No need to process    
    return false;
}

function setVarText(varNum, maxVar, ) {
    gvar.g_vartext =  (maxVar == 0
            ? "No variation"
            : "Var. " + varNum + " / " + maxVar);
}


function onSetSessionBoxTrackName(array) {
    // Bloc intermediate updates until 4th track
    if (array.length < 4) {return false;}
}

function onClipMarkersReceived (map) {
    // 3 values are received, each one split across 3 bytes for accomodating large numbers with Sysex byte limit (127)
    const bytes = [map.b0, map.b1, map.b2, map.b3, map.b4, map.b5, map.b6, map.b7, map.b8];
    const start_time = fromMidiBytes(bytes.slice(0, 3));
    const end_time   = fromMidiBytes(bytes.slice(3, 6));
    const length     = fromMidiBytes(bytes.slice(6, 9));
    //console.warn ("[bSYSEX] Processing Clip Markers: Start=" + start_time + ", end=" + end_time+ ", length=" + length);
    gvar.set("g_clstart", start_time);
    gvar.set("g_clend", end_time);
    gvar.set("g_cllen", length);
    return false; // Block processing (gvar updating)
}

function fromMidiBytes(bytes) {
  return Math.round(((bytes[0] << 14) | (bytes[1] << 7) | bytes[2]) / 1000);
}

// Example Hooks
/*
function sysExHookString(value) {// value = decoded string}
function sysExHookChunked(value) {// value = final string}
function sysExHookArray(array) {// array = array of values}
function sysExHookVector(map) {// map : {var1: 1, var2: 2, var3: 3}}
*/
// ===================================================================================
// SYSEX TYPES - SUMMARY
// ===================================================================================
// Each entry consists of prefix:p, and index, i and a configuration map (dictionnary).
// Each entry indicates how to process received Sysex messages with the byte layouts:
//   noIndex : F0 p  [slot] [control] payload F7
//   indexed : F0 p  i  [slot] [control] payload F7
//
// Configuration maps are made of :
// 1/ type: A given type among the following :
// - String : Raw ascii conversion
// - Chunked : A string that arrive in several parts (chunks) with a 1st control byte first
// - Array : An array of string that arrive in slots 1st and chunks with a control byte 2nd
// - Vector : One or several numerical values directly fed from the sysex byte
//
// 2/ The global variable name: varName or (for vectors) a variable array (VarNames) in which to store the received content (payload).
//    For arrays, varName will be fed as an array of received values.
//     
// 3/ init: The initial value of the variable or (for vectors) and array of initial values
//
// 4/ hook: The name of a function to be called before variables are updated, for example to perform extra calulation of transformation.
//    Variables are passed by reference to the hook, enabling transformation before update.
//    A hook can return a "false" value, in which case the update of variables will be bypassed. 
//
// All entries support both noIndex [p, {configuration}] and indexed [p, i, {configuration}] entries.
// A given prefix p must be used exclusively as either noIndex or indexed, never both
// For noIndex entries, the payload starts 1 byte after the prefix (offset = 1 base).
// For indexed entries, the payload starts 2 bytes after the prefix (offset = 2 base).
// The slot (for arrays) and control byte (for chunks) add +1 each to the base offset when present.
// The chunk control byte is made of two parts : 1st part; chunk nubmer, 2nd part: total number of chunks
//
// -------------------------------------------------------------------------------------------------
// type     | ascii | noIndex layout               | offset | indexed layout               | offset
// -------------------------------------------------------------------------------------------------
// string   |  yes  | p, text                      |   1    | p, i, text                   |   2
// chunked  |  yes  | p, control, text             |   2    | p, i, control, text          |   3
// array    |  yes  | p, slot, control, text       |   3    | p, i, slot, control, text    |   4
// vector   |  no   | p, numerical values          |   1    | p, i, numerical values       |   2
// -------------------------------------------------------------------------------------------------
// Notes:
//   - string and vector share the same offsets (no slot or control byte)
//   - chunked noIndex offset (2) differs from indexed (3) by the index byte only
//   - array is the only type carrying both slot AND control bytes, giving offset 3 (noIndex) and 4 (indexed)
//   - ascii conversion (decode()) is used for string, chunked and array
//   - vector values are raw numeric bytes, no conversion
//   - vector can have only one entry to p^rocess a single variable
// ===================================================================================
const sysExList = [
    [0,   0, { type: "string",  varName: "g_xxxx",        init: "_xxxx_" }],    // F0 00 00 (Example)

    
    [106, 0, { type: "chunked", varName: "g_tname_sel", init: "_track_" }],     // F0 6A 00

    [107, { type: "array", varName: "g_sbtname", init: ["_SB Track1_", "_SB Track2_", 
            "_SB Track3_", "_SB Track4_"], hook: onSetSessionBoxTrackName }],   // F0 6B : Session Box Track Names

    [107, 1, { type: "chunked", varName: "g_tname_sb1", init: "_mtrack1" }],    // F0 6B 01
    [107, 2, { type: "chunked", varName: "g_tname_sb2", init: "_mtrack2" }],    // F0 6B 02
    [107, 3, { type: "chunked", varName: "g_tname_sb3", init: "_mtrack3" }],    // F0 6B 03
    [107, 4, { type: "chunked", varName: "g_tname_sb4", init: "_mtrack4" }],    // F0 6B 04

    [108, 0, { type: "chunked", varName: "g_sname_sel", init: "_scene_" }],     // F0 6C 00
    [110, 0, { type: "chunked", varName: "g_dname_sel", init: "_device_" }],    // F0 6E 00
    [111, 0, { type: "chunked", varName: "g_dname_nav", init: "_deviceN_" }],   // F0 6F 00

    [112,    { type: "vector", varNames: ["b0","b1","b2","b3","b4","b5","b6","b7","b8"], 
               init: [0,0,0,0,0,0,0,0,0], hook: onClipMarkersReceived }],           // F0 70 Clip markers
    [113, 0, { type: "chunked", varName: "g_cname_sel", init: "_clip_" }],          // F0 71 00
    [122,    { type: "vector", varNames: ["g_vnum0", "g_max_var"],init: [0, 0], // F0 7A Variation Control
                                                            hook: onVarReceived}],   
    [123,    { type: "array", varName: "g_pname", 
               init: Array(16).fill("_Parameter_"), hook: onSetParameters }],       // F0 7B : Parameters Names

    
    [92,  1, { type: "vector", varNames: ["g_tra", "g_trl", "g_trs"],init: [0, 0, 0]}],     // F0 5C 01 Twister ring : Enabled, Linked, Synced
    [92,  2, { type: "vector", varNames: ["g_mra", "g_mrl", "g_mrs"],init: [0, 0, 0]}],     // F0 5C 02 MPK ring : Enabled, Linked, Synced
    [109,    { type: "vector", varNames: ["g_dev_pos", "g_dev_nbr", "g_dev_on_unused",      // F0 6D (vector) : Device + Chain (if rack)
               "g_dev_parent", "g_dev_type", "g_dev_rack", "g_chnum0", "g_max_ch", "g_nbp", "g_rnbr"], 
               init: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],   hook: onNewDevice }]   
 ];
// Lookup tables 
const sysEx = {
    noIndex: new Map(),   // p → entry
    indexed: new Map(),   // "p:i" → entry
};
compileSysEx(sysExList);
// Builder
function compileSysEx(list) {
    for (const entry of list) {
        const [p, maybeI, cfg] = entry;

        // [p, cfg]
        if (cfg === undefined) {
            sysEx.noIndex.set(p, maybeI);
            continue;
        }

        // [p, i, cfg]
        sysEx.indexed.set(`${p}:${maybeI}`, cfg);
    }
}
// ------------------------
// STATE (stateless helper)
// ------------------------
let pendingChunk = {};
const pendingArray = {};
const tempArrays = {}; // staging buffers only, never authoritative

// ------------------------
// Initialization
// -------------------------
function onInit() {
    sysExList.forEach((entry) => {
        const isNoIndex = entry.length === 2;
        const cfg = isNoIndex ? entry[1] : entry[2];
        if (!cfg) return;

        // ARRAY: always prepare buffer
        if (cfg.type === "array") {
            if (!cfg.varName) return;
            tempArrays[cfg.varName] = [];
            if (cfg.init !== undefined) {
                gvar.set(cfg.varName, cfg.init);
            }
            return;
        }

        // Early exit for everything else
        if (cfg.init === undefined) return;

        // STRING
        if (cfg.type === "string") {
            if (!cfg.varName) return;
            gvar.set(cfg.varName, cfg.init);
            return;
        }

        // CHUNKED
        if (cfg.type === "chunked") {
            if (!cfg.varName) return;
            gvar.set(cfg.varName, cfg.init);
            return;
        }

        // VECTOR
        if (cfg.type === "vector") {
            if (!Array.isArray(cfg.varNames)) return;
            cfg.varNames.forEach((varName, idx) => {
                gvar.set(varName, cfg.init[idx]);
            });
            return;
        }
    });
}

// ------------------------
// Main handler
// ------------------------

function OnSysExReceived(sysexdata) {
    const data = Array.from(sysexdata);
    if (data.length < 3) return;

    const p = data[0];
    const i = data[1];
    const entry = resolveEntry(p, i); // Returns { cfg, offset}}
    if (!entry) return;
    //console.warn ("[bSYSEX] Resolving entry p=", p, ", i=", i, ", cfg=", JSON.stringify(entry.cfg), ", offset=", entry.offset);

    /*
    const data2 = sysexdata;
    console.warn("[RAW]", data2);
    console.warn("[LENGTH]", data2.length);
    console.warn("ENTRY OFFSET USED:", entry.offset);
    console.warn("EXPECTED START BYTE:", data[entry.offset]);
    console.warn("FULL SLICE:", data.slice(entry.offset));
    */


    switch (entry.cfg.type) {

        // --------------------
        // VECTOR
        // --------------------
        case "vector": {
            const raw = data.slice(entry.offset);
            const values = raw[raw.length - 1] === 0xF7 ? raw.slice(0, -1) : raw;
            // Check expected variables number versus message
            if (values.length !== entry.cfg.varNames.length) {
                //console.warn(`[BNames.js] prefix=${p}, index=${i} expected=${entry.cfg.varNames.length} received=${values.length}`);
                return;
            }
            setVectorVars(entry.cfg.varNames, values, entry.cfg.hook);
            return;
        }
        case "chunked": {
            
            const control = data[entry.offset - 1]; // noIndex: data[1], indexed: data[2]
            const part = control >> 4, total = control & 0x0F;

            const text = decode(data, entry.offset);

            
            if (total <= 0 || part <= 0 || part > total) {
                //console.warn(`[BNames.js] prefix=${p}, index=${i} invalid chunk control byte , part=${part} total=${total}`);
            }
            // Init & accumulate
            const key = entry.cfg.varName;
            if (!pendingChunk[key]) pendingChunk[key] = "";
            if (part === 1) pendingChunk[key] = text;
            else pendingChunk[key] += text;
            // Publish
            if (part === total) {
                setChunked(key, pendingChunk[key], entry.cfg.hook);
                delete pendingChunk[key];
            }

            return;
        }

        // --------------------
        // ARRAY (chunked)
        // --------------------
        case "array": {
            const slot = data[entry.offset - 2]; // indexed: slot=data[2], noIndex: slot=data[1]
            const control = data[entry.offset - 1]; // indexed: control=data[3], noIndex: control=data[2]
            const part = control >> 4, total = control & 0x0F;

            if (total <= 0 || part <= 0 || part > total) {
                console.warn(`[BNames.js] prefix=${p}, index=${i} invalid array control byte , part=${part} total=${total}`);
            }

            const text = decode(data, entry.offset);

            if (part === 1 && total > 1) {pendingArray[slot] = text; return;}
            if (part > 1 && part < total) {pendingArray[slot] = (pendingArray[slot] || "") + text; return;}
            if (part === total) {
                setArray(entry.cfg.varName, slot, (pendingArray[slot] || "") + text, entry.cfg.hook);
                delete pendingArray[slot];
                return;
            }
            return;
        }
        // --------------------
        // STRING
        // --------------------
        case "string": {
            const text = decode(data, entry.offset);
            setString(entry.cfg.varName, text, entry.cfg.hook);
            return;
        }
    }
}

// ------------------------
// Decode
// ------------------------
function decode(data, offset) {
    let end = data.length;
    if (data[end - 1] === 0xF7) end--;

    let text = "";
    for (let i = offset; i < end; i++) {
        text += String.fromCharCode(data[i]);
    }
    return text;
}

// ------------------------
// Entry resolution
// ------------------------

function resolveEntry(p, i) {
    const indexedKey = `${p}:${i}`;

    if (sysEx.noIndex.has(p)) {
        const cfg = sysEx.noIndex.get(p);
        const offset = cfg.type === "array" ? 3 : cfg.type === "chunked" ? 2 : 1;
        return { cfg, offset };
    }

    if (sysEx.indexed.has(indexedKey)) {
        const cfg = sysEx.indexed.get(indexedKey);
        let offset;
        if (cfg.type === "array")         offset = 4; // p, i, slot, control, text
        else if (cfg.type === "chunked")  offset = 3; // p, i, control, text
        else                              offset = 2; // p, i, values
        return { cfg, offset };
    }

    return null;
}


// ------------------------
// Setters
// ------------------------

function setString(name, value, hook) {
    if (hook) {const result = hook(value); if (result === false) return;}
    //console.warn("[bSYSEX] Setting string variable: " + name + ", value=" + value);
    gvar.set(name, value);
}

function setChunked(name, value, hook) {
    // Result is undefined by default, processing will continue
    if (hook) {const result = hook(value);if (result === false) return;}
    //console.warn ("[bSYSEX] Setting chunked variable: " + name + ", value=" + value);
    gvar.set(name, value);
}

function setArray(name, index, value, hook) {
    if (!tempArrays[name]) {tempArrays[name] = [];}
    tempArrays[name].push(value);
    //console.warn ("[bSYSEX] Accumulating array variable: " + name + ", index=," + tempArrays[name].length +  ", value=" + value);
    // hook may block intermediate updates otherwise update is performed for each slot
    if (hook) {const result = hook(tempArrays[name]);if (result === false) return;}
    //console.warn ("[bSYSEX] Setting array variable: " + name + ", value=" + tempArrays[name]);
    gvar.set(name, tempArrays[name].slice());
    tempArrays[name] = [];
}

function setVectorVars(varNames, values, hook) {
    const map = {}; // Buil a map to be accessed with map.name to get the value in the hook
    for (let i = 0; i < varNames.length; i++) {map[varNames[i]] = values[i];}
    // Result is undefined by default, processing will continue
    if (hook) {const result = hook(map);if (result === false) return;}
    //console.warn ("[bSYSEX] Setting vector variable: " + varNames + ", value=" + values);
    for (let i = 0; i < varNames.length; i++) {gvar.set(varNames[i], values[i]);}
}


I’m struggling to understand why the latest version has caused these issues. I can’t recall having made any changes in the areas you report, so my current theory is that it is a timing error of some sort.

I can reproduce the issue reported by @jordikt, but haven’t found the cause yet. I’m unable to reproduce the issue reported by @thx538, but I haven’t had time to test with bg script 1 yet.

I apologize … what I posted just above is the the background script #3.
The background script #1 is this :

/// <reference path="C:/Users/LPA/AppData/Roaming/Elgato/StreamDeck/Plugins/se.trevligaspel.midi.sdPlugin/ScriptJint/streamdeck-midi.d.ts" />
// Environmental variables
gvar.g_dp = "%trevligaspel%/Designs/"  // Design Path
gvar.g_lp = "%trevligaspel%/Layouts/"  // Layout Path
gvar.g_pp = "%trevligaspel%/Images/"  // Picture Path

//Colors
const BAR_COLOR_ACTIVE   = "#B8A46E"; // Light Yellow
const BAR_COLOR_IDLE     = "#A2B0A2"; // Ligh Green
const TEXT_COLOR_ACTIVE = "#B49541"; // Yellow
const TEXT_COLOR_IDLE   = "Gray";

const TR_GRADIENT = "0:#ff0000,0.5:yellow,1:#00ff00";
const SC_GRADIENT = "0:#ff0000,0.5:red,1:#00ff00";

gvar.styles = {
    track:      { active: { color: "#8d4400", barbkg: "#af855e", font: { size: 20, weight: 600 } }, 
                    idle: { color: "#808080", barbkg: "#a9abb6", font: { size: 20, weight: 200 } } },
    scene:      { active: { color: "#4152b4", barbkg: "#707bac", font: { size: 20, weight: 600 } }, 
                    idle: { color: "#808080", barbkg: "#a9abb6", font: { size: 20, weight: 500 } } },
    device:     { active: { color: "#B46E41", barbkg: "#6eb893", font: { size: 20, weight: 600 } }, 
                    idle: { color: "#888888", barbkg: "#a9abb6", font: { size: 20, weight: 500 } } },
    chain:      { active: { color: "#296dda", barbkg: "#97befa", font: { size: 20, weight: 600 } },
                  select: { color: "#68a1fd", barbkg: "#97befa", font: { size: 20, weight: 600 } }, 
                    idle: { color: "#296dda", barbkg: "#a9abb6", font: { size: 20, weight: 500 } } },
    var:        { active: { color: "#B49541", barbkg: "#ccaf5f", font: { size: 20, weight: 600 } }, 
                  select: { color: "#dfab1c", barbkg: "#ccaf5f", font: { size: 20, weight: 600 } }, 
                    idle: { color: "#B49541", barbkg: "#a9abb6", font: { size: 20, weight: 500 } } },
    clip:       {   name: { color: "#41b467",                      font: { size: 20, weight: 600 } },
                 markers: { color: "#ceb778",                      font: { size: 20, weight: 600 } },
               barActive: {                     barbkg: "#ddbb5c"                                  },
             barInactive: {                     barbkg: "#a9abb6"                                  } },
    param:      { title:  { color: "#B49541",                      font: { size: 20, weight: 600 } }, 
                    text: { color: "#ebe6d8",                      font: { size: 20, weight: 500 } } }
};

function setObjStyle(obj, bar, key1, key2) {
    const style = gvar.styles[key1]?.[key2];
    if (!style) {
        console.warn(`Unknown style: ${key1}.${key2}`);
        return;
    }

    if (style.color && obj) {
        obj.color = style.color;
    }

    if (style.font && obj) {
        if (style.font.size !== undefined) obj.fontSize = style.font.size;
        if (style.font.weight !== undefined) obj.fontWeight = style.font.weight;
    }

    if (bar && style.barbkg) {
        bar.bar_bg_c = style.barbkg;
    }
}


// Device Navigation
gvar.g_autofold = 0; // See DV_Nav_Dial
gvar.g_showClip = false; // Toggle Device / Clip View
function OnGlobalVariableChanged(name, value) {
    // Let modules set a view switch via g_showClip
    if (name == "g_showClip") {midi.sendCC(16, 111, (value) ? 0 : 127);}
}

// StreamDeck Connection
const DEVICE = "Stream Deck +";
midi.sendCC(11,0,127);
function OnDeviceConnected(DEVICE) {
    console.warn("B ENV: Device " + DEVICE + " connected");
    midi.sendCC(11,0,127);}
function OnDeviceDisconnected(DEVICE) {
    console.warn("B ENV: Device " + DEVICE + " disconnected");
    midi.sendCC(11,0,0);}


module.exports = {setObjStyle};

and I have only 3 background scripts.

I reverted to Version 4.2.0.133 for the moment.
Let me know if you need further testing.

Log ID:
f5c41eb3-b8b2-4aa6-b917-71d8c0cbaa66

Video:

Log should describe the behaviour shown in the video.

Everytime I restart the Stream Deck Software, the ports of the background scripts are configured to ports GP11 and GP12 (the ports that I manually put for testing).

Once the Stream Deck Software has been launched, I press the “Run(init)commands“ button of every background script. They are set to the correct ports.

But when the Stream Deck Software is quitted and launched again, the ports are restored to GP11 and GP12.

And also a little annoyance.
It seems that in javascript, in midi.sendCC the channel is is 1 based while it is 0 based in OnControlChangeReceived.

Am I correct ?
Do you think that should be changed while we are still in a beta ?

The intention has always been to keep it 1 based in JavaScript; I’ll check it.

I found the issue with the midiScript port settings in the (init) commands, and, as I suspected, it was a timing issue. The (init) commands worked as expected when started manually, but failed when started at plugin startup.

I have reordered things and added synchronization at plugin startup, which seems to solve the problem.

@thx538 , I am unable to reproduce your problem, but it is possible that it was caused by the same timing issue. Please try this version and see if your issue is resolved.

Breaking change: The channel reported in midi events is now 1-based.

Version 4.2.0.203

Version 4.2.0.203:
Confirmed that the (init) commands are working as expected in bg scripts.
Actions for chaging ports are working as expected in all scenarios.
Setting Midi ports to #none# is working as expected in all scenarios.

Yes, it seems. I don’t see the “Plugin is loading …” window at startup anymore.