A Quark or a Plug-in visualising SynthDef

It works here under Debian/Gnu and Apple, I’ve not tried under Microsoft but it should work, if unixCmd and systemCmd work there.

You seem to have it working in Linux (excellent!) & for Apple perhaps see:

If you’ve got Graphviz installed on macOS, you’re in good shape. It tends to play nice and can even pop up right inside editors like Emacs and VSCode with minimal fuss – just install the right packages for your editor. You got Linux already, I see )) Now, Windows, well, that’s where things get a bit mysterious. Honestly, it’s not the go-to choice in this community over here I think.

In viewDotFile:

var viewerDefault = (osx: "open", linux: "dot -Txlib", windows: "/usr/local/bin/dotty");

Windows: A POSIX executable location is unlikely to be successful.

OSX: open depends on filesystem associations. ‘.dot’ is also a MS Word document template, so macOS is probably trying to treat it as a Word doc (hence opening it in Pages).

hjh

1 Like

I have already done what you mentioned, and I have also installed graphviz via MacPorts and via homebrew, but it does not work as you describe. I hope you can find a way to help me if you read my last post carefully. I wrote details of what I did to get your help and to show that it does not work as you describe!

Could you tell me the default software associated with the .dot on MacOS?

Thanks! your screenshot helps me.

On macOS, the ‘.dot’ files are stored in one of the following path:

  • /private/tmp/ when installing ‘Graphviz’ via MacPorts? or on macOS 12.7?
  • Platform.userAppSupportDir +/+ "tmp" when installing ‘Graphviz’ via homebrew or on macOS 13.5.2?

I installed ‘Graphviz Prevew’ for VSCode, and there I can see the image.

I think @rdd was just having a playful jab at the Windows users with that, all in good humor of course)))

Hi @prko,

here a solution suggested to me by Fredrik Olofsson and today updated in his blog . . Fredrik Olofsson Musikproduktion . . f0blog one-reason-why-i-love-sc.

To use the sc3-dot quark in SuperCollider on a mac you’ll need to install graphviz, preferably via macports (sudo port install graphviz) or via homebrew (brew install graphviz).

Then install the quark from within SuperCollider…

Quarks.install("sc3-dot");

add the following lines to your startup.scd file…

Dot.renderMode= 'pdf';
Dot.pdfViewer= "open -a Preview.app";
Dot.dotCmd= "/opt/local/bin/dot";  //macports
//Dot.dotCmd= "/usr/local/bin/dot";  //homebrew

and finally recompile SuperCollider. Now a command like…

{SinOsc.ar}.draw;

should automatically create a .dot file, convert to .pdf and open using Preview.app.

By default you will find the resulting .dot and .pdf files in the ~/Library/Application Support/SuperCollider/tmp directory.

Thanks again Fredrik! :heart:

2 Likes

Awesome. I feel like I have installed this 20 times in the past 20 years and then lose the installation.

BTW - the dot executable may be in a different place on M1 with homebrew. Mine is here:

Dot.dotCmd= "/opt/homebrew/bin/dot";

Sam

@MurbiX and @Sam_Pluta

Thanks!

@rdd
It is suggested that the following steps (or similar to these) be considered for inclusion in the help file, at your discretion. In my experience, the process for letting your quark sc3-dot in modern SC on macOS was longer than in Ubuntu. I apologise if my inquiry comes across as impolite, that was not my intention.

"brew install graphviz".runInTerminal // step 1

Quarks.install("https://gitlab.com/rd--/sc3-dot") // step 2

thisProcess.recompile // step 3

(
Dot.renderMode= 'pdf';
Dot.pdfViewer= "open -a Preview.app";
Dot.dotCmd= "/opt/homebrew/bin/dot";
{SinOsc.ar}.draw
)

(
Dot.renderMode= 'svg';
{SinOsc.ar}.draw
)
1 Like

Yes, ta kindly F0!

I’ve added a link to the MacOS instructions in the Readme.

Hopefully that helps people in the future.

Ps. The windows default probably did (does?) work if you had (have?) Cygwin setup? I don’t really know!

1 Like

Pps. And no, not at all impolite, apologies slow reply!

1 Like

Thanks for this!

I tried to do it in Windows, but I still do not know how to do it. No idea, sorry!

@rdd

I looked into it again over several hours. I’ve found one sure and one suspected reason why it doesn’t work on Windows.

  1. The “\” or "/"is not delivered correctly.
    I found this by modifying .unixCmd with .runInTerminal in line 38:
    sc/Dot.sc · master · r d / sc3-dot · GitLab

  2. The .shellQuote seems to send the filename in single quotes, but the Windows command prompt only accepts double quotes.

Ta kindly for looking! Super happy to accept and fixes you come across, and I’m sorry I can’t be of more help with this…

1 Like

I finally found a way to make scDot work in Windows. Using it on Mac and Linux is now easier!
Please have a look at the following video:
https://www.dropbox.com/scl/fi/4oa5j370danjkunreeusq/Dot-simple.mov?rlkey=msvrr3bzp97icrto0zsdq08b6&dl=0

This is available after revising some method definitions for the Dot class as follows (I just added some preliminary code to skip some steps and added the correct implementation for Windows… It would be great if you could reflect this! I currently only use github… Or I can submit a PR and ask for a merge…):

Dot {

	classvar <>directory, <>dotCmd, <>dotViewer, <>svgViewer, <>pdfViewer, <>renderMode, <>drawInputName, <>useSplines, <>useTables, <>fontSize, <>fontName, <>fixEdgeLocation, <>verbose, <>truncateInputsAt;

	*defaultSettings {
		directory = Platform.defaultTempDir;
		dotCmd = "dot";
		dotViewer = nil;
		svgViewer = nil;
		pdfViewer = nil;
		renderMode = 'dot'; // dot | svg | pdf | hsc3
		drawInputName = false;
		useSplines = false;
		useTables = true;
		fontSize = 10;
		fontName = "Helvetica";
		fixEdgeLocation = false;
		verbose = false;
		truncateInputsAt = 32
	}

	*initClass {
		this.defaultSettings
	}

	*baseFileNameFor { | synthDef |
		^directory.standardizePath +/+ synthDef.name.asString;
	}

	*fileNameForWithExtension { | synthDef extension |
		^Dot.baseFileNameFor(synthDef) ++ extension;
	}

	*asyncCmd { | message command |
		verbose.if {
			["asyncCmd", message, command].postln
		};
		command.unixCmd // asynchronous
	}

	*syncCmd { | message command |
		verbose.if {
			["syncCmd", message, command].postln
		};
		command.systemCmd // synchronous
	}

	*viewDotFile { | fileName |
		var viewerDefault = (osx: "open", linux: "dot -Txlib", windows: "start" + "".quote + dotCmd.quote);
		var viewer = dotViewer ? viewerDefault.at(thisProcess.platform.name);
		var command = if(thisProcess.platform.asString != "a WindowsPlatform") {
			"% %".format(viewer, fileName.shellQuote)
		} {
			"% %".format(viewer, fileName)
		};
		Dot.asyncCmd("viewDotFile", command)
	}

	*viewDotFileFor { | synthDef |
		Dot.viewDotFile(Dot.fileNameForWithExtension(synthDef, ".dot"))
	}

	*dotFileToSvgFileFor { | synthDef |
		var dotFileName = Dot.fileNameForWithExtension(synthDef, ".dot");
		var svgFileName = Dot.fileNameForWithExtension(synthDef, ".svg");
		var command = if(thisProcess.platform.asString != "a WindowsPlatform") {
			"% -Tsvg % -o %".format(dotCmd, dotFileName.shellQuote, svgFileName.shellQuote)
		} {
			"% -Tsvg % -o %".format(dotCmd, dotFileName, svgFileName)
		};
		Dot.syncCmd("dotFileToSvgFileFor", command)
	}

	*viewSvgFileFor { | synthDef |
		svgViewer.notNil.if {
			var command = "% %".format(svgViewer, Dot.fileNameForWithExtension(synthDef, ".svg").shellQuote);
			Dot.asyncCmd("viewSvgFileFor", command)
		} {
			var image = Image.openSVG(Dot.fileNameForWithExtension(synthDef, ".svg"));
			var window = Window.new(synthDef.name.asString, Rect(100, 100, image.bounds.width, image.bounds.height), false, true, nil, false);
			window.onClose_ {
				image.free
			};
			window.view.setBackgroundImage(image, 1, 1, nil);
			window.view.fixedSize_(Size.new(width: image.width, height: image.height));
			window.front
		}
	}

	*dotFileToPdfFileFor { | synthDef |
		var dotFileName = Dot.fileNameForWithExtension(synthDef, ".dot");
		var pdfFileName = Dot.fileNameForWithExtension(synthDef, ".pdf");
		var command = if(thisProcess.platform.asString != "a WindowsPlatform") {
			"% -Tpdf % -o %".format(dotCmd, dotFileName.shellQuote, pdfFileName.shellQuote)
		} {
			"% -Tpdf % -o %".format(dotCmd, dotFileName, pdfFileName)
		};
		Dot.syncCmd("dotFileToPdfFileFor", command)
	}

	*viewPdfFileFor { | synthDef |
		var viewerDefault = (osx: "open", linux: "xdg-open", windows: "start" + "".quote + "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe".quote);
		var viewer = pdfViewer ? viewerDefault.at(thisProcess.platform.name);
		var command = if(thisProcess.platform.asString != "a WindowsPlatform") {
			"% %".format(viewer, Dot.fileNameForWithExtension(synthDef, ".pdf").shellQuote)
		} {
			"% %".format(viewer, Dot.fileNameForWithExtension(synthDef, ".pdf"))
		};
		Dot.asyncCmd("viewPdfFileFor", command)
	}

	*drawHsc3 { | synthDef |
		var command = if(thisProcess.platform.asString != "a WindowsPlatform") {
			"hsc3-dot scsyndef-draw %".format(Dot.fileNameForWithExtension(synthDef, ".scsyndef").shellQuote)
		} {
			"hsc3-dot scsyndef-draw %".format(Dot.fileNameForWithExtension(synthDef, ".scsyndef"))
		};
		synthDef.writeDefFile(directory.standardizePath,true);
		Dot.asyncCmd("drawHsc3", command)
	}

	*writeDotFileFor { | synthDef |
		var file = File(Dot.fileNameForWithExtension(synthDef, ".dot"), "w");
		synthDef.dot(file);
		file.close
	}

	*draw { | synthDef |
		renderMode.switch(
			'hsc3', {
			    Dot.drawHsc3(synthDef)
			},
			'dot', {
			    Dot.writeDotFileFor(synthDef);
			    Dot.viewDotFileFor(synthDef)
			},
			'svg', {
			    Dot.writeDotFileFor(synthDef);
			    Dot.dotFileToSvgFileFor(synthDef);
			    Dot.viewSvgFileFor(synthDef)
			},
			'pdf', {
			    Dot.writeDotFileFor(synthDef);
			    Dot.dotFileToPdfFileFor(synthDef);
			    Dot.viewPdfFileFor(synthDef)
			},
			{
				"Dot.draw: unknown renderMode".error
			}
		)
	}

}
1 Like

If you want to skip installing anything, there are several decent browser-based dot renderers:
https://viz-js.com/

It’s very easy to hook this one up inside of a WebView so you can get dot graphs directly in your SuperCollider UI - I did this at some point though, for the life of me, I can’t find that code anymore!

2 Likes

Thanks for that! I needed something like this for other work!

hello

apologies slow reply, &

ta kindly!

can you send a patch? something like:

git diff > patch.text

here or email, though email maybe be quicker!

best,
rd

1 Like

I thought it was prohibited to do this because of “development burden” or some other term people are coming up with nowadays. At least we can modify our clones and never do PRs. :sweat_smile:

No problem! I am glad you replied!
I cannot see your email!
Please check your sc3-dot project page. I have already requested a merge:


edited:
The complete code which I patched is already posted: