From: Joe E. <jo...@em...> - 2005-03-10 02:14:22
|
Brian wrote: >> >> For a real-world example, tell me how many of JSL's current >> synthdrivers set their "sysexID" variable to a string that does NOT >> begin with "F0"? I haven't stumbled across any yet. In fact, how many >> deviate from the "[F0][ManufacturerID][DeviceID][payload][F7]" >> format? Every device I currently own conforms to this message style. >> Yet, every JSL driver has to manually craft sysex messages itself. >> How many of the current drivers, do you estimate, all have an, >> essentially, identical bit of code in createNewPatch which takes the >> data of the patch and just slaps the F0 and the manuf and device ID's >> on the beginning and the F7 on the end? > > > > Alot do, actually a lot of synths have pretty complex "Default > Patches", so the drivers actually store a dump of a "Default Patch" in > a file and load it in when create new patch is performed. > >> >> Right! JSL asked for a sysex message, and that's all that it grabs >> off of the wires. What I'm getting at is that, a vast majority of the >> time, JSL might as well lop the F0 and the F7 and give the driver the >> stuff inside. > > I dunno. Some synths have a patch dump made up of multiple F0..F7 > pairs. For example, the Boss DR-660 Driver, a patch is actually i > think 14 sysex messages sent in quick succession. Lopping off the > first and last byte but leaving the others in place would be kind of > odd and it would be a nightmare to have to insert a bunch of F0 and > F7's all throughout the patch in order to send or receive data. > Especially since not all the sub-messages have a fixed size. Two things: 1 - If the driver receives multiple F0...F7 pairs, then you could lop the F0's and F7's off of all of them and the driver could just get an array of sysex payloads. I dunno. The more we discuss stripping the F0/F7, the more I think "This is silly to raise such a fuss over just two bytes". The two arguments I have in support of raising a fuss. First, I suspect that a majority of the drivers all have code to strip/disregard those bytes on incoming messages and to replace them on outgoing ones. Each time someone does it, it raises the possibility of a bug and it contributes to code-bloat. The second argument is that, the first time I ever looked at an existing driver (as the programming.html suggested), the first thing I saw at the top of the file was a fully-formed sysex ID string. The thought that went through my mind "Wait a minute... I thought the whole point of the design was to *insulate* me from the minutae of sysex and allow me to just deal with the data *within* the sysex messages.". As a programmer, it caused me to have doubts about the wisdom of the design of the program... which made me reluctant to invest much effort in learning how to code for it. In short, I think looking at current driver implmentations could be scaring some potential developers away. 2 - I'm not saying that we have to make every driver use some new design. That's what sublcassing is for. Imagine having Driver, with its complicated way of doing things. You could make a subclass of that called, say, MoreConformingDriver, which is designed for patch dumps with a single sysex message which have [F0][data][F7] format and the programmer just deals with that [data]. Then, you could have a subclass of *that* called EvenMoreConformingDriver, which is just like its superclass, but deals with patch dumps of the format [F0][ManufacturerID][DeviceID][data][F7] and, again, the programmer just deals with the [data] part and everything else is handled transparently. Now, from what you tell me, it sounds like the Boss DR-660 wouldn't be able to make use of EvenMoreConformingDriver. Fine. It would continue to subclass Driver. However, I think that it would save a lot of coding (and look more inviting to potential new developers) if driver constructors contained a few simple commands like I'm doing with the driver I'm working on: setManufacturerID("00000E"); setDeviceID("05"); setDecodingType(ALESIS); Just those three commands, and then my createNewPatch and editPatch methods get to just deal with the (decoded to 8-bit) bytes after the DeviceID and before the F7. Heck, someone could make a subclass of *that* called "EvenMoreConformingAlesisDriver" and then all you'd need to do is set your deviceID! Maybe it's just me... but I feel that, if you're writing for a device that is fairly standard, then subclasses like this could save a lot of time, because you only deal with the level of complexity that you need to. > I think It's easier to tell a driver writer, whatever bizzare data > your manufacture prepends to the patch, insert that here... and have > it always work, then have to explain put your manufactuer ID here, > your device ID here, this is the standard sysex representation of that > data, if your synth doesn't use that than subclass this instead One thing that I find disconcerting, however, is the fact that it's not easy to know what data elements you have to set. For example, while writing my driver, I tried to "Get" a patch... and I got an exception thrown. After I hunted around, I figured out that it was because I hadn't initialized "String[] patchNames". Well... how silly of me! *Everybody* knows that you have to initialize patchNames. :P So, I think that it would make driver development a little smoother if it were easier to know what info you needed to provide for things to work. One idea would be to have EvenMoreConformingDriver an abstract class and to make some abstract methods for getDeviceID and getManufacturerID. Then, if you try to subclass it, you'll get compile errors if you don't implement them. This is good for two reasons: First, compile-time errors are generally better than runtime-errors since the *user* can't encounter a compile-time error, and secondly, because it would be easier for the developer to tell, from the error, what the problem was. Of course, using abstract classes is just one possiblity. Maybe it could be done with interfaces... I dunno. But you get the idea. > Plus I would hate to write an editor where I had to worry that what > the manual was calling byte number 55, was actually byte number 48 in > the array I was passed because some stuff had been stripped off the front. I've got the opposite problem, where my spec calls the byte after the deviceID "byte 0". So, nyeah! :) > That said, it is a good idea to look back occasionally at what has > evolved and look to see if it can be refactored without losing anything. And keep in mind that I'm willing to put in a lot of effort to aid any refactoring. I'm not the kind to say "This all sucks... you guys fix it and call me when you're done.". If it is decided to make a change, I'll be the first one diving in to help convert old stuff so that it works with the new stuff, if need be. > One example of this, is that we provide a default "Compute Checksum" > method so that many synths don't have to implement it themselves, but > if (again all to commonly) the synth uses some other approach to > checksum computation or even uses multiple checksums (again way too > common), the author can override this. Do you know of any technical barrier to putting all of the various checksum algorithms into one class, so that something like the hypothetical EvenMoreConformingDriver could use something like: setChecksumType(YAMAHA_PRE_1996); in the constructor? I didn't say *psychological* barriers.... I said *technical*. :) - Joe |