Jump to content

LPX Scripter Toolkit


Dewdman42

Recommended Posts

I have been slowly developing an add-on Scripter toolkit which provides some helper functions, classes and objects which can make some tasks easier to deal with in Scripter. There is still lots more to do and the project can change at any time, but I offer public access to it now in order to get more suggestions and ideas from anyone brave enough to try it.

 

You can read the wiki about it here: https://gitlab.com/dewdman42/lpxscriptertoolkit/-/wikis/home

 

Basically this will be a supplemental API that provides higher level functionality then what is provided by Apple, and also works around some of the annoyances we all know about.

 

The main file of interest in this repo is the file called mods.js. This file can be copy and pasted into Logic's MIDIClass.js file, and then instantly your scripts will have access to the enhanced API.

 

I will be adding more features as I go and if you make good suggestions I will take them into consideration in order to make this helpful for all.

 

In the future I intend to also create an external program which can be used to automatically install or remove this enhancement from LogicPro and also to provide a way to copy and paste the toolkit directly into a script in compact form so that if you make a script using this higher API, the script can be shared with other users who don't have the toolkit installed on their system.

 

Please let me know if you have any questions or suggestions.

Edited by Dewdman42
Link to comment
Share on other sites

Glad to hear! Please definitely let me know what you wish it could do. There is a list of things I plan to add.

 

Mostly it will be small tools, not big feature rich things. The idea is that YOU can write feature rich scripts using these simple extensions.

 

But I’m definitely open to hearing ideas about what those extensions ought to be in order to easily facilitate feature rich scripts.

Link to comment
Share on other sites

In case anyone wants to give it a try, what is there so far... Here is an easy installer I just put together that installs the extensions into LPX and provides a way to go back too factory also.

 

InstallToolkit.zip

 

installer.jpg.e8e876bd14ad86df41bf97189da4034a.jpg

 

Current API docs are here: https://gitlab.com/dewdman42/lpxscriptertoolkit/-/wikis/LogicPro-Scripter-Toolkit-API

 

Need feedback about what would be most useful to work on next...

Link to comment
Share on other sites

  • 10 months later...

Very cool..just learning about scripter due to a crazy limitation with how Logic can not really handle my use case. So I went down the environment path and can get that to basically do what I want….but I need it to be much easier to explain to others who use it. And should work like other channels to some degree. With a plug-in right on the channel, you can just insert your custom midi transformation tools right where you need…vs opening a new layer and dragging channel objects and patching…making sure to select the right channel…etc…everytime you create a new track. Basically the dance is just too many steps and is not extensible.

 

I read your api and dang the event extensions are exactly what I would want to leverage. It’s seems relatively simple what I want to do. The plug-in will intercept all midi coming into Logic. Then when midi note on data is sensed…it mutes the software instrument channels output for a configurable duration. It will also provide an offset for forwarding midi to Logic channel for best alignment when views in piano roll editor. Turning off quantize radial would be cool too.

 

Some of the track timing may prove too difficult if logics delay compensation can’t be bypassed to the vsti channel while it records. Using an external midi plug-in will put it correctly in time with the project. It is also selectable to allow for delay compensation, so it is in there somewhere.

 

Now I think my use case is not terribly uncommon. I need the virtual instrument channel to still record while muting its output. I monitor with a hardware synth to get the timing right and find something close in timbre. I want to also punch in and out on the channel so it needs to play through until the live midi is again sensed. Do you know of a way to determine if the channel is armed and the transport is in record mode?

 

I am new to JavaScript but should be able to pick it up…any help or skeleton example would be welcome. Can scripter work prior to channel input? Or is there a way to control an environment object from scripter?

 

Thanks in advance! Great work.

Link to comment
Share on other sites

Can scripter work prior to channel input? Or is there a way to control an environment object from scripter?

There are some basic things that are missing from your desription and these have quite some impact on how to tackle that kind of problem.

 

- Scripter sits in a MIDI FX plugin slot which only ever deals with MIDI events coming from a Track, either already there or played live while that Track is selected. So it can't affect events before they reach a Track.

- Because of its location inside a virtual instrument MIDI>Audio stream, Scripter events cannot control the parameters (fader, mute, solo) of the very Track/Channel they live in, nor others, for that matter, at least not directly. Because of this, they also can't be routed to the Environment directly (although there is a way, just sit tight).

- Also, Scripter does not deal with MIDI Sysex Data or Logic's Meta Events or Fader Events, the latter being essential to control fader, mute and solo of a Track/Channel.

- The Environment is much more versatile as far as location of the process(es) goes. It can process live input (regardless of track selection), route MIDI, Meta and Fader data between Environment-, MIDI- and Audio-objects, branch off conditionally to other Environment-, MIDI- and Audio-objects, etc.

- However, Environment-objects can't be put between Scripter and virtual instrument, as that is inside the mentioned virtual instrument MIDI>Audio stream (again, there is a workaround).

- Also, Environment has no concept of time, so you can not have it "do x for y time" or "wait x time before doing y".

 

To route Scripter events back into the Environment, you use the External Instrument Plugin (EIP) as the VI after Scripter. EIP lets you choose a MIDI port. If you have activated the Inter Application Communication (IAC) driver in MacOS's Audio-MIDI-Setup, you can select that as the MIDI out port which will bring the data stream back into the Environment via an automatically created MIDI in port, ready for Environment tweaks.

Beware, there is the risk of a MIDI feedback loop if the Channel with the EIP is selected as the active track (again, ways around that).

 

Anyway, in your use case I'd not even bother thinking about Scripter and how to get data back and forth with all its complications. I'd dedicate a latching button (sending CC72 in this example) on the keyboard to manually control the Mute of the selected track, with just one Transformer:

 

Before:

 

2051087177_Bildschirmfoto2021-09-16um08_56_35.png.6f960a38998445238ef8d83647c54d0c.png

After:

 

1759493563_Bildschirmfoto2021-09-16um08_59_05.png.123bbe81703f0b0027bf475bc5b0bb0b.png

Which does this when that button is pressed:

 

chmute.gif.45c0664292e550c9115193476e6bbfe2.gif

This way you can even choose to use the feature for extra tight funky clavinet for Jamiroquai or skip it when you need to create a soft and lush strings backdrop for "The long and winding road".

 

Make this your Template and you're set.

Link to comment
Share on other sites

Can scripter work prior to channel input? Or is there a way to control an environment object from scripter?

There are some basic things that are missing from your desription and these have quite some impact on how to tackle that kind of problem.

 

- Scripter sits in a MIDI FX plugin slot which only ever deals with MIDI events coming from a Track, either already there or played live while that Track is selected. So it can't affect events before they reach a Track.

- Because of its location inside a virtual instrument MIDI>Audio stream, Scripter events cannot control the parameters (fader, mute, solo) of the very Track/Channel they live in, nor others, for that matter, at least not directly. Because of this, they also can't be routed to the Environment directly (although there is a way, just sit tight).

- Also, Scripter does not deal with MIDI Sysex Data or Logic's Meta Events or Fader Events, the latter being essential to control fader, mute and solo of a Track/Channel.

- The Environment is much more versatile as far as location of the process(es) goes. It can process live input (regardless of track selection), route MIDI, Meta and Fader data between Environment-, MIDI- and Audio-objects, branch off conditionally to other Environment-, MIDI- and Audio-objects, etc.

- However, Environment-objects can't be put between Scripter and virtual instrument, as that is inside the mentioned virtual instrument MIDI>Audio stream (again, there is a workaround).

- Also, Environment has no concept of time, so you can not have it "do x for y time" or "wait x time before doing y".

 

To route Scripter events back into the Environment, you use the External Instrument Plugin (EIP) as the VI after Scripter. EIP lets you choose a MIDI port. If you have activated the Inter Application Communication (IAC) driver in MacOS's Audio-MIDI-Setup, you can select that as the MIDI out port which will bring the data stream back into the Environment via an automatically created MIDI in port, ready for Environment tweaks.

Beware, there is the risk of a MIDI feedback loop if the Channel with the EIP is selected as the active track (again, ways around that).

 

Anyway, in your use case I'd not even bother thinking about Scripter and how to get data back and forth with all its complications. I'd dedicate a latching button (sending CC72 in this example) on the keyboard to manually control the Mute of the selected track, with just one Transformer:

 

Before:

 

Bildschirmfoto 2021-09-16 um 08.56.35.png

After:

 

Bildschirmfoto 2021-09-16 um 08.59.05.png

Which does this when that button is pressed:

 

chmute.gif

This way you can even choose to use the feature for extra tight funky clavinet for Jamiroquai or skip it when you need to create a soft and lush strings backdrop for "The long and winding road".

 

Make this your Template and you're set.

I'm sure Apple had it's reasons to not include sysex in Scripter, but a MidiFX plug-in itself can deal with sysex messages as well as send it back to the host (Logic)

Sysex in AUv3

 

I haven't yet tried it in my MidiFx plug-in, but when sending back to the host (Logic) using AUMIDIOutputEventBlock, you can send actual Midi Events specified by the Midi Specifications.

Not sure how Logic would deal with me sending Meta Events like Marker, Cue Point, Lyric, etc.. via the AUMIDIOutputEventBlock.

Link to comment
Share on other sites

Fuzz and Val,

 

Thats an interesting direction that never occurred to me…sysex F9, F4, F5, and F253; as a way to map and trigger something in the environment and vice versa.

 

Thanks for the visuals, super helpful! And killer response!

 

So for playback events, scriptor sits after playback and before any Instruments. If record is set, the VSTi treats the received events just like playback. The environment however can intercept before it hits the Logic sequencer engine. Right?

 

I gather that when using the external midi instrument plug-in you can then get midifx scriptor to “sit in-front” of the environment when used on an external midi track?! Which is really cool, and I am going to try that to use midifx strummer to play some outboard gear. Then try the iac to play a standalone like kontact player or pipe back into logic.

 

Back to topic….So in my case that would still require two tracks, essentially making my no output midi track no longer needed. But you have to still select the external midi track and record enable the VSTi track you mean to record on. Not really hard to do, and I suppose that’s a much cleaner work flow without every instrument requiring two tracks. I would however still prefer a couple objects set in the environment, never to be looked at again…like your suggestion. And then just throwing a scriptor on the instrument track where you would want that functionality.

 

An environment cc trigger could allow midi to pass to the virtual instrument only when a conditional state is met. So the environment sets a special CC flag that isn’t recorded on the midi track. Sysex is a cool approach as that is not normally recorded. Having it as a track pluggin eliminates the no-output track. And you can just turn midifx off when your done recording with that track. Could even map the plug-in bypass function to some midi event or key press.

 

In the environment set up a global transformer to send F4 for all note on events and F5 for all note off events without filtering the source data.

 

In Scriptor when it sees F4/F5 events it filters all midi from reaching the VSTi. When it sees no F4/F5 events it just lets them play.

 

So the scriptor logic might be something like if F4 or F5 exists and Note on or Note off exists then run block output. If F4 or F5 do not exist and Note on or Note off exists then run stop block output. I think some type of window average and timer to smooth out a change of blocking state would be a good measure for sanity…but maybe not even needed.

 

Seems pretty simple. I see a potential for hung notes. So some type of dimensional array to track which note-ons have not been sent note-offs…for when going to the blocking state. But v1 could just send all note offs and value resets for the pedals, pitch and wheel with each blocking function state change. Maybe use a dictionary lookup for what things and values comprise a reset. A midi panic lite of sorts, I guess.

 

V2 could track live vs playback by comparison, you would have to duplicate one channel to a dedicated midi channel in the environment and maybe have all those velocities reset to zero. The idea being only the live events are the ones that get dropped. That would allow for overdub loop style of midi recording…even with external gear. But I still primarily punch in-out with both audio and midi.

 

Thanks for your detailed responses. Great stuff! You both rule!

Link to comment
Share on other sites

Fuzz and Val,

 

Thats an interesting direction that never occurred to me…sysex F9, F4, F5, and F253; as a way to map and trigger something in the environment and vice versa.

 

Thanks for the visuals, super helpful! And killer response!

 

So for playback events, scriptor sits after playback and before any Instruments. If record is set, the VSTi treats the received events just like playback. The environment however can intercept before it hits the Logic sequencer engine. Right?

 

I gather that when using the external midi instrument plug-in you can then get midifx scriptor to “sit in-front” of the environment when used on an external midi track?! Which is really cool, and I am going to try that to use midifx strummer to play some outboard gear. Then try the iac to play a standalone like kontact player or pipe back into logic.

 

Back to topic….So in my case that would still require two tracks, essentially making my no output midi track no longer needed. But you have to still select the external midi track and record enable the VSTi track you mean to record on. Not really hard to do, and I suppose that’s a much cleaner work flow without every instrument requiring two tracks. I would however still prefer a couple objects set in the environment, never to be looked at again…like your suggestion. And then just throwing a scriptor on the instrument track where you would want that functionality.

 

An environment cc trigger could allow midi to pass to the virtual instrument only when a conditional state is met. So the environment sets a special CC flag that isn’t recorded on the midi track. Sysex is a cool approach as that is not normally recorded. Having it as a track pluggin eliminates the no-output track. And you can just turn midifx off when your done recording with that track. Could even map the plug-in bypass function to some midi event or key press.

 

In the environment set up a global transformer to send F4 for all note on events and F5 for all note off events without filtering the source data.

 

In Scriptor when it sees F4/F5 events it filters all midi from reaching the VSTi. When it sees no F4/F5 events it just lets them play.

 

So the scriptor logic might be something like if F4 or F5 exists and Note on or Note off exists then run block output. If F4 or F5 do not exist and Note on or Note off exists then run stop block output. I think some type of window average and timer to smooth out a change of blocking state would be a good measure for sanity…but maybe not even needed.

 

Seems pretty simple. I see a potential for hung notes. So some type of dimensional array to track which note-ons have not been sent note-offs…for when going to the blocking state. But v1 could just send all note offs and value resets for the pedals, pitch and wheel with each blocking function state change. Maybe use a dictionary lookup for what things and values comprise a reset. A midi panic lite of sorts, I guess.

 

V2 could track live vs playback by comparison, you would have to duplicate one channel to a dedicated midi channel in the environment and maybe have all those velocities reset to zero. The idea being only the live events are the ones that get dropped. That would allow for overdub loop style of midi recording…even with external gear. But I still primarily punch in-out with both audio and midi.

 

Thanks for your detailed responses. Great stuff! You both rule!

Don't get me wrong, I love Scripter and The Enviroment but it sounds like you want something complex.

You should look into writing a MidiFx plug-in instead.

What's great about AUv3 is you can put hosting capibility in the main app, while still having the Audio Unit Extension be available to Logic and the main app.

Now instead of relying on Logic, you can code exactly what you want in the main app that intializes your Audio Unit Extension.

The key here though is design, design, design. Don't just code on the fly. Sometimes that's what I do with Scripter because Scripter allows for that. I make a change "run script" and now it's available to use.

Not the same using Swift or Objective-C.

 

Just food for thought.

Link to comment
Share on other sites

So for playback events, scriptor sits after playback and before any Instruments. If record is set, the VSTi treats the received events just like playback. The environment however can intercept before it hits the Logic sequencer engine. Right?

Right.

 

when using the external midi instrument plug-in you can then get midifx scriptor to “sit in-front” of the environment

If you use IAC to pipe it back into Logic, yes.

 

An environment cc trigger could allow midi to pass to the virtual instrument only when a conditional state is met.

You're making it way more complicated than necessary. If you go as far as setting up a CC trigger, you may as well just mute the channel with it and be done.

Using Note Ons and Offs to determine data routing might work with simple, clear, slow monophonic lines, but will fall flat on its face if more than one note and/or performance data like MWheel, PitchWheel and Sustain Pedal happen at the same time and get arbitrarily blocked which would easily result in hung or detuned notes. This will be a bitch to debug, I promise.

 

Sysex is a cool approach as that is not normally recorded.

This is not true, it gets recorded like any other MIDI data. Also, just to make sure, Sysex MIDI is something else than Logic's internal Meta Data.

 

Could even map the plug-in bypass function to some midi event or key press.

Again, map the channel mute to the MIDI event and you're set without even coding a script.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...