DocAppGui Model + GenericMidiOutput


#1

Hi there,

You may have seen me hinting that i’m developing an application framework using Juce, and it’s almost ready to share. It may seem a little superfluous at first, but i think it should help in the creation of applications that are more complex than a simple Component based app will allow.

It’s called the ‘DocAppGui Model’, and is based around three main bases.

Document
This is the most significant class, providing a structured means of managing user data for your app. It has a unit base class called DocumentDataElement, which provides a standard interface; each element is able to export itself as an Xml tag, and the master document class uses this ability to store the whole structure to a file - as well as recreate it from a file. A kind of smart pointer is provided too which allows GUI components to safely refer to elements in the structure, as well as recieve change notifications from them.

App and Gui
This allows you to wrap the main app functionality and GUI component structure in two separate linked objects. The App maintains any Documents the program is using (currently it just uses one, but I will be expanding this to support multiple Documents), and has ApplicationCommand stuff implemented for easy use, as well as providing a MenuBarModel. It will also automatically refresh the Gui object whenever a Document changes. The reason for this abstraction/separation is to make it very easy to develop an app that will work as both standalone and plugin; using this model, you create an App subclass and a Gui subclass, which then will translate smoothly into a JuceAudioPlugin system (the filter inherits your App subclass, the editor inherits the Gui subclass).

GenericMidiOutput
I’ve also made a ‘GenericMidiOutput’, which can be used for most simple MIDI purposes acting on a single assigned port; if your program only needs one port, you can use a GenericMidiOutput* in the App subclass and call its simple sending functions (sendCcMessage(…) etc). When building a standalone application, the instance of this output would be a subclass called JuceSingleMidiOutput, which wraps the MidiOutput stuff; when making a plugin, the instance is a special JuceAudioPlugin-friendly alternative which puts your messages into a buffer to be sent to the plugin’s output- thus you have one interface that works seamlessly between platforms.

As usual, just posting this information to see how people feel about it, and if anyone’s interested or has any suggestions/criticisms.


#2

Sounds like some interesting ideas - what kind of test app are you developing with it?


#3

I’ve been developing it alongside my university dissertation program, which is a universal MIDI device controller.

I was sick of ‘bodging together’ parts to hack up an application, which is pretty much how you could describe a lot of my coding in the past! This app is fairly complex, and heavily user-data driven. The data is totally variable (users can add/remove things to panels and lists, thus requiring a solid structure) and also interrelated (e.g. controls are linked to parameters, and this link is maintained when dumped to a file by a data id, which is a feature of the document structure classes). Also, the program must respond to changes in data in a number of ways (e.g. send MIDI data when a parameter in the document changes).

It might be a little while til i get to release it all, as i’ve still got assignments and exams (although i have handed my dissertation in, the program’s still not really finished but it works). I hope to write a more basic example application using the system, along with a tutorial, to illustrate how it can be used.


#4

Looks really cool! I look forward to having a play when it’s ready.


#5

Just in case anyone’s curious about how this model is used, i’ve put the current state of the html documentation up on my website. I’ve not put the code up yet, as I plan on making a few more changes before i release it. However, it may give you some kind of idea of how you can implement it to build an application.

http://haydxn.net/content/JUCE/DocAppGui/Docs/html/


#6

it’s already changed quite a bit since i built that documentation!

I’ve just been working on the method of creating the actual app program. Whereas previously we all depend on the ApplicationStartup, MainAppWindow etc… and tinker with them, it’s a little bit easier here!

As an example of how it works, the following line in my ‘MidiApp’ App subclass implementation file turns my model into a standalone application…

START_JUCE_APPLICATION( DocAppGui_Standalone<MidiApp> );

This implements JUCEApplication, and also takes care of the creation of a DocumentWindow, using the properties you define in your App and Gui subclass to determine how they are set up. If you need more control over the app’s behaviour (using commandline stuff etc), you can just do something like this instead:

class Standalone : public DocAppGui_Standalone<MyApp>
{
   // override virtual JUCEApplication functions here...
};
START_JUCE_APPLICATION ( Standalone );

Stuff like the app name, version etc… you set in the AppInfo structure inside the App class. The Gui has a GuiInfo structure too, holding things like backgroundColour (for the main window), default dimensions, resizability, etc…

i think that’s pretty neat myself! i’m going to work on a base DocAppGui_Filter next…


#7

neat, just managed to make a JuceAudioPlugin wrapper for the model.

CREATE_DOCAPPGUI_FILTER (DocAppGui_Filter<MidiApp>);
  • this is the only line of code different in the two builds, but one is an app and one is a plugin :slight_smile: !

Of course, at the moment, this doesn’t present the VST interface (e.g. parameter access for the host, the process functions etc…) - pretty critical stuff of course! … that is a part of the model i need to work on next. I think there will probably be some way of registering elements in your document structure as ‘FilterParameters’. Also, there’s another function in the document class where you can define a method of retrieving a special ‘FilterPatch’ version of the structure as xml.

One thing though- why have the filter name properties been changed to macros? is it a workaround for a particular type of plugin, or am i mistaken and it’s always been like that? i thought maybe the vst spec needed to have this info before juce could have been initialised, but it’s using the String constructor at the point the macros are used. This macro-ness is a shame for this project as it means that the ‘define stuff once in the app class’ doesn’t translate as well as i’d hoped.


#8

[quote=“haydxn”]neat, just managed to make a JuceAudioPlugin wrapper for the model.

CREATE_DOCAPPGUI_FILTER (DocAppGui_Filter<MidiApp>);
  • this is the only line of code different in the two builds, but one is an app and one is a plugin :slight_smile: !

Of course, at the moment, this doesn’t present the VST interface (e.g. parameter access for the host, the process functions etc…) - pretty critical stuff of course! … that is a part of the model i need to work on next. I think there will probably be some way of registering elements in your document structure as ‘FilterParameters’. Also, there’s another function in the document class where you can define a method of retrieving a special ‘FilterPatch’ version of the structure as xml.

One thing though- why have the filter name properties been changed to macros? is it a workaround for a particular type of plugin, or am i mistaken and it’s always been like that? i thought maybe the vst spec needed to have this info before juce could have been initialised, but it’s using the String constructor at the point the macros are used. This macro-ness is a shame for this project as it means that the ‘define stuff once in the app class’ doesn’t translate as well as i’d hoped.[/quote]

All sounds pretty cool.

The names had to change to macros because the AU build needed to have the name in its resources - sorry, that’s life!


#9

i figured that was the case!


#10

woohoo, now i’ve hooked up the parameter interface… now you can derive any piece of data from FilterParameter if you wish for it to be linked to an audio filter parameter. you register it with a parameter index in your app, and override two functions in your data to convert between a float and whatever format your data is stored as. snap!


#11

some more tweaking, and it’s coming along nicely now- i’ve redesigned a fair bit to make it a lot easier to make apps. The App class has a default set of app commands to automatically give you a file menu with standard file commands and handling for your own custom document types, and by default will create a GUI that maintains a MultiDocumentPanel for your open documents, including handling of recently opened files.

I hope to have a release for y’all to play with in the not-too-long, although my exams make it a little naughty to be coding all the time!

Basic process is as follows:

  • Design your user document structure, by subclassing DocumentDataElement.
  • Create a Document class to hold the root of your structure, by subclassing Doc (using your own data element subclass in the template) and specifying file settings (extension, etc) in the constructor.
  • Create a document component to display your document, via a DocComponent subclass. This will access your data and allow you to edit it.
  • Create an App subclass, telling it how to create your Doc and DocComponent subclasses. All file/document handling is done for you.

if you need a GUI that does more than simply display a multiDocumentPanel for your open documents (for example, to have a different strip of global controls in addition to the panel), then subclass Gui and override the App::createGui() function - if not, it will automatically use a ‘BasicGui’, and handle your documents for you.

set the configuration in DocAppGui_Config.h - comment out the type you don’t want (e.g. for an app you leave the line #define DOCAPPGUI_STANDALONE uncommented). the ‘DOCAPPGUI_CREATE (AppSubclass)’ macro will turn the app into either a standalone or a juceAudioPlugin.


#12