MIDIOut.connect, check if connected (error handling)

How do I check if a MIDIout or MIDIIn is already connected?

And how do I handle a error when SC wants to connect to a busy port? Any good information about error handling in SC somewhere?

I found a ‘hack’ here:

edit:
https://doc.sccode.org/Classes/Exception.html

(
	try { MIDIOut.connect(i); } { |err|
		switch(err.species.name)
		{ 'PrimitiveFailedError' } { 
			postln("path: "  + err.path);
			postln("errorString: " + err.errorString);
			postln("what: " + err.what);
			if(err.errorString.find("_ConnectMIDIOut").notNil){
				"caught connectMIDIOut error, device already connected?".postln;
			} { "unknown primitive exception".postln; } // err.throw; }
		}
		// default condition: unhandled exception, rethrow
		{ "unknown exception".postln; err.throw; }
	}
)

This, I believe, is a platform-specific question.

MacOS and Windows, I don’t know. I do know that these OSes present ports for devices but not apps.

In Linux, ALSA maintains the connections. So, to get the current status, ask ALSA: "aconnect -l".unixCmdGetStdOut and parse the string. (“Why isn’t there a more convenient way?” I guess because nobody needed it. As a funny aside, this was removed from MIDIIn help, but James McCartney’s original help file for MIDIIn introduced the class only with “A popular 80s technology.”)

https://doc.sccode.org/Guides/Understanding-Errors.html#Error%20objects%20and%20error%20handling

hjh

1 Like

Thanks. Is it possible to define your own errors and what is a good way to do so?

Alternately, is there any reason why SC should prohibit user-defined errors? It would be unnecessary (and awful) to impose an artificial limitation here.

And if so, how would that be done? For instance, SC has no mechanism to prohibit subclassing, so at minimum, you can always have MyNewErrorType : Error { ... } and there’s nothing SC can do to stop you.

In any case, the Error help file (for the class Error) does provide an even simpler example:

Error("File % could not be opened.".format(path)).throw;

Actually the linked bit on error handling has a similar example, right at the top of that section: Error("This is a basic error.").throw;

hjh

I see, but in the examples they do switch(err.species.name) and one can select PrimitiveFailedError for example.

When using Error("This is a basic error.").throw, the err.species.name is just Error.

How to make a thing like PrimitiveFailedError. One has to add extensions to the Error.sc class? Or can one better write a own error class?

Already stated: “you can always have MyNewErrorType : Error { ... }

MyNewError : Error {
    *new { | /* whatever arguments you need */
        ... populate instance variables ...
    }
    errorString {
        ^"This is the bad thing that happened..."
    }
}

^^ where the above is just following models in the class library. The error class definitions are not complex – pretty easy to suss out how to add more.

hjh

1 Like

Thanks, seems to work.

LPUnknownInstrumentError : Error {
  var <>instrument;

  *new {  arg instrument;
    ^super.new(instrument)
  }

  errorString {
    ^"LP_ERROR: unknown instrument: " ++ instrument
  }
}

LPNoDeviceFoundError : Error {
  var <>device;

  *new {  arg device;
    ^super.new(device)

  }

  errorString {
    ^"LP_ERROR: device not found: " ++ device
  }
}