[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[sc-dev] bad or missing line breaks in class library



I've seen many files with weird formatting because of line breaks that are either missing or incorrectly coded. So I just wrote a little code snippet to find them. Results are attached.

Specifically I was looking for lines with non-whitespace, followed by anything, followed by tab and close-brace, to match things like this:

Pdfsm : ListPattern {
var >startState;
*new { arg list, startState=0, repeats=1;
^super.new( list, repeats ).startState_(startState) }

... huh? Where'd the closing brace for *new go? Oh, it's tacked onto the end of the previous line.

But it ended up finding a lot of files where dozens of lines are read in as one line. Why a problem? It makes grep really nasty to use on some parts of the classlib.

If there are no objections, I'll try to figure out a way to fix them automatically. Thought I would ask because some of the most-affected files are in JITLib and crucial.

Thanks.
hjh

./SCClassLibrary/Common/Audio/Demand.sc:
77:  		inputs.do { |in| if(in.rate == \audio) { in <! 0 } };	}

./SCClassLibrary/Common/Audio/Noise.sc:
74: 	}	*ar { arg lo = 0, hi = 127, trig = 0.0;		^this.multiNew('audio', lo, hi, trig)	}

./SCClassLibrary/Common/Collections/ArrayedCollection.sc:
272: 		//			},{ false });
273: 		//		});

./SCClassLibrary/Common/Collections/SequenceableCollection.sc:
502: 	// supports a variation of Mikael Laurson's rhythm list RTM-notation.
	convertRhythm {
		var list, tie;
		list = List.new;
		tie = this.convertOneRhythm(list);
		if (tie > 0.0, { list.add(tie) });  // check for tie at end of rhythm
		^list
	}
	sumRhythmDivisions {
		var sum = 0;
		this.do {|beats|
			sum = sum + abs(if (beats.isSequenceableCollection) {
				beats[0];
			}{
				beats
			});
		};
		^sum
	}
	convertOneRhythm { arg list, tie = 0.0, stretch = 1.0;
		var beats, divisions, repeats;
		#beats, divisions, repeats = this;
		repeats = repeats ? 1;
		stretch = stretch * beats / divisions.sumRhythmDivisions;
		repeats.do({
			divisions.do { |val|
				if (val.isSequenceableCollection) {
					tie = val.convertOneRhythm(list, tie, stretch)
				}{
					
					val = val * stretch;
					if (val > 0.0) {
						list.add(val + tie);
						tie = 0.0;
					}{
						tie = tie - val
					};
				};
			};
		});
		^tie
	}

./SCClassLibrary/Common/Control/Bus.sc:
123: 	printOn { arg stream;
		stream << this.class.name << "(" <<*
			[rate, index, numChannels, server]  <<")"
	}

./SCClassLibrary/Common/Control/Node.sc:
193: 	hash {  ^server.hash bitXor: nodeID.hash	}

./SCClassLibrary/Common/Control/WII.sc:
252: 		//		}).play;

./SCClassLibrary/Common/Control/asDefName.sc:
5: 	asDefName {	^name	}

./SCClassLibrary/Common/Files/Help.sc:
595: *categories {	^ nil	}

./SCClassLibrary/Common/GUI/osx/Base/SCCocoaView.sc:
6: 		mouseUpAction.value(this, x, y, modifiers, buttonNumber, clickCount, clickPos);	}

./SCClassLibrary/Common/GUI/osx/Base/SCView.sc:
1244: 	defaultCanReceiveDrag { ^true;	}
1271: 			this.setProperty(\clearDrawing);	}
1279: 		this.setProperty(\clearOnRefresh, bool);			}
1283: 		this.setProperty(\relativeOrigin, bool);			}	
1357: 	mouseTrack { arg x, y, modifiers; 	}
1524: 	mouseTrack { arg x, y, modifiers; 	}

./SCClassLibrary/Common/Math/SimpleNumber.sc:
302: 			Error("SimpleNumber-writeInputSpec constant not found: " ++ this.asFloat).throw;		};

./SCClassLibrary/Common/Streams/ListPatterns.sc:
174: 		^super.new( list, repeats ).startState_(startState)	}

./SCClassLibrary/Common/Streams/Patterns.sc:
504: 			inval = ((table.tableRand * (hiVal - loVal)) + loVal).yield;		};

./SCClassLibrary/Common/Streams/Ppar.sc:
141: 	numberOfGroups { ^list.size	}

./SCClassLibrary/Common/Streams/TabFileReader.sc:
60: 		^this.read(path, skipEmptyLines, skipBlanks, _.interpret, delimiter, startRow, skipSize )	}

./SCClassLibrary/JITLib/Patterns/Pdef.sc:
346: 			if(this.isPlaying) { this.play(quant:playQuant) }	}

./SCClassLibrary/JITLib/ProxySpace/NodeProxy.sc:
62: 								this.class.defaultNumControl							}
396: 					list.do { |item, i| this.put(i + index, item, channelOffset.wrapAt(i)) }				}

./SCClassLibrary/JITLib/ProxySpace/extStoreOn.sc:
37: 		try { doc.bounds_(bounds) };	// swingosc safe
	}
}

./SCClassLibrary/JITLib/ProxySpace/wrapForNodeProxy.sc:
259: 					XOut.kr(out, e, SynthDef.wrap(func, nil, [In.kr(out, proxy.numChannels)]))				};

./SCClassLibrary/JITLib/extras/History.sc:
166: 			[lines, lineShorts].do(_.removeAt(index));		};

./SCClassLibrary/JITLib/extras/NodeProxyEditor.sc:
6: 	
	*new { arg proxy, pxKey, nSliders=16, win, comp, 
		extras=[\scope, \doc, \reset], monitor=true, sinks=true, morph=false; 
		^super.new.nSliders_(nSliders).init(win, comp, extras, monitor, sinks, morph)
			.pxKey_(pxKey).proxy_(proxy);
	}

	proxy_ { arg px; 
		if (px.isKindOf(NodeProxy), { 
			proxy = px;
			editNameView.object_(px.source);
			editNameView.string_(px.key.asString);
			oldNodeMap = proxy.nodeMap;
			if (monitor.notNil) { monitor.proxy_(proxy) };
			this.fullUpdate;
		})
	}
	pxKey_ { arg key; 
		if (key.notNil, {  
			pxKey = key; 
			{ editNameView.string_(pxKey.asString);  }.defer;
		})
	}

7: 
	clear {
		proxy = nil; 
		pxKey = nil; 
		{ editNameView.object_(nil).string_(""); }.defer;
		this.fullUpdate;
	}
	
	init { arg win, comp, extras, monitor, sinks, morph;
				
		var bounds;				
		skin = GUI.skin; 		
		font = GUI.font.new(*GUI.skin.fontSpecs);		
		bounds = Rect(0, 0, 370, nSliders + 2 * skin.buttonHeight + 16);		
		win = win ?? { "NodeProxyEditor: making internal win".postln; 
13: 		
		this.makeTopLine(extras);
		if (monitor, { this.makePxMon; zone.decorator.nextLine.shift(0, 4); });
		if (morph, { this.makeMorph; zone.decorator.nextLine.shift(0, 4); });

		this.makeSinksSliders(sinks);
		this.makeSkipJack; 
	}
	makePxMon { 
		monitor = ProxyMonitorGui(proxy, zone, skin.buttonHeight, true, false);
	}

	makeMorph { 
		zone.decorator.shift(0, 2);
		GUI.staticText.new(zone, Rect(0,0, 330, 1)).background_(Color.gray(0.2));
		zone.decorator.shift(0, 2);
		PxPreset(proxy, zone) 
	}
	
	makeTopLine { |extras|
		editNameView = GUI.dragSource.new(zone, Rect(0,0,90, skin.buttonHeight))
			.font_(font).align_(\center)
			.background_(Color.white);
		
		GUI.button.new(zone, Rect(0,0,40, menuHeight)).states_([
				["watch",  skin.fontcolor, Color.clear ],
				["wait",  skin.fontcolor, Color.clear ]
			])
			.action_({ |b| [ { this.stopUpdate }, { this.runUpdate } ][b.value].value })
			.font_(font);

		GUI.button.new(zone, Rect(0, 0, 20, menuHeight))
				.font_(font)
				.states_([ ["^", skin.fontcolor, Color.clear] ])
				.action_({  this.class.new(proxy, pxKey, nSliders); });
				
		if (extras.includes(\scope)) {
			GUI.button.new(zone, Rect(0,0,40, menuHeight))
				.font_(font)
				.states_([["scope", skin.fontcolor, Color.clear]])
				.action_({ arg btn; if(proxy.notNil, { proxy.scope }) });
		};
						
		if (extras.includes(\reset)) {
			GUI.button.new(zone, Rect(0,0,40, menuHeight))
				.states_([["reset",  skin.fontcolor, Color.clear ]])
				.action_({ 
					if(proxy.notNil) { proxy.nodeMap = ProxyNodeMap.new; this.fullUpdate; } 
				})
				.font_(font);
		};
		if (extras.includes(\doc)) {
			GUI.button.new(zone, Rect(0,0,40, menuHeight))
				.states_([["doc",  skin.fontcolor, Color.clear ]])
				.action_({ 
					if(proxy.notNil and: currentEnvironment.isKindOf(ProxySpace)) { 
						currentEnvironment.document(proxy.key)
							.title_("<" + proxy.key.asString + ">") 
					} {
15: 					}
				})
				.font_(font);
		};
20: 		
		sinkWidth = if (bigSinks, 40, 0); 	// invisibly small
		#edits, sinks = Array.fill(nSliders, { arg i;
			var ez, sink;
			zone.decorator.nextLine; 

			sink = GUI.dragBoth.new(zone, Rect(0,0, sinkWidth, skin.buttonHeight))
				.string_("-").align_(\center).visible_(false);
				
			sink.action_({ arg sink; var px;
				if (sink.object.notNil) { 
					px = currentEnvironment[sink.object.asSymbol];
					if(px.isKindOf(NodeProxy)) {
						proxy.map(editKeys[i], px);
						this.fullUpdate;
					}
				}
			}); 

			ez = GUI.ezSlider.new(zone, 290 @  skin.buttonHeight, "", nil.asSpec, 				labelWidth: 60, numberWidth: 42);
			ez.labelView.font_(font).align_(\center);
21: 			[ez, sink]
		}).flop;

32: 	}
	
	makeSkipJack {
		skipjack = SkipJack(
			{ this.checkUpdate }, 
			0.2, 
			{ w.isClosed }, 
			this.class.name
		); 
		w.onClose_({ skipjack.stop; });
		this.runUpdate;
	}

	getCurrentKeysValues {  
		if (proxy.isNil, {^[] });
		currentSettings = proxy.getKeysValues(except: ignoreKeys);
		editKeys = currentSettings.collect({ |list| list.first.asSymbol }); 
	}

	checkUpdate { 
		var oldKeys; 
		oldKeys = editKeys; 
		this.getCurrentKeysValues; 
		if (monitor.notNil) { monitor.updateAll }; 
		if ( (editKeys != oldKeys), { this.updateAllEdits }, {  this.updateVals });
	}
	
	fullUpdate { 
		this.getCurrentKeysValues; 
		this.updateAllEdits;
	}
	
	updateVals {
		var sl, val, mapKey;
45: 			if (val != try { prevSettings[i][1] }) {	 
				// when in doubt, use this:
				//	val = (currentSettings.detect { |set| set[0] == key } ? [])[1];
				if(sl.numberView.hasFocus.not) {
					if (val.isKindOf(SimpleNumber), { 						
						sl.value_(val.value);
						sl.labelView.string_(this.replaceName(key));
						sinks[i].string_("-");
					}, { 
						if (val.isKindOf(BusPlug), { 
							mapKey = currentEnvironment.findKeyForValue(val) ? "";
							sinks[i].object_(mapKey).string_(mapKey);
							sl.labelView.string = "->" + key;
						});
					});
				};
46: 			};
		};
47: 		prevSettings = currentSettings; 
	}
	replaceName { |key| 
140: 	}
	
	runUpdate {  skipjack.start }
	stopUpdate { skipjack.stop }
}



RecordProxyMixer {
	var <>proxymixer, bounds;
	var <recorder, <recType=\mix;
	var <>recHeaderFormat, <>recSampleFormat, <preparedForRecording=false;
	var skipjack, <display;
	
	*new { arg proxymixer, bounds; 
		^super.newCopyArgs(proxymixer, bounds).initDefaults.makeWindow
	}
	initDefaults {
		recHeaderFormat = recHeaderFormat ?? { this.server.recHeaderFormat };
		recSampleFormat = recSampleFormat ?? { this.server.recSampleFormat };
	}
	
	prepareForRecord {
		var numChannels=0, path, proxies, func;
		proxies = this.selectedKeys.collect { arg key; this.at(key) };
		if(proxies.isEmpty) { "NodeProxyEditor: no proxies.".postln; ^nil };
		
		
		if(recType == \multichannel)  {
			proxies.do {  |el| numChannels = numChannels + el.numChannels };
			func = { proxies.collect(_.ar).flat }; // no vol for now!
		} {
			proxies.do {  |el| numChannels = max(numChannels, el.numChannels) };
			func = { var sum=0;
				proxies.do { |el| sum = sum +.s el.ar };
				sum 
			}
		};
		
		path = thisProcess.platform.recordingsDir +/+ "SC_PX_" ++ numChannels ++ "_" ++ Date.localtime.stamp ++ "." ++ recHeaderFormat;
		recorder = RecNodeProxy.audio(this.server, numChannels);
		recorder.source = func;
		recorder.open(path, recHeaderFormat, recSampleFormat);
		preparedForRecording = true;
		^numChannels
	}
	
	font { ^GUI.font.new(*GUI.skin.fontSpecs) }
	skin { ^GUI.skin }
	
	server { ^proxymixer.proxyspace.server }
	
	removeRecorder {
		recorder !? {
			recorder.close;
			recorder.clear;
			recorder = nil;
		};
		preparedForRecording = false;
	}
	
	record { arg paused=false;
		if(recorder.notNil) {recorder.record(paused) };
	}
	
	pauseRecorder { recorder !? {recorder.pause} }
	unpauseRecorder { 
		recorder !? { if(recorder.isRecording) { recorder.unpause } { "not recording".postln } } 
	}
	
	selectedKeys {  ^proxymixer.selectedKeys }
	at { arg key; ^proxymixer.proxyspace.envir.at(key) }
	selectedKeysValues {
		^this.selectedKeys.collect { |key| 
					var proxy = this.at(key);
					[ key, proxy.numChannels ]
		}.flat;
	}
	
	makeWindow {
		var rw, recbut, pbut, numChannels, recTypeChoice;
		var font = this.font;
		
		rw = GUI.window.new("recording:" + proxymixer.title, bounds);
		rw.view.decorator = FlowLayout(rw.view.bounds.insetBy(20, 20));
		rw.onClose = { this.removeRecorder; this.stopUpdate; };
		rw.view.background = this.skin.background;	
			
		recbut = GUI.button.new(rw, Rect(0, 0, 80, 20)).states_([
			["prepare rec", this.skin.fontcolor, Color.clear],
			["record >", Color.red, Color.gray(0.1)],
			["stop []", this.skin.fontcolor, Color.red]
		]).action_({|b|
			var list;
			switch(b.value,
				1, { 
					numChannels = this.prepareForRecord;
					if(numChannels.isNil) { b.value = 0; pbut.value = 0 } 
				},
				2, { this.record(pbut.value == 1) },
				0, { this.removeRecorder  }
			);
			if(b.value == 1 and: { numChannels.notNil }) {
				list = this.selectedKeysValues;
				this.displayString = format("recording % channels: %", numChannels, list.join(" "));
			};
			
		}).font_(font);
		
		pbut = GUI.button.new(rw, Rect(0, 0, 80, 20)).states_([
			["pause", this.skin.fontcolor, Color.clear],
			[">", Color.red, Color.gray(0.1)]
		]).action_({|b|
			if(b.value == 1) {  this.pauseRecorder } { this.unpauseRecorder }
		
		}).font_(font);
		
		recTypeChoice = GUI.popUpMenu.new(rw, Rect(0, 0, 110, 20))
				.items_([ \mix, \multichannel ])
				.action_({ arg view; 
					recType = view.items[view.value]; 
					if(recbut.value != 0) { recbut.valueAction = 0 } 
				})
				.font_(font);
		recTypeChoice.value = 1;
		GUI.button.new(rw, Rect(0, 0, 60, 20))
				.states_([["cancel", this.skin.fontcolor, Color.clear]])
				.action_({ if(recbut.value != 0) { recbut.valueAction = 0 } })
				.font_(font);

	
		rw.view.decorator.nextLine;
		display = GUI.staticText.new(rw, Rect(30, 40, 300, 20)).font_(font);
		rw.front;
		this.makeSkipJack;
		this.runUpdate;
		
		^rw
	}

	displayString_ { arg str;
		display.string = str;
	}
	
	updateZones {
		if(preparedForRecording.not) {
			this.displayStrin
141: g = format("proxies: %", this.selectedKeysValues.join(" "));
		}
	}

	title {  ^"recorder for" + proxymixer.title }

	runUpdate { skipjack.start; }
	stopUpdate { skipjack.stop }
	makeSkipJack {				// stoptest should check window.
		skipjack = SkipJack({ this.updateZones }, 0.5, name: this.title);
	}
}



./SCClassLibrary/JITLib/extras/ProxyMixer.sc:
4: 	
	*new { arg proxyspace, nProxies = 16, title, bounds;
		^super.new.init(proxyspace, nProxies, 
			title ?? { format("proxyspace: %", proxyspace.tryPerform(\name) ? "") }, bounds
		);
	}
	
	init { arg space, nPxs = 16, argTitle, argBounds; 
		
		var winHeight, globalLayout, height, color;
		skin = GUI.skin; 
9: 			.background_(skin.foreground);
	
		compArZone.decorator = FlowLayout(compArZone.bounds).gap_(skin.gap);
		compKrZone.decorator = FlowLayout(compKrZone.bounds).gap_(skin.gap);
		compEditZone.decorator = FlowLayout(compEditZone.bounds).gap_(skin.gap);
		
		this.makeArZone; 
		this.makeKrZone; 
		this.makeEditZone; 
		
		w.front; 

		this.makeSkipJack;
		w.onClose_({ this.stopUpdate }); 
		this.runUpdate;
		
	}
		
	runUpdate { editor.runUpdate; skippy.start; }
	stopUpdate { editor.stopUpdate; skippy.stop }
		
	makeWindow {
		w = GUI.window.new(this.title, origBounds);
		w.view.background = skin.background;
		
	}
	makeSkipJack { 
		skippy = SkipJack({ this.updateZones }, 0.2, { w.isClosed }, title);
	}
	
	makeEditZone {
		editor = NodeProxyEditor(nil, nil, nProxies - 1, w, compEditZone);
	}

	openEditZone { arg flag;
			if(flag == 1 or: {editZoneOpen.not}) {
				if(editZoneOpen.not) { 
					origBounds = w.bounds;
					w.bounds = w.bounds.setExtent(fullBounds.width, fullBounds.height);
					editZoneOpen = true;
					editZoneBtn.value = 1;
					this.update;
				}
			}{
				w.bounds = w.bounds.setExtent(origBounds.width, origBounds.height);
				editZoneOpen = false; 
				editZoneBtn.value = 0; 
			};
	}


	makeArZoneHead { 
	
		GUI.popUpMenu.new(compArZone,Rect(10, 10, 110, skin.buttonHeight+2))
				.items_([\existingProxies, \activeProxies, \playingProxies])
				.action_({ arg view; selectMethod = view.items[view.value] })
				.font_(font);
				
		GUI.button.new(compArZone, Rect(10, 10, 50, skin.buttonHeight+2))
				.states_(
					[["reduce", skin.fontcolor, Color.clear]]				)
				.action_({ proxyspace.reduce }).font_(font);
		GUI.button.new(compArZone, Rect(10, 10, 30, skin.buttonHeight+2))
				.states_(
					[["doc", skin.fontcolor, Color.clear]]				)
				.action_({ proxyspace.document }).font_(font);
		GUI.button.new(compArZone, Rect(10, 10, 30, skin.buttonHeight+2))
				.states_(
					[["docc", skin.fontcolor, Color.clear]]				)
				.action_({ 
					proxyspace.document(this.selectedKeys)
				}).font_(font);
		/*
		GUI.button.new.new(compArZone, Rect(10, 10, 20, skin.buttonHeight+2)).states_([
				["#",  skin.fontcolor, Color.clear ]
			])
			.action_({ editor.pxKey !? { proxyspace.storeOn(Post, [editor.pxKey]) } })
			.font_(font);
		*/
		editZoneBtn = GUI.button.new(compArZone, Rect(10, 10, 60, skin.buttonHeight+2))
				.font_(font)
				.states_(
					[	["openEdit", skin.fontcolor, Color.clear], 
						["closeEdit", skin.fontcolor, Color.clear]
					]				)
				.action_({ |b| this.openEditZone(b.value) });
		
		GUI.button.new(compArZone, Rect(10, 10, 20, skin.buttonHeight+2))
				.font_(font)
				.states_(
					[	["R", Color.red, Color.clear]					])
				.action_({  RecordProxyMixer(this, origBounds.resizeTo(472, 100)) });
		
	}
	
	makeArZone { 
		var arLayout = compArZone.decorator;
		this.makeArZoneHead;
		
		arLayout.nextLine;
		arLayout.shift(0,4);
		
		#pxMons, editBtnsAr = Array.fill(nProxies, { arg i; 
			var pxmon, edbut;
			pxmon = ProxyMonitorGui(nil, compArZone, skin.buttonHeight, true, false);			pxmon.zone.visible_(false);

		//	arLayout.shift(4); 
			
			edbut = GUI.button.new(compArZone, Rect(0,0,16,16))
				.font_(font)
				.visible_(false)
				.states_([
					["ed", Color.black, Color.grey(0.75)],
					["ed", Color.black, Color.white]])
				.action_({ arg btn;	
					editor.proxy_(pxmon.proxy).pxKey_(pxmon.proxy.key);
					this.openEditZone(1);
					editBtnsAr.do { |b| b.value_(0) };
					editBtnsKr.do { |b| b.value_(0) };
					btn.value_(1);
				});
			arLayout.nextLine;
			[pxmon, edbut]
		}).flop;	
27: 		/*
		GUI.button.new(compKrZone, Rect(0,0,20, skin.buttonHeight))
		.font_(Font("Helvetica-Bold", 12))
		.states_([["+", Color.red, Color.white]])
		.action_({
			if(emergencySynth.isPlaying.not) {
				emergencySynth = Synth.tail(0, "proxymixer_emergency");
				NodeWatcher.register(emergencySynth);
			} {
				emergencySynth.release
			}
		});
		*/
		layout.nextLine;
		layout.nextLine;
		
		buttonLinesKr = Array.fill(nProxies, { arg i;
			var nameBtn, pausBtn, sendBtn, editBtn, pollBtn;
			
			nameBtn = GUI.dragSource.new(compKrZone, Rect(0,0,68, skin.buttonHeight))
			.font_(font)
			.align_(\center);
			
68: 			
			[ nameBtn, pausBtn, sendBtn, editBtn, pollBtn].do({ arg v; v.visible_(false) });
		});
77: 	}

	updateZones {
		this.updateArSlots;	
		this.updateKrSlots; 
	}
	
	updateKrSlots { 
		var krProxyNames;
		krProxyNames = proxyspace.krProxyNames;

94: 				
				showLine = key.notNil and: px.notNil;	
				butLine.do(_.visible_(showLine));
			}
96: 		prevKrNames = krProxyNames;
	}

	existingProxies { ^proxyspace.arProxyNames }
	activeProxies { ^proxyspace.arProxyNames({ |px, key| px.isPlaying }) }
	playingProxies { ^proxyspace.arProxyNames({ |px, key| px.monitor.isPlaying }) }

	selectedKeys { ^this.perform(selectMethod) }
	
	updateArSlots {
		var arPxNames, pxKey, px, pxMon;
		arPxNames = this.selectedKeys;
		
		if (arPxNames.size > nProxies) { 
100: 				
			arPxNames = arPxNames.drop(keysRotationAr).keep(nProxies);
		} {
103: 		
		if (arPxNames != prevArNames) {	 
			nProxies.do { arg i;
				pxMon = pxMons[i]; 
				pxKey = arPxNames[i]; 
				
				px = proxyspace.envir.at(pxKey);
				if(px.notNil) { 
					pxMon.zone.visible_(true);
					editBtnsAr[i].visible_(true);
					pxMon.proxy_(px);
				}{
					pxMon.zone.visible_(false);
					editBtnsAr[i].visible_(false);	
				}
			} 
107: 		prevArNames = arPxNames;
	}
		
	adjustWindowSize { arg n;
		n = n ? nProxies;
		w.bounds = if(editZoneOpen) 
			{ origBounds.resizeBy(0, 330) } 
			{ origBounds.copy.height_(n  * 18 + 80) };
	}
}


./SCClassLibrary/JITLib/extras/ProxyMonitorGui.sc:
1: 	
	*new { |px, w, height=16, usePlayN=true, makeWatcher=true| 
		^super.new.proxy_(px).init(w, height, usePlayN, makeWatcher); 
	}

	init { |w, height, usePlayN, makeWatcher| 
7: 			// swingosc: 16 is normal  24 is alt, ctl is off, and fn is 16 as well
			if(proxy.notNil) {
				[ 	{ 	if ([524576, 24].includes(modif)) { proxy.end } { proxy.stop } }, 
					{ 	proxy.playN; } 
				].at(btn.value).value
			}
		});
		
		setOutBox = GUI.numberBox.new(zone, Rect(0,0,16,height))
			.font_(font).align_(0)
			.action_({ |box, mod| 
				proxy.monitor.out_(box.value.max(0).asInteger);
			}); 
		if (usesPlayN) { 
			playNDialogBut = GUI.button.new(zone, Rect(0,0,20,height))
11: 					box.value_(1 - box.value)
				});
		}; 
		
		pauseBut = GUI.button.new(zone, Rect(0,0,34,height))
13: 			.action_({ arg btn; 
			if(proxy.notNil, {
					[ 	{ proxy.resume; }, { proxy.pause; }  ].at(btn.value).value;
				})
			});
		
		sendBut = GUI.button.new(zone, Rect(0,0,34,height))
16: 					// alt-click osx, swingosc
					if ([524576, 24].includes(mod) ) { proxy.rebuild } { proxy.send }
				};
17: 				btn.value_(1 - btn.value)
			})
18: 			;
	
		if (win.isKindOf(GUI.window)) { win.front };
		if (makeWatcher) { this.makeWatcher };
	}

	makeWatcher { 
		skipjack.stop;
		skipjack = SkipJack({ this.updateAll }, 
			0.5, 
			{ win.isClosed },
			"PxMon" + try { proxy.key }
		);
		skipjack.start;
	}
	
	updateAll { 
		var monitor, outs, amps, newHasSeriesOut;
30: 				playsSpread = proxy.monitor.hasSeriesOuts.not;
				outs = monitor.outs; 
			}); 
58: 		oldState = currState;
	}
	clear { proxy = nil }
}


./SCClassLibrary/crucial/Gui/CXMenu.sc:
18: 			wbounds = Rect(20,20,windowWidth ? buttonWidth + 10,height);		},{

./SCClassLibrary/crucial/KernalTools/AnnotatedDebugNodeWatcher.sc:
32: 		this.doPost("ON ", nodeID, prevID, nextID);	}

./SCClassLibrary/crucial/KernalTools/CXObjectInspector.sc:
182: 		//	},minWidth:width)

./SCClassLibrary/crucial/Players/AbstractPlayer.sc:
525: 	delta { 	^this.beatDuration	}

./SCClassLibrary/crucial/Players/PlayerMixerGui.sc:
0: 
PlayerMixerGui : AbstractPlayerGui {

	guiBody { arg layout;
		this.durationGui(layout);
		model.players.do({ arg pl;
			pl.gui(layout.startRow);	
		});
	}
	
}


./SCClassLibrary/crucial/Players/SimpleTrigger.sc:
10: 	synthArg { ^spec.minval }
	rate { ^\control } 
	addToSynthDef {  arg synthDef,name; 
		synthDef.addTr(name,this.synthArg); 
	} 
	instrArgFromControl { arg control; ^control } 
	makePatchOut { 
		patchOut = UpdatingScalarPatchOut(this,enabled: false); 
	} 
	didStop {

./SCClassLibrary/crucial/Players/SimpleTriggerGui.sc:
0: 
SimpleTriggerGui : AbstractPlayerGui {

	guiBody { arg layout;
		ActionButton(layout,model.name ? "trig",{ model.trig;});
	}

}


./SCClassLibrary/crucial/Players/pathUtilities.sc:
9: 	loadPath { arg warnIfNotFound=true;
		^this.collect { arg obj;
			obj.loadPath(warnIfNotFound)
		}
	}

./SCClassLibrary/crucial/UncoupledUsefulThings/Constraint.sc:
4: 	not {	^Not(this)	}
5: 	or { arg constraint;	^Any([this,constraint])	}

./SCClassLibrary/crucial/UncoupledUsefulThings/ZArchive.sc:
0: 
ZArchive : File {
	
	var stringCache,<>path,<>version=1.0;
	var lastItem,count=0,stringCacheStart;

	*write { arg pathName;
		^super.new(pathName, "wb").path_(pathName).check.initStringCache
	}
	*read { arg pathName;
		^super.new(pathName, "rb").path_(pathName).check
			.getStringCache
	}
	writeItem { arg thing, extraArgs;
		var check;
		// == has some problems
		check = lastItem === thing;

		if(check,{
			count = count + 1;
		},{
			lastItem = thing;
			this.saveCount;
			thing.writeZArchive(this,extraArgs);
		});
	}
	readItem { arg class; // if class not nil, it will assert that the item is of that class
		
		var type,size,thing,classname;
		if(count > 0,{
			count = count - 1;
			^lastItem
		});
		type = this.getChar;
		
		if(type == $.,{ // ... repetition
			count = this.getInt32 - 1;
			^lastItem
		});

		if(type == $N,{
			if(class.notNil and: (Nil !== class),{ 
				die("ZArchive got wrong type:",nil,"expected:",class.asString); 
			});
			^lastItem = nil
		});
		if(type == $F,{
			thing = this.getFloat;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(type == $I,{
			thing = this.getInt32;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(type == $s,{ // small string < 128
			thing = this.readString;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(type == $S,{ // large string
			thing = this.readLargeString;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(type == $y,{ // symbol
			thing = this.readString.asSymbol;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(type == $D,{// dictionaries
			classname = this.readString;
			size = this.getInt32;
			thing = classname.asSymbol.asClass.new(size);
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			size.do({ arg i;
				thing.put(this.readItem,this.readItem);
			});
			^lastItem = thing
		});
		if(type == $C,{ // collection
			classname = this.readString;
			size = this.getInt32;
			thing = classname.asSymbol.asClass.new(size);
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			size.do({ arg i;
				thing.add( this.readItem );
			});
			^lastItem = thing
		});
		if(type == $x,{ // small compile string
			thing = this.readString.interpret;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(type == $X,{ // large compile string
			thing = this.readLargeString.interpret;
			if(class.notNil and: (thing.class !== class),{ 
				die("ZArchive got wrong type:",thing,"expected:",class.asString); 
			});
			^lastItem = thing
		});
		if(this.pos >= (stringCacheStart),{ 
			this.close;
			"End of file, unable to read item".die(this);
		});
		this.close;
		die("ZArchive read error, got bad type code:",type);
	}
	
	writeClose {
		var stringCacheStart;
		this.saveCount;
		stringCacheStart = this.pos;

		// if you do go over the limit, you could simply raise the limit but your old files aren't compatible
		if(stringCache.size >= (2**16),{ 
			"Too many strings in archive !  Not supported.".die; 
		});
		
		this.putInt16(stringCache.size);
		stringCache.keysValuesDo({ |string,index|
			this.putInt16(index);
			this.putInt8(string.size);
			this.putString(string);
		});
		this.putInt32(stringCacheStart);

		this.close;
	}
	
	//PRIVATE
	saveCount {
		if(count > 0,{
			super.putChar($.);
			super.putInt32(count);
			count = 0;
		});
	}
	check { 
		if(this.isOpen.not,{ "Z
1: Archive failed to open".die(path); }); 
	}
	initStringCache { stringCache = Dictionary.new }
	getStringCache {
		var size;
		this.seek(-4,2); // bytes from the end
		stringCacheStart = this.getInt32;
		
		this.seek(stringCacheStart,0);
		size = this.getInt16;
		stringCache = Array.newClear(size);
		size.do({ arg i;
			var index,ssize,string;
			index = this.getInt16;
			ssize = this.getInt8;
			/*if(ssize < 0,{ 
				Error("ZArchive read error.  String table returns negative sized item").throw; 
			});*/
			string = String.newClear(ssize);
			this.read(string);
			stringCache.put( index, string );
		});
		this.seek(0,0);
		
		// the one thing you will never archive is the archiver itself
		// so lastItem starts with this
		lastItem = this;
		// any other item in existence is something you might potentially save next
		// eg. Object, nil
	}
	writeString { arg string;
		var prev;
		prev = stringCache[string];
		if(prev.isNil,{
			prev = stringCache.size;
			stringCache[string] = prev;
		});
		this.putInt16(prev);
	}
	readString {
		var ix,string;
		ix = this.getInt16;
		^stringCache[ix] ?? {"ZArchive failed to find String : index:".die(ix);};
	}
	writeLargeString { arg string;
		this.putInt32(string.size);
		this.putString(string);
	}
	readLargeString {
		var size,string;
		size = this.getInt32;
		string = String.newClear(size);
		this.read(string);
		^string
	}
	asZArchive { ^this }
}
/*
 to detect repeats of dictionaries (or events) and arrays:
  instead of internally using writeItem/readItem, use prWriteItem,prReadItem.
this would break current archives, so you could use a different type code
 for the new ones
*/


./SCClassLibrary/crucial/Crucial.sc:
208: 			Library.at(\menuItems,\tools,'Server Node Report').value;		},minWidth: 250);
211: 			Library.at(\menuItems,\tools,'Annotated Buses Report').value;		},minWidth: 250);
214: 			Library.at(\menuItems,\tools,'listen to audio busses').value;		},minWidth: 250);
221: 			Library.at(\menuItems,\tools,'Annotated Nodes Report').value;		},minWidth: 250);

~top = "./SCClassLibrary/";
~regexp = "[^ \n\r\t].*\t}";
~threaded = true;

(
// depth-first, why not?
~searchDirectory = { |path|
var dirs = (path ++ "*/").pathMatch,
files = (path ++ "*.sc").pathMatch;

dirs.do({ |dir|
~searchDirectory.(dir);
});

files.do({ |file|
~searchFile.(file);
if(~threaded and: { thisThread.isKindOf(Routine) }) { 0.01.wait };
});
};

~searchFile = { |path|
var file = File(path, "r"),
line, lineCount = 0, needToPostPath = true;
if(file.isOpen) {
protect {
while { (line = file.getLine(4096)).notNil } {
if("^//".matchRegexp(line).not and: { ~regexp.matchRegexp(line) }) {
if(needToPostPath) {
"\n%:\n".postf(path);
needToPostPath = false;
};
"%: %\n".postf(lineCount, line);
};
lineCount = lineCount + 1;
};
} {
file.close
};
} {
"Failed to open %. Continuing.".format(path).warn;
};
};
)

// test
~searchFile.(SCView.filenameSymbol.asString);

// run for real
{ ~searchDirectory.(~top); }.fork(AppClock);



: H. James Harkins
.::!:.:.......:.::........:..!.::.::...:..:...:.:.:.:..:

"Come said the Muse,
Sing me a song no poet has yet chanted,
Sing me the universal."  -- Whitman