Jump to content

Undocumented Scripter features


Dewdman42

Recommended Posts

Over the course of the past few weeks I have been learning the Scripter API, I have come across a number of undocumented features.  Some of these things are just things that are built into JavaScript and usable in Scripter, and some are hidden features specific to Scripter.  I am gathering some notes in order to put together an undocumented feature list.  If anyone knows of any other hidden features or things that have been discovered to work with Scripter which are not explicitly documented in the Logic Effects Manual, please add to this thread and I will consider for this document.  Here is what I have so far.

 

  1. PluginParameters array has a checkbox type of UI element that is not documented.  It provides simple value of 0 or 1 depending on checkbox state.  I am unaware of any other attributes for this UI type that might be available.
  2. PluginParameters array has a new momentary type of UI element introduced in LPX 10.3.2.  This type does not maintain any state, it can just be used to trigger the ParametersChanged() callback function.
  3. UpdatePluginParameters() function does not appear to be documented in the Logic Effects manual, but it does show up in some of the example scripts there.  This function causes the UI to be redrawn, so in this way it can by dynamically changed.
  4. There is a callback function called Idle(), which is called by LPX a few times per second, but during idle times only so it won't get in the way of HandleMIDI() and ProcessMIDI() from doing their job.  I found this by looking at the factory example script called Stutter V2.  This is a very good callback function to put housekeeping duties like updating the GUI or other counting operations that aren't directly involved with sending midi events.
  5. The UI menu type items have some built in behavior that changes what they look like if there is only one value in the menu, not clear to me exactly what that is. With two items in the value list, it shows as two radio buttons.  Three or more appear as popup menu.
  6. When NeedsTimingInfo is true, beatPos can be set on outgoing midi events to specify their playback timestamp.  There are also several functions which can play the midi event at some distance in the future relative to that beatPos timestamp of the event.  I have found that using sendAfterBeat() and sendAfterMilliseconds(), the outgoing midi event can also be well in the future beyond the end of the current process block.  Its not clear to me what happens if you just set the beatPos to a value beyond the end of the process block.
  7. It should be noted that the beatPos floating point value that is provided is not always exactly what the outgoing event will be because all output in LPX is rounded to the nearest midi tick (1/960 beat). 
  8. the hidden attribute of UI elements is not documented, but can be found by looking at examples provided in the Logic Effects manual.
  9. The disableAutomation attribute of UI elements is not documented, but appears to disable automation from being able to change the specific UI controls that have that attribute set to true.

That is what I have so far.  Any and all information about undocumented features in Scripter are welcome on this thread and I will consider for the document I am putting together.  This could include JavaScript features that are particularly useful in Scripter.

  • Like 1
Link to comment
Share on other sites

Another thing that is commonly know, but is here for completeness and will be documented soon is the following file:

 

/Applications/Logic Pro X.app/Contents/Frameworks/MADSP.framework/Resources/EventTypes.js

 

this file defines some, but not all, of the built in API of scripter, including the event classes and MIDI functions.  Its possible, but not reccomended, to add things to this file in lieu of extern support.

Link to comment
Share on other sites

Here's a neat "feature":

 

If you create a new NoteOff event with an existing NoteOn event as an argument (ex. let off = new NoteOff(e);)

off in our example is an instance of NoteOff with a positive velocity and the MIDI status of a NoteOn. Someone at Apple got bored before fixing the entire code base.

Link to comment
Share on other sites

well, here's a question, do you know if there is any way to call the constructor of the various midi event types and provide data such as velocity, channel, pitch, etc...as arguments to the constructor?

 

Also do you know if there is any way to create a midi event object without calling "new"?

Link to comment
Share on other sites

Well interestingly enough, I did play around with that.  I was using an ES5 approach before to create a sort of subclass with an improved constructor.  It works fine under ES5.  Then with ES6 I tried to do it with "class" and performance and timing of the midi playback suddenly went out the window, I have no idea why and went back to the ES5 approach.  now that I have learned a little more about JavaScript I actually prefer the old way.  I think the new class directive is just a thin wrapper around underlying JavaScript.  JavaScript on its own is much more flexible and not so heavily type-based.  Everything is an object and you can freely modify objects on the fly and basically do whatever you want.  That being said, I'm still curious if the built in midi event types provided by Scripter have any other constructors already.  You mentioned that you used an undocumented constructor passing a NoteOn event to the NoteOff constructor...and it did sort of work for you, though not predictably.   In fact to me that sounds like just an accident in the way its implemented as a function in EventTypes.js.   Somehow it picks up the argument passed in, but assumes it is something other then it is.  It probably assumes that its a NoteOff object or something, not really sure.

 

Anyway, I'm just wondering if I can avoid creating the subclass in order to have better constructors.   Can't we just modify the prototype of NoteOn, for example?

Link to comment
Share on other sites

  • 2 weeks later...

Its been a busy few weeks! 

 

Yes, mining the factory presets unearths a lot of the information which is missing from the documentation. In fact, I blame the documentation for many of the reasons why the more advanced functionality isn't imminently obvious. It has frustrated the hell out of me. Anyhow.

 

If you check the class implementations in EventTypes.js file you will see that each constructor essentially clones any object that is provided to the constructor, taking only the values relevant to the class type type into account; so, as @Unheardofski mentioned, you can pass a NoteOn instance into a NoteOff constructor, and vice versa. As far as I know, you can do this with any event instance, and default values are used in cases where the provided object property names don't match up or are nullish.

 

> well, here's a question, do you know if there is any way to call the constructor of the various midi event types and provide data such as velocity, channel, pitch, etc...as arguments to the constructor?

 

You are right that there is no way to parameterise event type constructors directly, but you could implement the Factory pattern do that job for you. If design patterns seem a but redundant in this context, I think simply accepting the 'clone' approach of EventTypes constructors may work for you in that context @Dewdman42?.Check the property assignments in the constructors to get a better idea.

 

In relation to subclassing midi classes, I suspect there is the possibility that there are some intrinsic Objective-C bindings to the class types in Scripter via JavaScriptCore and the way it has been configured internally by Logic/Mainstage, so subclassing event types is probably best avoided for production work or professional script production at the moment.

 

If you prefer the 'stick anything to anywhere' approach of ES5, yes, you can modify the prototype of all the EventType classes and objects rather than creating your own classes in the EventTypes.js file. You can extend, modify and override prototypes directly in the Scripter Editor and save those runtime mutations in a PST. BTW, any code, and I mean ANY code you put into the EventTypes.js file is injected with each script evaluation, so ensure that you first back up the file before you go modifying.

 

I'm curious as to what you meant be the 'Fader' type... yes, there is a well known blog post that mentions Faders, and there is a relatively infamous github gist that looks authentic that alludes to a Fader class, but there is no Fader class in the EventTypes.js file.

 

I mean that. Allow me to close this:

 

There is no Fader event type or parameter type. 

 

You can do this and see no errors:

PluginParameters = [
    {
        name: "Not A Fader But A Linear Slider"
    ,   type: "fader"
    ,   defaultValue: 0
    ,   minValue: 0
    ,   maxValue: 100
    ,   numberOfSteps: 100
    }
]

 

But you can also do this and see no errors:

PluginParameters = [
    {
        name: "Still A Linear Slider"
    ,   type: "whatveryoulike"
    ,   defaultValue: 0
    ,   minValue: 0
    ,   maxValue: 100
    ,   numberOfSteps: 100
    }
]

 

That word has caused a lot of confusion in the context of Scripter. I think it comes down to the mixed language used in the manuals... the word 'slider' and 'fader' are used interchangeably there, but there is no Fader in the production code that ships with Scripter. To verify, you will get a ReferenceError if you add ``new Fader()` in a script (without a custom Fader class, which independent of this, did use as shorthand for a logarithmic sider class at one point). It mirrors the disparate references to 'GetHostInfo' and 'GetTimingInfo' in some of the comments within the factory presets also. Apple did a bad job there IMO.

 

I'm ranting now. Personally, I believe the value of ES6 is mostly synthetic, that is, its a headspace thing entirely down to personal preferences and how one likes to architect and interpret a system (or fancies themselves as doing such). But that said... it is a preference of my own, so I use them without modifying the Scripter API methods and objects of the Scripter API. Any ES6 construct has a mirror image ES5 construct (in most cases - new.target is the exception, but thats not relevant here), so, tomatoes/tomatoes. But if the stylistics of ECMAScript/JavaScript are too interruptive, you could also attempt using CoffeeScript or CoffeeScript2 and transpiling your code to an edition of ECMAScript that can be used in Scripter. If you have programming experience or an incessant curiosity, Babel can be fun to play around with.

 

Here is a checkbox:

 

PluginParameters = [
    {
        name: "check"
    ,   type: "checkbox" // undocumented
    ,   defaultValue: 0 // set to 1 to have it checked by default
    }
]
// elsewhere
function ParameterChanged (index, value) {
    // in case you have multiple parameters...
    switch(index) {
        case 0 :
            var presentValue = GetParameter(0)
            var nextValue = presentValue === 0 ? 1 : 0
            SetParameter(0, nextValue)
    }
}

 

How hard is that? Why the hell couldn't they just put that in the manual???? They do fail to communicate that ParameterChange events are buffered, so after setting a parameter, you are not notified until another parameters has changed in the GUI. Or that there is a 256 byte limit to Trace and a dormant console, or that the byte value of unicode emoticons is higher and make it easier to choke the thing. Or to type the word 'clear' at the bottom of the console and hit enter to execute it. OMFG. 

 

BTW:

- there is a reference to the hidden property under the "Dynamically hide or show MIDI plug-in controls" heading here

- there is also a referent to UpdatePluginParameters in the same section linked above

- there is a reference to disableAutomation under the "SetParameter" section of the MainStage manual here

 

Thankfully the Logic Manual is now online, but I would recommend reading though the (very annoying) documentation on Scripter in both the Logic and MainStage effects manuals for a more comprehensive (yet irritating) overview.

 

On a different note, I would welcome anyone available to help me test the Scriptable library I've been working on for the past few weeks, so please drop me a line if you are interested. One of the most difficult parts is documentation, so assistance there would be most welcome (GitBook experience would be excellent!). Never give a night owl too much coffee. Laterz!

Link to comment
Share on other sites

 

I'm curious as to what you meant be the 'Fader' type... yes, there is a well known blog post that mentions Faders, and there is a relatively infamous github gist that looks authentic that alludes to a Fader class, but there is no Fader class in the EventTypes.js file.

 

I mean that. Allow me to close this:

 

There is no Fader event type or parameter type. 

There used to be but it has never done anything, I guess they eventually scrapped/removed it.

This is from a saved older version of the EventTypes.js I have (that file is identical to the gist you reference):

Fader.prototype = new Event();
Fader.prototype.constructor = Fader;
//-----------------------------------------------------------------------------
function Fader(e) {
   this.status = 0x50;
   if (e) {
       // clone existing event
       this.channel = (e.channel) ? e.channel : 1;
       this.number = (e.number) ? e.number : 1;
       this.value = (e.value) ? e.value : 0;
       this.inStartFrame = (e.inStartFrame) ? e.inStartFrame : 0;
       this.isRealtime = (e.isRealtime) ? e.isRealtime : false;
   } else {
       // default values
       this.channel = 1;
       this.number = 1;
       this.value = 0;
       this.inStartFrame = 0;
       this.isRealtime = true;
   }
};

//-----------------------------------------------------------------------------
Fader.prototype.toString = function() {
   return '[' + this.constructor.name +
       ' slot:' + this.channel +
       ' parameter ID:' + this.number +
       ' value:' + this.value + ']';
};


Link to comment
Share on other sites

If you check the class implementations in EventTypes.js file you will see that each constructor essentially clones any object that is provided to the constructor, taking only the values relevant to the class type type into account; so, as @Unheardofski mentioned, you can pass a NoteOn instance into a NoteOff constructor, and vice versa. As far as I know, you can do this with any event instance, and default values are used in cases where the provided object property names don't match up or are nullish.

 

> well, here's a question, do you know if there is any way to call the constructor of the various midi event types and provide data such as velocity, channel, pitch, etc...as arguments to the constructor?

 

You are right that there is no way to parameterise event type constructors directly, but you could implement the Factory pattern do that job for you. If design patterns seem a but redundant in this context, I think simply accepting the 'clone' approach of EventTypes constructors may work for you in that context @Dewdman42?.Check the property assignments in the constructors to get a better idea.

 

In relation to subclassing midi classes, I suspect there is the possibility that there are some intrinsic Objective-C bindings to the class types in Scripter via JavaScriptCore and the way it has been configured internally by Logic/Mainstage, so subclassing event types is probably best avoided for production work or professional script production at the moment.

 

If you prefer the 'stick anything to anywhere' approach of ES5, yes, you can modify the prototype of all the EventType classes and objects rather than creating your own classes in the EventTypes.js file. You can extend, modify and override prototypes directly in the Scripter Editor and save those runtime mutations in a PST. BTW, any code, and I mean ANY code you put into the EventTypes.js file is injected with each script evaluation, so ensure that you first back up the file before you go modifying.

So, using the clone feature I guess could work something like this:

var newNote = new NoteOn( {pitch: 45, channel: 1, velocity:100} );

For those new to Javascript, the curly braces above {} indicate the declaration of an untyped object.

In the above example, an object containing 3 parameters is passed in to the NoteOn constructor, and the NoteOn constructor knows to look for certain parameters by name and copy them to itself.   Other members are set implicitly by the NoteOn constructor.

 

The above would not work for me because the beatPos member is not cloned by the constructor in EventTypes.js.  Therefore I created a subclass with an improved constructor.

 

its definitely possible to subclass midi events in ES5 with a new parameterized constructor.   This is how I have done it.

var MyNoteOnSubclass = function(beatPos, channel, pitch, velocity) {  
  NoteOn.call(this, beatPos, channel, pitch, velocity);
  this.beatPos = beatPos;
  this.channel = channel;
  this.pitch = pitch;
  this.velocity = velocity;
};
MyNoteOnSubclass.prototype = Object.create(NoteOn.prototype);  
MyNoteOnSubclass.prototype.constructor = MyNoteOnSubclass; 

 

The above then allows the following

var note = new MyNoteSubclass( 1.5, 1, 45, 100 );

 

I have used this in Scripter and it works fine.  Calling note.send() does exactly what its supposed to, for example...  and beatPos can now be parameterized in the constructor of the subclass.  However a factory could have also just as easily been done like this and avoid subclassing:

 

function NoteOnFactory( beatPos, channel, pitch, velocity ) {
   var event = new NoteOn;
   event.channel = channel;
   event.pitch = pitch;
   event.velocity = velocity;
   event.beatPos = beatPos;

   return event;
}

 

and used like this

 

 

var note = NoteOnFactory( 1.5, 1, 45, 100 );

 

 

As to why some people have reportedly gotten some odd results trying to use an existing NoteOn to clone to to NoteOff or visa versa...

 

If you use an existing object to pass to the constructor like this:

var firstNote = new NoteOn;
NoteOn.channel = 1;
NoteOn.pitch = 45;
NoteOn.velocity = 100;
var newNoteOff = new NoteOff(firstNote);

 

The above pretty much does the same thing as the first example I gave, except it creates a NoteOff, cloning channel, pitch, velocity, articulationID and isRealTime from the incoming NoteOn object.  Javascript doesn't care that a NoteOn object was passed in.  The constructor clone in EventTypes.js doesn't seem to do anything wrong though, that I can see.  ??

 

What I am learning about JavaScript is that typing is extremely loose, pretty much nonexistent.  Everything is an object.  Objects are not type-checked really.  You can talk about classing and subclassing, but the truth is that Javascript doesn't enforce much in terms of type-checking.  That's why you can pass an NoteOff object into the NoteOn constructor, or even just pass in a totally typeless object such as 

 

{pitch: 45, channel: 1, velocity:100}

 

In Javascript you can create all sorts of typed and untyped objects on the fly any way you want and pass them around from here to there, and JavaScript won't complain, because there is no type checking, including classes.   When classes are "subclassed" so to speak, in JavaScript, members and methods are inherited, which can be handy.  To some degree there may not be much point in trying to using typical OOP class hierarchies in Javascript because its not  enforced strictly anyway.  On the other hand, its extremely convenient and a feature of JavaScript, to build objects on the fly and pass them around your script.  As long as the neccessary member values or methods are there when its called later..it will all just work.  That is very convenient feature of JavaScript, but unfortunately it also allows a NoteOn object to be passed to a NoteOff constructor and JavaScript doesn't type check it at all, leading to potentially undesirable results.

Link to comment
Share on other sites

 

As to why some people have reportedly gotten some odd results trying to use an existing NoteOn to clone to to NoteOff or visa versa...

 

If you use an existing object to pass to the constructor like this:

var firstNote = new NoteOn;
NoteOn.channel = 1;
NoteOn.pitch = 45;
NoteOn.velocity = 100;
var newNoteOff = new NoteOff(firstNote);

 

The above pretty much does the same thing as the first example I gave, except it creates a NoteOff, cloning channel, pitch, velocity, articulationID and isRealTime from the incoming NoteOn object.  Javascript doesn't care that a NoteOn object was passed in.  The constructor clone in EventTypes.js doesn't seem to do anything wrong though, that I can see.  ??

let a = new NoteOn();
let b = new NoteOff(a);
console.log(b)

[Running] node "c:\Users\ae\GitHub\chordioLPX\EventTypes.js"
NoteOff {
 status: 128,
 channel: 1,
 pitch: 100,
 velocity: 100,
 articulationID: 0,
 isRealtime: true,
 beatPos: 0 }

[Done] exited with code=0 in 0.173 seconds

See above, it doesn't correct velocity if > 0.

I haven't checked all the constructors for similar stupidity but to me this one stands out because the whole point of this seems to be to easily be able to create a NoteOff from existing NoteOn. That simplicity fails when you have to add another line of code to set velocity to zero, not to mention the time it took for me to initially find why my NoteOffs were producing sound...

 

I agree with you that JS's strong suit isn't type checking, but the above is totally on whoever wrote the code.

Although I spew a bit over Scripter in general I love it and nothing's perfect. I wish they would add more parameter types and GUI options, if one looks at the Drum Machine Designer or other MIDI effects, there is a lot that would be nice to have access to.

Link to comment
Share on other sites

NoteOff should still work even with a velocity of 100 though right?  A NoteOn with velocity zero is the same as a NoteOff, but I think a NoteOff with a positive velocity is basically a so called "release velocity", and there have even been some keyboards that made use of it...  I'm not sure that is wrong to clone the velocity.
Link to comment
Share on other sites

@Unheardofski - thanks for the heads up! Guess I must have been late to the party and Fader had been removed by the time I started trying to hack Scripter to my own ends - it seems natural that it would be there if one were able to script the mixer. So I guess the situation is closer to a RIP Fader situation rather that 'there is absolutely no fader and never was (drama)' Pity thats not possible at the moment :( Can you recall the last edition of Logic that had Fader? Its midi status code looks interesting.

 

@Dewdman42 I don't know where to start! Its great that you're reporting your findings here and there is much to discuss as Scripter is most definitely in need of some love (cough), but it has its charms as it is IMO.  I don't want to pollute the thread with programming info (guilty), as to be frank, (a) I wouldn't know where to shut up and (b) I think this is more of a solutions forum than a programming forum (I'm happy with both though). Would you (or anyone else) be interested in setting one up or joining one on Github?

 

I am not trying to negate anything that you provide here by asking this, but what is your opinion on the semantic difference between these two functionally equivalent implementations:

 

var MyNoteOnSubclass = function(beatPos, channel, pitch, velocity) {  
  NoteOn.call(this, beatPos, channel, pitch, velocity);
  this.beatPos = beatPos;
  this.channel = channel;
  this.pitch = pitch;
  this.velocity = velocity;
};
MyNoteOnSubclass.prototype = Object.create(NoteOn.prototype);  
MyNoteOnSubclass.prototype.constructor = MyNoteOnSubclass; 

or

 

class MyNoteOnSubclass extends NoteOn {
    constructor (beatPos, channel, pitch, velocity) {
        super()
        this.beatPas = beatPos
        this.channel = channel
        this.pitch = pitch
        this.velocity = velocity
    }
}

 

?

 

Programming is as much about semantics as it is about efficiency of implementation when the conditions are right IMO ,and Scripter scripts can get large enough to be considered micro-apps, so the easier to read, the easier to refactor and document etc... default parameters have their uses too etc.... There are obvious use cases for subclassing events, but I would proceed with caution, not because of the programmatic limitations, but because of Scripters API limitations.

Link to comment
Share on other sites

NoteOff should still work even with a velocity of 100 though right?  A NoteOn with velocity zero is the same as a NoteOff, but I think a NoteOff with a positive velocity is basically a so called "release velocity", and there have even been some keyboards that made use of it...  I'm not sure that is wrong to clone the velocity.

You may be right and I am mis-remembering, many a script has been written since I stumbled over this. I'll test and report back. If I am wrong I apologize in advance for yapping on about a moot point.

Link to comment
Share on other sites

I am not trying to negate anything that you provide here by asking this, but what is your opinion on the semantic difference between these two functionally equivalent implementations:

 

IDK about semantic difference. I do know that this is hosted in an application for people that are generally reluctant to update OS and DAW. I have decided not to use ES6 or newer stuff like "momentary" on account of being too lazy to make multiple versions of everything. I say go with whichever solution that is more legacy-y. 

 

Also I am upp for the GitHub geekfest

Link to comment
Share on other sites

The purpose of this thread is really to ask y'all to share your undocumented knowledge about scripter.

 

Regarding the semantics, of course I would prefer to use the newer syntax but I wrote a sequencer script a few weeks ago, first using the old way and then later I tried to swap out the subclassing with the new syntax and while it was way easier to read, the timing of the sequencer was way off suddenly for no explicable reason.

 

I have read that the new class syntax is just a wrapper around preexisting javascript mechanisms. I don't know if that's true but if it is true then we don't know what kind of implementation they used to try to emulate the behavior of other OOP languages like java and c++. What I know is that my simple sequencer which was previously very tight was suddenly way way off just by using the class syntax to define my simple subclasses which merely had an updated constructor.

 

Since then I have gotten more comfortable with JavaScript as it is, everything is a prototyped object that can be freely extended on an instance by instance basis. Any notion of class hierarchies is really only by people trying to force that paradigm onto JavaScript, which doesn't require it. There can be advantages to using that paradigm, don't get me wrong, but sometimes it can also be something not worth the hassle for a small self contained script. In that case the loosy goosy object world of JavaScript can be an advantage, and keep script complexity actually lower in some cases.

 

In java/c++, great care is taken by the compiler to enforce certain OOP rules. The reason for this is because when you have a project with millions of lines of code across thousands of source files, you need the compiler to help find bugs. This often actually results in a lot of complicated design patterns that require a lot of code to do a little work, the advantage being code reuse and more compile time checking of some things. There are certain situations where OOP methodologies can be easier to read and more convenient, it other situations where it just creates added complexity, and uncertainty about the code execution path. There are most definitely pros and cons with OOP.

 

JavaScript's fundamental classless paradigm also has pros and cons but I'm getting more comfortable with it and I think it's best to just stay with JavaScript rather then trying to wrap OOP rules of other class based languages around it.

Link to comment
Share on other sites

@Unheardofski Great! - drop me a PM and we can set it up any time. @Dewdman42, you're very welcome to join in if you'd like to? It sounds like we can both program in a few different languages which is great, but it does make it difficult when trying to import that context into Scripter - I can see why you like the ES5 approach - it is by no means a bad thing :)
Link to comment
Share on other sites

NoteOff should still work even with a velocity of 100 though right?  A NoteOn with velocity zero is the same as a NoteOff, but I think a NoteOff with a positive velocity is basically a so called "release velocity", and there have even been some keyboards that made use of it...  I'm not sure that is wrong to clone the velocity.

You may be right and I am mis-remembering, many a script has been written since I stumbled over this. I'll test and report back. If I am wrong I apologize in advance for yapping on about a moot point.

Just tested some, it seems I was wrong all along, sorry.

Link to comment
Share on other sites

Pulling out a few choice undocumented features from your earlier long email...

 

If you check the class implementations in EventTypes.js file you will see that each constructor essentially clones any object that is provided to the constructor, taking only the values relevant to the class type type into account; so, as @Unheardofski mentioned, you can pass a NoteOn instance into a NoteOff constructor, and vice versa. As far as I know, you can do this with any event instance, and default values are used in cases where the provided object property names don't match up or are nullish.

 

Yep, but their cloning is not perfect.  for example, I notice beatPos is not copied.

 

 

They do fail to communicate that ParameterChange events are buffered, so after setting a parameter, you are not notified until another parameters has changed in the GUI.

 

Can you provide an example script showing this?  I would be more inclined to think that ParameterChanged, as a callback is simply called when Scripter gets the next chance to call it.  If you have a lot of midi going on, it might be delayed.

 

Or that there is a 256 byte limit to Trace and a dormant console

 

Yep an important limitation to know about.  The manual does indicate that some Trace messages will be simply lost if there are too many of them at once, and they don't give much detail about how or when that might happen.  They are particularly concerned about Trace blocking midi activity, if the callback takes too long it can cause another callback to be late.

 

My work around is to use an object that buffers trace messages into a queue and flush it, during Idle, but only a few lines flushed at a time.

 

 

, or that the byte value of unicode emoticons is higher and make it easier to choke the thing.

 

Good to know.  Do you have an example of this we can watch out for?

 

 

Or to type the word 'clear' at the bottom of the console and hit enter to execute it. OMFG. 

That's a GREAT undocumented feature to know about!  Do you know if the clear command is available programmatically in any way?

Link to comment
Share on other sites

let a = new NoteOn();
let b = new NoteOff(a);
console.log(b)

[Running] node "c:\Users\ae\GitHub\chordioLPX\EventTypes.js"
NoteOff {
 status: 128,
 channel: 1,
 pitch: 100,
 velocity: 100,
 articulationID: 0,
 isRealtime: true,
 beatPos: 0 }

[Done] exited with code=0 in 0.173 seconds

How did you produce that console.log?

Link to comment
Share on other sites

how much of your Scripter projects are you able to run in visual studio?

By using require for the EventTypes and some dummy functions I can emulate a lot of functionality without ever running Logic but obv only to a certain point. I find it much easier and inspiring to code in VSC or Atom than copy/pasting into scripter back and forth

Link to comment
Share on other sites

I'm happy to join in but I have to keep focus on my own project for the next week or two. I hope that the manual I am attempting to write shows some of this. Its pretty challenging as I sincerely have a problem with being concise and there are a lot of edge cases in Scripter. Testing is definitely important. The library implements a BDD framework so that projects can be tested in an IDE (e.g. Atom) outside of the Scripter Editor. Let me know if you want to lend a hand - I need some testers and there are one or two snags I would like to nip before release. BTW - beatPos is only used when NeedsTimingInfo is true, so, as its a transient variable, I assume that is why it is not cloned. Assumably that is also the case with the isRealTime property etc. Only Apple engineers have the answer to that one! There is no analog to clear that I know of, but, bearing in mind the Trace character buffer issue, you can emulate it (sort of ) with something like this:

 

clear = () => Trace("\n".repeat(25)) // or variation thereof

Link to comment
Share on other sites

  • 4 months later...
  • 4 weeks later...
  • 3 months later...

Has anyone found a way of implementing a timer? Since javascript is single-threaded synchronous, unless one of the things added on top would allow it, I would think that there is no way of doing it. My specific intended use case is to use a descending timer as a means to pool multiple midi events together, where the timer is reset to a default millisecond value every time an event comes in, and when the timer reaches 0, all of the pooled events get processed together. Since the processing of events may or may not be dependent on future events, you can't just set a delay; some kind of timer is needed for this use case.

 

It seems like having a timer would be useful for a lot of things beyond this use case aswell, so it seems weird to me that there is no obvious way of implementing one.

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...