Scztt quark updates

I’ve pushed a number of major updates to some of my quarks, and published a new one. Please take a chance to try them out and let me know if you have any issues!

Here’s a quick run-down:


IconSet quark (new)

Quarks.install("https://github.com/scztt/IconSet.quark");

A quark wrapping two common open-source icon sets - Material (https://material.io/resources/icons/?style=baseline) and Linea (https://linea.io/).

It provides a simple interface to add svg icons to your UI from either of these two sets (including colorizing and scaling).:

  ToolBar(
      MenuAction("Louder").icon_(Linea("music_volume_up")),
      MenuAction("Quieter").icon_(Linea("music_volume_down")),
      MenuAction("Or nothing at all").icon_(Linea("music_mute"))
  )
  .toolButtonStyle_(QToolButtonStyle.textBesideIcon)
  .bounds_(400@60)
  .front;


NodeSnapshot

Quarks.install("https://github.com/scztt/NodeSnapshot.quark");

  • IO display overlay (visible when clicking on an IO triangle) now shows metadata about the bus, including rate, channels, and an average/min/max value.
    tree-1_1

  • Input/output display now shows IO’s for buses that are mapped to Synth arguments via .asMap.

  • IO display is now updated if it changes on the Synth (e.g. a mapped control is changed)
    *Dots are shown next to IO display to indicate channels

  • IO scope displays now show the bus values as the node in question will see them: this means, if a node is reading a bus that is only written to LATER in the graph, the scope will show silence (what the node sees), not an active signal. This can help when debugging node order problems.

  • Added TreeValidator , which can walk a TreeSnapshot and produce warnings of invalid states (e.g. faulty node ordering). It is available in the UI as a button + drop-down at the top of the snapshot view. New validation passes can be added using TreeValidator.addValidation. The default validator will warn in cases where a node is reading from a bus that is written to by a later node, and when a node overwrites bus data already written to by another node before it was read (this bus data would be lost).
    image

  • Bug fixes


OSequence

Quarks.install("https://github.com/scztt/OSequence.quark");

  • OSequence is still highly undocumented! Sorry! But it now has a barebones help file with examples and a short tutorial.
  • Introduced OSequence:plot to visually plot a sequence. The x-axis of the plot is always time - the y-axis is a property of the events in your OSequence , specified in the first argument - e.g. oseq.plot(\midinote) would plot the midinote values from Event s in the sequence.
  • When creating an OSequence via OSequence:*fromStream , Rest events are handled correctly (e.g. no event is stored, but time is incremented)
  • FIX: An issue with OSequence:copy where the same event would remain in two OSequences at once.
  • Implemented common Collection iterators like do , collect , etc., as well as some OSequence specific operations: doTimes , doReplaceTimes , filter (an in-place version of select ), collectKey and setKey (collects/sets e[key] for all items e in the sequence).
  • OSequence now prefers to track the duration of individual events using the sustain key where possible, since this reflects better how Pbind’s behave.

Connection

Quarks.install("https://github.com/scztt/Connection.quark");

  • Added ControlValueEnvir:asPbind , which creates a stream of events representing all the values in a ControlValueEnvir . This can be composed with another event stream to easily modulate parameters.
  • OSCReplyUpdater , SignalStateUpdater , BusStateUpdater now support being placed at a specific location in the synth graph, via target and addAction arguments.

BandSplitter

Quarks.install("https://github.com/scztt/BandSplitter.quark");

  • BandSplitter now supports kr and ar rates.

Singleton

Quarks.install("https://github.com/scztt/Singleton.quark");

  • FIX: Singleton’s passed a string name, e.g. MySingleton("foo") will work as expected (the string will be converted to a symbol and match an existing Singleton). Before this, using a string as a Singleton name would never match, because Singleton s are stored in an IdentityDictionary .

Require

Quarks.install("https://github.com/scztt/Require.quark");

  • If Require cannot find any files to include, it posts warnings specifying it’s search paths for debugging purposes.

  • Require:resolvePaths now takes arguments for both a list of extensions and relative root paths. This does not affect the behavior of Require per se, but makes this useful for complex automatic resolution scenarios, e.g.:

Require.resolvePaths(
	identifier: "Roland TR-66/*Conga*", 
	relativeTo: ["/Users/fsc/Documents/_sounds/drums/Drum Machines/"], 
	extensions:["wav", "aif"]
);

-> [ /Users/fsc/Documents/_sounds/drums/Drum Machines/Roland TR-66/MaxV - Conga Hi.wav,  /Users/fsc/Documents/_sounds/drums/Drum Machines/Roland TR-66/MaxV - Conga Mi.wav ] 
  • Require:roots is a list of root search paths to use when resolving files. The previous example could also work with: Require.roots.add("/Users/fsc/Documents/_sounds/drums/Drum Machines/")

8 Likes

Wow, a new world is opening. Thanks for sharing ! Really intrigued by NodeSnapshot and OSequence !

FYI, I’m getting an error when installing IconSet on SC 3.11-beta1 on Windows.

Installing IconSet
IconSet reports an incompatibility with this SuperCollider version or with other already installed quarks.
-> Quark: IconSet[0.0.1]

The quarks in my downloaded-quarks directory are
Bjorklund
Collapse
Connection
ddwPatterns
FreeAfter
IconSet
JITLibExtensions
miSCellaneous_lib
Modality-toolkit
NodeSnapshot
panola
quarks
SafetyNet
Singleton
Vowel
WavesetsEvent
WindowViewRecall

Best

Geoffroy

Fixed! It should work if you update.

Thanks ! It works now !

Thanks for sharing. NodeSnapshot makes my life easier :smile:

2 Likes

Still doesn’t work out of the box on 3.12.1. First it complains that it can’t find WARNING: IconSet not found I downloaded that one manually. But then it still can’t instantiate the Material class in TreeSnapshotView.initClass. I still don’t know what quark provides the Material class.

Apparently that’s also in IconSet, but the class was somehow not initialized. Apparently I had to download that half-a-GB of Google icons first.

Actually, even after that the class init fails. It tries to call isFolder on a string, but that method is not defined for the String class in standard SC. You probalby forgot to include that extension with your quarks.

The bug is here:

Material : IconSet { ///...

	*folders {
		^(folders ?? {
			folders = (this.rootPath +/+ "*").pathMatch;
			folders = folders.select(_.isFolder); // needs a PathName

The IconSet and Material class are part of the IconSet quark, and should be installed if you’ve installed the NodeSnapshot quark - because they’re marked as a dependency. If you’re having “missing class” errors related to IconSet and Material, make sure the quark is actually installed (Quarks.installed.do(_.postln);).

I pushed a fix for the isFolder issue - you can update via Quark("IconSet").update;.

If you still have issues after updating, let me know exactly what error messages you’re seeing and what led to them? Apart from the isFolder issue, I can’t reproduce any problems on a clean local SC installation.

I fixed that too, but alas it still still doesn’t work even after that, because the current distro of material-icons no longer has any ic_check_box anywhere in their half a gig of stuff. I guess they removed. So now it’s at

 ERROR: Couldn't find icon with name 'ic_check_box' in paths <super long list>

I guess I can substitute it with something like round_check_box, which still exists, an see if that fixes it.

I’m locally on Material 3.0.2 - you can also do git checkout tags/3.0.2 and see if this works? If this works, I’ll tag the dependency in IconSet so it only pulls the older version for now, until I can fix. IIRC they fundamentally restructured the icons in 4 and it’s a minor pain to figure out parsing the new folder structure :confused:

This should probably not be an error, also - it’s too easy to refer to something that isn’t there? I’ll probably chance so it gives you a warning and a silent icon.

1 Like

Well, it got passed the initClass problems now with 3.0.2 icons. I haven’t tested anything else yet.

Well I couldn’t do it like that because your IconSet quark doesn’t show up in the big list of quarks in SC 3.12.1, as I note in my first post in this thread, about the WARNING: IconSet not found. I don’t know why SC can’t find it, when it could and download all other dependencies for NodeSnapshot.

Also, while it seems installed ok now, it isn’t actually working. Using the example from the help after a

Synth(\default) // ->Synth(\default)

(TreeSnapshot.get({
    |snapshot|
    snapshot.postln;
});)
/* 
-> TreeSnapshot
TreeSnapshot
  + Group: 0
*/

Doesn’t seem to see any synths. If do ctrl+T they do show up in the standard way

NODE TREE Group 0
   1 group
      1007 default

I thought maybe it just doesn’t see the \default one, but this also shows no synths:

SynthDef(\egg, { 0.1 * Out.ar(0, SinOsc.ar()) }).add

Synth(\egg)

(TreeSnapshot.get({
    |snapshot|
    snapshot.postln;
});)
/*
-> Synth(\egg : 1009)
-> TreeSnapshot
TreeSnapshot
  + Group: 0
*/

On the other hand

(
TreeSnapshotView().front.autoUpdate();
)

does see it in its gui, so I guess help page example for TreeSnapshot might be bad or I misunderstood it.

Further if I try playing the more complex example from TreeSnapshotView’s help, I get a gzillion of errors like

ERROR: Message 'isSymbol' not understood.
Perhaps you misspelled 'asSymbol', or meant to call 'isSymbol' on another receiver?
RECEIVER:
   Float 0.000000   00000000 00000000
ARGS:

PROTECTED CALL STACK:
	Meta_MethodError:new	000001BE7693B240
		arg this = DoesNotUnderstandError
		arg what = nil
		arg receiver = 0.0
	Meta_DoesNotUnderstandError:new	000001BE7693D580
		arg this = DoesNotUnderstandError
		arg receiver = 0.0
		arg selector = isSymbol
		arg args = [  ]
	Object:doesNotUnderstand	000001BE766C5D80
		arg this = 0.0
		arg selector = isSymbol
		arg args = nil
	a FunctionDef	000001BE78D2B580
		sourceCode = "{

				|v|

				(v.isSymbol || v.isString) and: { v.isMap }

			}"
		arg v = 0.0
	a FunctionDef	000001BE7A7B4980
		sourceCode = "<an open Function>"
		arg elem = 0.0
		arg i = 0
	ArrayedCollection:do	000001BE7A861D40
		arg this = [ 0.0 ]
		arg function = a Function
		var i = 0
	Collection:selectAs	000001BE7A7B45C0
		arg this = [ 0.0 ]
		arg function = a Function
		arg class = Array
		var res = [  ]
	a FunctionDef	000001BE78D2B100
		sourceCode = "<an open Function>"
		arg key = out
		arg value = [ 0.0 ]
		var mapped = nil
	Dictionary:keysValuesArrayDo	000001BE7A9B1640
		arg this = IdentityDictionary[ (out -> 0.0), (amp -> 0.10000000149012), (freq -> 261.62557983398), (filter -> 3.0) ]
		arg argArray = [ out, 0.0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, amp, 0.10000000149012, nil, nil, nil, nil, nil, nil, freq, 261.62557983398, nil, nil, nil, nil, nil, nil, nil, nil, filter, 3.0 ]
		arg function = a Function
		var i = 0
		var j = 1
		var key = nil
		var val = nil
		var arraySize = nil
	Dictionary:keysValuesDo	000001BE7A9A4400
		arg this = IdentityDictionary[ (out -> 0.0), (amp -> 0.10000000149012), (freq -> 261.62557983398), (filter -> 3.0) ]
		arg function = a Function
	SynthSnapshot:prMappedInputs	000001BE78D2AC80
		arg this = + Synth(1016): buzzs
		var result = nil
		var mappings = Set[  ]
	SynthSnapshot:inputs	000001BE78D29B00
		arg this = + Synth(1016): buzzs
	SynthSnapshotView:makeSynthInOutputs	000001BE7690DC00
		arg this = a SynthSnapshotView
		arg synth = + Synth(1016): buzzs
		arg parent = a View
		var oldInOuts = Dictionary[  ]
		var oldView = nil
		var newView = nil
		var layout = a VLayout
		var sortFunc = a Function
	SynthSnapshotView:set	000001BE7690BB00
		arg this = a SynthSnapshotView
		arg newSynth = + Synth(1016): buzzs
		var toRemove = nil
		var toAdd = nil
		var newIO = nil
	TreeSnapshotView:makeViewNode	000001BE788A5E00
		arg this = TreeSnapshotView('default')
		arg node = + Synth(1016): buzzs
		arg args = nil
		var viewObj = [  ]
	a FunctionDef	000001BE7A7B4080
		sourceCode = "<an open Function>"
		arg elem = + Synth(1016): buzzs
		arg i = 0
	ArrayedCollection:do	000001BE7A861D40
		arg this = [ a SynthSnapshot, a SynthSnapshot, a SynthSnapshot, a SynthSnapshot ]
		arg function = a Function
		var i = 0
	List:do	000001BE7A7F96C0
		arg this = List[ a SynthSnapshot, a SynthSnapshot, a SynthSnapshot, a SynthSnapshot ]
		arg function = a Function
	Collection:collectAs	000001BE7A7B3CC0
		arg this = List[ a SynthSnapshot, a SynthSnapshot, a SynthSnapshot, a SynthSnapshot ]
		arg function = a Function
		arg class = Array
		var res = [  ]
	a FunctionDef	000001BE788A9100
		sourceCode = "<an open Function>"
		var views = nil
		var layout = a VLayout
	TreeSnapshotView:populateViewGroup	000001BE788A8100
		arg this = TreeSnapshotView('default')
		arg gsv = a GroupSnapshotView
	TreeSnapshotView:makeViewNode	000001BE788A5E00
		arg this = TreeSnapshotView('default')
		arg node = + Group: 1011
		arg args = nil
		var viewObj = [  ]
	a FunctionDef	000001BE7A7B4080
		sourceCode = "<an open Function>"
		arg elem = + Group: 1011
		arg i = 0
	ArrayedCollection:do	000001BE7A861D40
		arg this = [ a GroupSnapshot ]
		arg function = a Function
		var i = 0
	List:do	000001BE7A7F96C0
		arg this = List[ a GroupSnapshot ]
		arg function = a Function
	Collection:collectAs	000001BE7A7B3CC0
		arg this = List[ a GroupSnapshot ]
		arg function = a Function
		arg class = Array
		var res = [  ]
	a FunctionDef	000001BE788A9100
		sourceCode = "<an open Function>"
		var views = nil
		var layout = a VLayout
	TreeSnapshotView:populateViewGroup	000001BE788A8100
		arg this = TreeSnapshotView('default')
		arg gsv = a GroupSnapshotView
	TreeSnapshotView:makeViewNode	000001BE788A5E00
		arg this = TreeSnapshotView('default')
		arg node = + Group: 1
		arg args = nil
		var viewObj = [  ]
	a FunctionDef	000001BE7A7B4080
		sourceCode = "<an open Function>"
		arg elem = + Group: 1
		arg i = 0
	ArrayedCollection:do	000001BE7A861D40
		arg this = [ a GroupSnapshot ]
		arg function = a Function
		var i = 0
	List:do	000001BE7A7F96C0
		arg this = List[ a GroupSnapshot ]
		arg function = a Function
	Collection:collectAs	000001BE7A7B3CC0
		arg this = List[ a GroupSnapshot ]
		arg function = a Function
		arg class = Array
		var res = [  ]
	a FunctionDef	000001BE788A9100
		sourceCode = "<an open Function>"
		var views = nil
		var layout = a VLayout
	TreeSnapshotView:populateViewGroup	000001BE788A8100
		arg this = TreeSnapshotView('default')
		arg gsv = a GroupSnapshotView
	TreeSnapshotView:makeViewNode	000001BE788A5E00
		arg this = TreeSnapshotView('default')
		arg node = + Group: 0
		arg args = nil
		var viewObj = [  ]
	TreeSnapshotView:update	000001BE788BB5C0
		arg this = TreeSnapshotView('default')
		arg newSnapshot = TreeSnapshot
  + Group: 0
		var oldViews = IdentitySet[  ]
	a FunctionDef	000001BE7308A540
		sourceCode = "<an open Function>"
	a FunctionDef	000001BE78D4BE00
		sourceCode = "<an open Function>"
	Function:prTry	000001BE7308D940
		arg this = a Function
		var result = nil
		var thread = a Thread
		var next = nil
		var wasInProtectedFunc = false

But the sound is ok, so I guess the problem is with TreeSnapshotView. It seems pretty wierd because something like 0.2.asSymbol surely does work. Ah, ok, you’re calling something like 0.0.isSymbol which errors in my SC. I guess it’s an issue like with the paths, that you probably have some convenience extensions for these methods.

The isSymbol dependency crept in through a very common quark a while ago - I fixed this locally, but only just pushed the change. If you update this should be resolved.

When you postln a TreeSnapshot or it’s nodes, it doesn’t recursively show everything contained in them. This USED to be the behavior, but in most normal use-cases (e.g. when you’re playing a bunch of Synths), this stretches to 20, 30, 40, 100 lines in the post window, which is extremely disruptive and can for example ruin stack traces.

You can use TreeSnapshot:nodeOrder to fetch all nodes recursively (a depth-first traversal, so the order is consistent with the order they would be executed on the server:

(
TreeSnapshot.get({
	|sn|
	sn.nodeOrder.do(_.postln)
})
)

GroupSnapshots also can behave like a Stream, where they yield their child nodes recursively and in order:

(
TreeSnapshot.get({
	|sn|
	var nodes = sn.root.asStream;
	var node;
	while { (node = nodes.next).notNil } {
		node.postln
	}
})
)
1 Like

Thank you for the rapid turnaround time. I really appreciate it!

By the way, since you’ve done all that introspection business in TreeSnapshot, have you also done or considered doing the equivalent of NdefGui but for a plain Synth that’s running on the server? The info collected by TreeSnapshot seems enough to construct a NodeMap with parameters etc.

I’m guessing the answer is yes, since you’ve written ControlValueEnvir which seems to be some kind of attempt to control all things with an envir and it has connectToSynthArgs, but I’m rather unclear how to use it.

Past the isSymbol stuff, TreeSnapshotView still errors very simple use. Probably because it depends on the AverageOutput plug-in installed.

Synth(\default)
TreeSnapshotView().front.autoUpdate();

Clicking on a few knobs which now I can see

image

Gives this

Auto-added new SynthDef stethoscope0
Auto-added new SynthDef stethoscope1
Execution warning: Class 'AverageOutput' not found
ERROR: Message 'ar' not understood.
RECEIVER:
   nil
ARGS:
Instance of Array {    (000001DCD40A8338, gc=88, fmt=01, flg=00, set=02)
  indexed slots [2]
      0 : instance of OutputProxy (000001DCD3A20358, size=11, set=4)
      1 : instance of OutputProxy (000001DCD3A62AD8, size=11, set=4)
}
Instance of Impulse {    (000001DCD254F2F8, gc=88, fmt=00, flg=00, set=03)
  instance variables [8]
    synthDef : instance of SynthDef (000001DCD33543B8, size=16, set=4)
    inputs : instance of Array (000001DCD3DB14B8, size=2, set=2)
    rate : Symbol 'audio'
    synthIndex : Integer 2
    specialIndex : Integer 0
    antecedents : nil
    descendants : nil
    widthFirstAntecedents : nil
}

PROTECTED CALL STACK:
	Meta_MethodError:new	000001DCCEAD2E00
		arg this = DoesNotUnderstandError
		arg what = nil
		arg receiver = nil
	Meta_DoesNotUnderstandError:new	000001DCCEAD5140
		arg this = DoesNotUnderstandError
		arg receiver = nil
		arg selector = ar
		arg args = [ [ an OutputProxy, an OutputProxy ], an Impulse ]
	Object:doesNotUnderstand	000001DCCE373000
		arg this = nil
		arg selector = ar
		arg args = nil
	a FunctionDef	000001DCD1464C40
		sourceCode = "{

			|values, reset|

			var rateSym;

			var min, max, avg;



			rateSym = if(values.rate == \\audio, \\ar, \\kr);



			min = RunningMin.perform(rateSym, values, reset);

			max = RunningMax.perform(rateSym, values, reset);

			avg = AverageOutput.perform(rateSym, values, reset);



			[avg, min, max];

		}"
		arg values = [ an OutputProxy, an OutputProxy ]
		arg reset = an Impulse
		var rateSym = ar
		var min = [ a RunningMin, a RunningMin ]
		var max = [ a RunningMax, a RunningMax ]
		var avg = nil
	SynthDef:buildUgenGraph	000001DCD1C17040
		arg this = SynthDef:SignalStatsUpdater_-1168411923
		arg func = a Function
		arg rates = nil
		arg prependArgs = [ [ an OutputProxy, an OutputProxy ], an Impulse ]
		var result = nil
		var saveControlNames = nil
		var controlProxies = [  ]
	a FunctionDef	000001DCD1468300
		sourceCode = "<an open Function>"
		var rateSymbol = nil
		var trigger = an Impulse
		var input = [ an OutputProxy, an OutputProxy ]
		var values = nil
	SynthDef:buildUgenGraph	000001DCD1C17040
		arg this = SynthDef:SignalStatsUpdater_-1168411923
		arg func = a Function
		arg rates = nil
		arg prependArgs = [  ]
		var result = nil
		var saveControlNames = nil
		var controlProxies = [  ]
	a FunctionDef	000001DCD1C15500
		sourceCode = "<an open Function>"
	Function:prTry	000001DCD0A02500
		arg this = a Function
		var result = nil
		var thread = a Thread
		var next = nil
		var wasInProtectedFunc = false
	
CALL STACK:
	DoesNotUnderstandError:reportError
		arg this = <instance of DoesNotUnderstandError>
	Nil:handleError
		arg this = nil
		arg error = <instance of DoesNotUnderstandError>
	Thread:handleError
		arg this = <instance of Thread>
		arg error = <instance of DoesNotUnderstandError>
	Object:throw
		arg this = <instance of DoesNotUnderstandError>
	Function:protect
		arg this = <instance of Function>
		arg handler = <instance of Function>
		var result = <instance of DoesNotUnderstandError>
	SynthDef:build
		arg this = <instance of SynthDef>
		arg ugenGraphFunc = <instance of Function>
		arg rates = nil
		arg prependArgs = nil
	OSCReplyUpdater:updateSynthDef
		arg this = <instance of SignalStatsUpdater>
	SignalStatsUpdater:inputFunc_
		arg this = <instance of SignalStatsUpdater>
		arg func = <instance of Function>
	Meta_SignalStatsUpdater:new
		arg this = <instance of Meta_SignalStatsUpdater>
		arg inputFunc = <instance of Function>
		arg statsFunc = <instance of Function>
		arg rate = 1
		arg target = <instance of Node>
		arg addAction = 'addAfter'
	SynthOutputDisplay:init
		arg this = <instance of SynthOutputDisplay>
		arg bus = <instance of Bus>
		arg inputType = <instance of Meta_OffsetOut>
		arg node = <instance of Node>
		arg addAction = 'addAfter'
		var parent = nil
		var minView = nil
		var maxView = nil
		var avgView = nil
		var baseString = nil
		var min = 99999
		var max = -99999
		var rateMethod = 'ar'
	Meta_SynthOutputDisplay:newWindow
		arg this = <instance of Meta_SynthOutputDisplay>
		arg parent = nil
		arg bounds = <instance of Rect>
		arg bus = <instance of Bus>
		arg inputType = <instance of Meta_OffsetOut>
		arg node = <instance of Node>
		arg addAction = 'addAfter'
		var wind = <instance of Window>
		var self = nil
	< FunctionDef in Method View:attachHoverScope >
		arg v = <instance of StaticText>
		arg x = 23
		arg y = 8
		var origin = <instance of Point>
		var winBounds = nil
		var disp = nil
		var bus = <instance of Bus>
		var actualSize = <instance of Point>
		var focused = <instance of UserView>
		var rate = nil
		var index = nil
		var numChannels = nil
		var type = <instance of Meta_OffsetOut>
	View:mouseDownEvent
		arg this = <instance of StaticText>
		arg x = 23
		arg y = 8
		arg modifiers = 0
		arg buttonNumber = 0
		arg clickCount = 1
^^ ERROR: Message 'ar' not understood.
RECEIVER: nil

I guess I need to have the AverageOutput plug-in installed.

Ok, I got that one (it’s in RFWUGens.scx)

Now it needs ArrayMax

Auto-added new SynthDef stethoscope0
Auto-added new SynthDef stethoscope1
Auto-added new SynthDef SignalStatsUpdater_873611252
Execution warning: Class 'ArrayMax' not found
ERROR: Message 'ar' not understood.

I guess it’s working now, I can see a pretty scope when I keep the mouse down on the out-thingy. I’m not sure if it’s not missing anything in the window though; there’s a lot of empty space in the screenshot above.

By the way, if anyone else cares about this: the TreeSnapshot part can be cleanly separated from the gui part by just taking the first 400 lines or so of NodeSnapshot.sc, up to and including the TreeSnapshot class but not the TreeSnapshotView and what follows. It turns out Scott has written that first part with no dependencies whatsoever on other quarks, his own or anybody else’s. :smiley: That part doesn’t include the validator though, which is at the end of the file.

17 posts were split to a new topic: Deep dive into threading, blocking, sync/async, scheduler internals (split from scztt quarks thread)