Algorithmic Composer, page1
Algorithmic Composer Program Description
Angelo Fraietta
Student Number 95035879
University of Western Sydney
Music Thesis or Performance - Subject 33460
23 November, 1998
Algorithmic Composer, page2
I designed Algorithmic Composer to meet a personal need as both a composer
and performer of electronic music. I required a tool for the PC platform that would
enable me to send MIDI data, which I was manipulating during a performance, to an
external sound engine.
I was introduced to algorithmic compositional techniques through the “Max”
software package when studying Music Technology 3 in 1996. I used Max for all my
performance projects; however, two aspects of Max disappointed me – it was
unavailable on most of the computers in the multimedia lab due to its price, and the
program was not available for the PC platform. I commenced using C-Sound in
Music Technology 5. Real time manipulation and sound generation was not available
for the Windows or Dos environments, but was available for Linux. The
disadvantage with C-Sound was that it was both a non-graphical environment, and I
was unable use external sound engines. I required a program that would run on PC
and allow MIDI input and output; and because I could not buy such a software
package, I decided to write one. I set the following specifications for the program:
1. The program must include a graphical user interface (GUI) that enabled
composers, who mostly are not trained programmers, to create complex
algorithmic structures without requiring a deep understanding of computer
science.
2. The program had to enable and encourage documentation. After
performing a significant amount of MAX programming, and helping many
students with their MAX patches, I realized that patch documentation is
necessary to enable patch maintenance or assessment.1
1 Nell Dale and Chip Weems, Introduction to Pascal and Structured design, fourth edition(Boston: Jones and Bartlett, 1997), p. 7.
Algorithmic Composer, page3
3. Patches must be navigable to facilitate patch de-bugging. The user must
be able to access and edit the data in an object and all other objects
connected to the selected object. The user can thereby navigate through a
patch and examine the logic flow through the internal data.
4. The performer must be able to reset the patch to a known condition to
enable effective rehearsal of pieces.
I chose the C++ language because it supports object orientated, object based,
and procedural programming paradigms2. Additionally, C++ will facilitate porting
Algorithmic Composer to other platforms, including Macintosh and Linux. I planned
to use Borland C++ Builder 3.0, a rapid application development (RAD)3 package, for
the Win32 GUI. Builder 3.0, however, was unavailable in Australia until May 1998,
so I commenced programming with Borland C++ 4.5 until Builder 3.0 became
available. Builder 3.0 arrived with a complimentary C++ 5.02 programming suite. I
chose to use C++ 5.02 instead of Builder 3.0 during the construction of the underlying
data structures for several reasons. C++ 5.02 had the same integrated development
environment (IDE) as C++ 4.5, which enabled me to continue working on the
program without immediately having to use a foreign IDE. I had already created a
menu driver that used a console interface for the data structures, and therefore did not
immediately require a GUI for the program. C+5.02 also had Code Guard, which
enabled me to find memory leaks, access violations, and other bugs in my program.
The program, however, would not immediately compile due to the changes in the C++
2 Stanley B. Lippman and Josée Lajoie, C++ Primer, third edition (Reading, Massachusetts:Addison-Wesley, 1988), p. 2.
3 Kent Reisdorph, Teach Yourself Borland C++ Builder in 14Days, Indiana: SAMS, 1998).
Algorithmic Composer, page4
language between the release of Borland C++ 4.05 and C++5.02,4 albeit only minor
changes. I had trouble migrating from C++ 5.02 to Builder 3.0 because Builder 3.0
did not support the class container types from C++ 5.02. This was not a great
problem because similar container types, including map and vector, are now included
in the C++ standard library.5 I did, however have to rewrite large sections of code.
I had a great deal of trouble with the timer events, due to the inability of
Windows 95 to process multimedia timers in 32 bit processes. Successful
implementation of multimedia timers in Windows 95 required that the time critical
sections of the program exist in a 16-bit dynamic link library (DLL).6 Flat thunks are
then required to allow 32-bit applications access the data structures within the 16-bit
DLL.7 Paul Messick, in his book Maximum MIDI: Music Applications in C++,8
provides a pair of DLLs, called the Maximum MIDI Toolkit, and complete source
code; his book, however, only supports implementation with Microsoft Visual C++.
I had to create another DLL to interface the Maximum MIDI Toolkit with the Borland
compilers because the import library for the 32-bit side of the DLL pair was in
Common Object File Format (COFF) and is not supported by Borland9.
4 Stanley B. Lippman and Josée Lajoie, C++ Primer, p. xviii.
5 Ibid., p. xix.
6 Mark McCulley, “Overcoming Timer-Latency Problems in MIDI Sequencers,” MicrosoftSoftware Development Network Online Library (1996):http://premium.microsoft.com/isapi/devonly/prodinfo/msdnprod/msdnlib.idc?theURL=/msdn_mlatency.htm.
7 Paul Messick, Maximum MIDI: Music Applications in C++ (Greenwich CT: Manning,1988), p. 37 – 38.
8 Ibid.
9 Inprise newsgroup, borland.public.cpp, 20 September 1998.
Algorithmic Composer, page5
I initially used the synchronizer from the Maximum MIDI Toolkit only to
discover that my part of the program that received the timing messages from the
toolkit used the Windows Message queue, which was worse than using the
multimedia timers in a 32-bit process. I realized at this point that the object data
structures in my program needed to be in a 16-bit DLL for accurate timing. I
attempted using the thunk compiler as described by Paul Messick, only to find that
thunk32.lib on the Microsoft Software Development Kit (Win32 SDK) was also in
COFF format. Borland included the thunk compiler in the C++ 5.02 Development
Suite, but did not include any way of implementing it with any Borland compilers. It
is possible, however, to create flat thunks using Borland Turbo Assembler (TASM).
TASM32 is included with Builder 3.0, but the examples for creating flat thunks are
only included with TASM 5.0, 10 which is TASM32 in a separate box and a price tag
of $150. After spending three solid weeks attempting to implement flat thunks in my
program without the specific TASM example, I decided to use Windows NT because
it uses a true 32-bit multimedia system.11 The program runs in Windows 95 with
limitations on timing accuracy.
I separated the program into three distinct program groups: MIDI interface,
program engine, and user interface. The current implementation of Algorithmic
Composer uses the Maximum MIDI Toolkit for MIDI input and output, the timing
algorithms and object types exist in the engine, and the main Windows program is
the user interface.
10 I received an example of flat thunking on 17 November 98 but have no time to implement itinto my program before this submission is due.
11 Mark McCulley, “Overcoming Timer-Latency Problems in MIDI Sequencers,” MicrosoftSoftware Development Network Online Library (1996).
Algorithmic Composer, page6
Midi Interface
Engine
C Funtion Calls
User Interface
Post Message
Post Message
Figure 1 Package Layout
The MIDI interface and Engine exist as a separate DLLs, which will facilitate
porting to new platforms and operating systems. Packages are linked with standard C
function calls and the PostMessage procedure. The PostMessage procedure sends
messages to the user interface through the windows message queue. The
PostMessage procedure performs a reentrant call, through the main program at time
critical sections of program execution, allowing the program to process the procedure
call when the central processing unit (CPU) is idle.12 An equivalent reentrant
procedure or function call would be required when porting the program to a new
platform if communication from the engine to the user interface is required. The
PostMessage functions inform the user interface of Trigger events, Display events,
and error messages, and thus prompt the interface to update the appropriate windows
through function calls to the engine. An interface, however, can still operate
effectively without this type of communication because the updating of edit windows
and icons is achieved by poling the objects when the CPU is idle.
12 Charles Petzold, Programming Windows 95, fourth edition (Redmond: Microsoft Press,1996), p. 46.
Algorithmic Composer, page7
The standard C function calls allow platform independence and language
portability. A software developer can construct another user interface using a
different language, providing the new language supports C function calls. For
example, the separation of the engine from the interface will potentially allow
ensemble performances via a network. One machine could have the engine loaded
into memory while other machines simultaneously access the underlying data
structures. The user interface could be written in JAVA, thus creating an Internet
ensemble.13 That area of research, although beyond the scope of this project, could
use the engine package of Algorithmic Composer as a central element, or simply as a
plug-in, without re-compiling the source.
Engine Construction
The engine was constructed using mainly the BaseShell and the Connector
classes. Both classes are inherited from Identity class, which has both a name and
comment, to enable and encourage patch documentation. (See figure 2).
BaseShells are the object types -- like a counter or delay (see figure 3) -- and
are connected together to form a Patch, similar to the way “older analogue machines
… used patch cables to connect different electronic modules”14 together. BaseShells
use their common ancestry to connect and communicate. The functions used to
connect the object are non-virtual, as the operations they perform are on the BaseShell
part of the object.
13 Alex Cockburn had the idea of an Internet ensemble as a project earlier this year.
14 Jeff Pressing, Synthesizer Performance and Real-Time Technique (Oxford: OxfordUniversity Press, 1992), p. 16.
Algorithmic Composer, page8
Identity
szName : char*szComment : char*
Identity( )~Identity( )GetName( )GetComment( )GetType( )SetName( )SetComment( )Save( )operator <( )$RestoreID( )SaveID( )
ConnectorBaseShell
1..21..2
Figure 2 BaseShell and Connector Inheritance
BaseShells and Connectors exist together inside a single Patch, which itself is
a type of BaseShell. Each BaseShell and Connector belong to one Patch, whereas a
Patch can have many BaseShells or Connectors. The only circumstance where a
BaseShell does not belong to a Patch is when the BaseShell is a Patch and not a sub-
patch. An example of this instance is when the user creates a new Patch from the file
menu. (See figure 4).
Algorithmic Composer, page9
Calculate
BaseShell
wNumInlets : unsigned intwNumOutlets : unsigned inttpInletConnections : InletContainertpOutlet : vector<OutletContainer*>
BaseShell( )~BaseShell( )operator ==( )Reset( )VoidInlet( )IntInlet( )DoubleInlet( )StringInlet( )Connect( )CanConnectInlet( )CanConnectOutlet( )GetNumInlets( )FindOutletConnectorIndex( )GetNumOutlets( )FindInletConnectorIndex( )GetInletName( )GetOutletName( )$RestoreBase( )AddInlet( )AddOutlet( )RemoveInlet( )RemoveOutlet( )CreateOutlets( )CreateInletLists( )SaveBase( )
Counter
Switch
InletsSwitch
OutletsSwitch
FlipFlop
Trigger
Figure 3 BaseShell Sub-Set Inheritance.
Identity
ObjectList
0..*
pParent
1
ConnectorLis t
0..*
pParent1
Patch
BaseShell
0..*
1
Connector
0..*
1
Figure 4 Patch Construction.
Algorithmic Composer, page10
A Connector is associated with one or two BaseShells through the Socket
Details attributes. (See figure 5).
SocketDetails
wSocketNumber : unsigned intpBase : BaseShell*
SocketDetails( )operator ==( )operator !( )
InletConnection
1
Has
0..*
OutletConnection
2Has
0..*
pBase
1
1
1..2
Connector
$ szType : const char* constInletConnection : SocketDetailsOutletConnection : SocketDetails
Connector( )Connector( )~Connector( )operator ==( )operator !( )InletDetails( )OutletDetails( )Disconnect( )DisconnectFromInlet( )DisconnectFromOutlet( )DisconnectFromParent( )ConnectToInlet( )ConnectToInlet( )ConnectToOutlet( )ConnectToOutlet( )SetInletBase( )SetOutletBase( )SetInletNum( )SetOutletNum( )GetType( )Save( )$Restore( )
1 0..*2 0..*
BaseShell
1
1
1..2
Figure 5 Connector to BaseShell Association
BaseShells are able to call the BaseShell through the Connector by obtaining
the address of the other BaseShell, from the Connector’s pBase attribute, and the inlet
or outlet number from the wSocketNumber attribute. The BaseShell’s outlet has an
array of Connectors (see figure 6). When an object needs to send a message from an
outlet, it iterates through its list of Connectors and uses the attributes from each
Connector.
Algorithmic Composer, page11
InletContainer
InletContainer( )DeleteConnectors( )~InletContainer( )
#tpInletContainer
has
#tpOutlet
calls
1
0..*
0..*
SocketContainer
SocketContainer( )RemoveConnector( )AddConnector( )SwapConnector( )GetNumConnectors( )GetConnector( )FindIndex( )HasConnector( )
OutletContainer
OutletContainer( )ProduceOutput( )ProduceOutput( )ProduceOutput( )ProduceOutput( )~OutletContainer( )DeleteConnectors( )
Connector
0..* 0..*
BaseShell
0..*
1
0..*
10..*
1..2
0..* 0..*
1..2
1
0..*
Figure 6 Inlet and Outlet Containers
Messages are sent to an object by using the inlet number as a parameter to the
virtual inlet function call to the BaseShell. BaseShell has an array of OutletContainers
that have four ProduceOutput methods, and, BaseShell also has four virtual inlet
function calls, one for each type of message. The outlet number is defined by the
tpOutlet index. The ProduceOutput functions appear as follows:
class OutletContainer :public SocketContainer{public:
//other class functions……void ProduceOutput();void ProduceOutput (const char* sVal);void ProduceOutput (int iVal);void ProduceOutput (double dVal);
};
Algorithmic Composer, page12
If a function has to send a message out through an outlet, the outlet number is used as
the index to access the appropriate outlet from tpOutlet. The overloaded
ProduceOutput function is called on the tpOutlet vector element.
void Delay::SendMessage (MessageCell& TheMessage){ switch (TheMessage.MsgType){ case MessageCell::VoidType: tpOutlet[0]->ProduceOutput(); break; case MessageCell::IntType: tpOutlet[0]->ProduceOutput(TheMessage.ival); break; case MessageCell::DoubleType: tpOutlet[0]->ProduceOutput(TheMessage.dval); break; case MessageCell::StringType: tpOutlet[0]->ProduceOutput(TheMessage.sval.c_str()); break; default: break; };//end case};
The Inlet function prototypes appear in the BaseShell class definition as follows:
class BaseShell: public Identity{public:
//other class functions……virtual void VoidInlet (unsigned InletNumber) {}virtual void IntInlet (unsigned InletNumber, int iVal){}virtual void DoubleInlet (unsigned InletNumber, double dVal){}virtual void StringInlet(unsigned InletNumber, const char* sVal){}//other class functions
};
The functions are not pure virtual functions, and as such, each subset object only
needs to overload the virtual functions it requires. The function call is not made to the
InletContainer, but rather to the virtual function. The main purpose of
tpInletContainer is to notify the Connectors pointing to this object when this object is
Algorithmic Composer, page13
about to be destroyed, thus preventing dangling pointers.15 The Inlet Number is used
as an index to an array of function pointers that are object specific. Consider the
following Delay class:
class Delay: public BaseShell, DelayLine{public:
//other functions…..//overloaded inlet functionsvoid VoidInlet(unsigned);
void DoubleInlet(unsigned, double); void IntInlet(unsigned, int); void StringInlet(unsigned, const char*);
void Reset (); void SetInterval(int i){wInterval = (unsigned)i;}//other functions
private://other attributes and functions……//these are the private functions that are called from inside Delayvoid DelayVoid();void DelayInt(int);void DelayString(const char*);void DelayDouble(double);void StringInlet1(const char*);
//these are the static arrays of pointers to functionstypedef void(Delay::*pVoidFunc)();static const pVoidFunc tpVoidFunc[];
typedef void(Delay::*pIntFunc)( int);static const pIntFunc tpIntFunc[];
typedef void(Delay::*pDoubleFunc)(double);static const pDoubleFunc tpDoubleFunc[];
typedef void(Delay::*pStringFunc)(const char*);static const pStringFunc tpStringFunc[];
};
15 Stanley B. Lippman and Josée Lajoie, C++ Primer, pp. 406-09.
Algorithmic Composer, page14
The statement:
typedef void (Delay::*pIntFunc)(int);
defines pIntFunc as a pointer to a Delay class member function that takes one integer
argument and a return type of void. Therefore
static const pIntFunc tpDoIntFunc[];
declares a constant static member that is an array of type pIntFunc. The array is then
defined:
const Delay::pIntFunc Delay::tpIntFunc [NUM_INLETS] = {&Delay::DelayInt,&Delay::SetInterval
};Returning to the Delay class definition we see that DelayInt and SetInterval are both
functions that take one integer as an argument and return void. Delay::tpIntFunc[1]
gives the address of Delay::SetInterval. If no function is desired for the input, the
function address in the static array is set at NULL.
const Delay::pDoubleFunc Delay::tpDoubleFunc [NUM_INLETS] = {&Delay::DelayDouble,NULL
};
Implementing the call to IntInlet of the Delay is as follows:
void Delay::IntInlet(unsigned InletNumber, int i){
if ((InletNumber < GetNumInlets())&& (tpIntFunc[InletNumber])) (this->*tpIntFunc[InletNumber])(i);}
The index is first checked, InletNumber < GetNumInlets(), and then the function
address is taken checked for validity with InletNumber used as the index. If both
conditions are met, the function is executed.
void Delay::DoubleInlet(unsigned InletNumber, double d){
if ((InletNumber < GetNumInlets())&& tpDoubleFunc[InletNumber])) (this->*tpDoubleFunc[InletNumber])(d);
Algorithmic Composer, page15
}
A double message at Inlet 1 will not execute because Delay::tpDoubleFunc[1] is equal
to NULL. The same method of pointer to class member function is used to acquire the
names to the inlets and outlets. A static array of const char* const is placed in each
object and is accessed the same way through the virtual BaseShell functions
const char* GetInletName(unsigned InletNumber);const char* GetOutletName(unsigned OutletNumber);
and implemented in the sub-class
const char* const Delay::szaInletDetails[NUM_INLETS] = {"Message",
"Interval"};
const char*const Delay::szaOutletDetails[NUM_OUTLETS] = {"Delayed Message"
};
const char* Delay::GetInletName(unsigned InletNumber)const{
if (InletNumber < GetNumInlets()) return szaInletDetails[InletNumber]; else return NULL;}
BaseShell also uses pure virtual functions to access attributes from the sub-
class that do not exist in the BaseShell super-class. The function
const char* GetType() = 0;
in the Identity class definition allows access to the type which is defined statically inthe sub-class; and
void Reset() = 0;
in the BaseShell class definition allows access to the Reset function. Instantiation of
Identity and BaseShell classes is therefore not possible except through derived classes
that override these pure virtual functions.
Algorithmic Composer, page16
New Objects are instantiated through the sub-set class member static functions
static BaseShell* Create(Patch* pParent);static BaseShell* Restore(const char**,unsigned long*, Patch*);
typedef BaseShell* (*pfnCreate)(Patch*);typedef BaseShell* (*pfnRestore)(const char**,unsigned long*, Patch*);
1
TypeListElement
pCreate : pfnCreatepRestore : pfnRestoreTypeName : std::string
operator ==( )
1
RestoreMapType
Key : stringAssociation : pfnRestore
operator <( )operator==( )operator[]( )count( )erase( )
TypeList
TypeElements : TypeListElementRestoreMap : RestoreMapTypeCreateMap : CreateMapType
Create( )RestoreObject( )
1
11
CreateMapType
Key : stringAssociation : pfnCreate
operator <( )operator ==( )operator[]( )count( )erase( )
1
Figure 7 Create and Restore Diagram.
The address of each Create and Restore function and its type is stored within
the TypeListElement class with the following type definitions:
std::string TypeName;typedef BaseShell* (*pfnCreate)(Patch*);pfnCreate pCreate;typedef BaseShell* (*pfnRestore)(const char**,unsigned long*, Patch*);pfnRestore pRestore;
(See figure 7).
TypeName is a string that defines the object file -- for example, Counter or Delay.
The list of all type name definitions is contained in the file “TypeNames.h” and must
Algorithmic Composer, page17
be accessible to the user interface during compilation. The pfnCreate type is an
address of a function that takes a Patch* as an argument and returns a BaseShell*,
while pfnRestore takes a const char**, an unsigned long*, and a Patch* as arguments,
and returns a BaseShell*.
TypeList has a RestoreMap and CreateMap that use the type name as the key
and return the pfnRestore or pfnCreate for that object type. This implementation is
hidden within the TypeList class, but is accessed through the function calls
static BaseShell* Create (const char* Type, Patch* pParent);
and
static BaseShell* RestoreObject(std::string Type, const char** pszCursor, unsigned long* pOldPointer, Patch* pParent);
within the TypeList class definition.
The call to TypeList::Create uses Type as the parameter that defines the type,
and pParent as the Parent Patch. TypeList looks inside its CreateMap for an element
that matches the Type argument. If a match is found, it retrieves the address of the
Create function and calls Create with the pParent as the argument, otherwise the call
returns NULL. Consider the following call to create a new Delay:
BaseShell* pBase = TypeList::Create(“Delay”, pPatch);
//enter into TypeListBaseShell* TypeList::Create(const char* szType, Patch* Parent){//Parent = pPatchstd::string Type(szType); //converted into string type. Type = Delayif(NewObjectMap.count(Type)) // is “Delay” here ? return NewObjectMap[Type](Parent); //ie. return Delay::Create(Parent)
//enter into DelayBaseShell* Delay::Create(Patch* Parent){
return new Delay (Parent); //let new Delay = pDelay}
Algorithmic Composer, page18
//return to TypeList//TypeList returns pDelaypBase = pDelay
Create Function Call : CreateMapType
: TypeList : DelayTypelist::pCreate : CreateMapType
1: Create (const char* Type, pPatch* Parent)
4: Create (Patch* pParent)
5: Delay (Patch* pParent, const char*, const char*, unsigned )
Extra argument parameters provided by Delay::Create
6: Create (Patch*)
7: Create (const char*, Patch*)8: return BaseShell*
2: count (string)
3: operator[] (string)
Figure 8 Create Sequence Diagram.
TypeList returns the pointer to a new BaseShell that is actually a Counter. (See Figure
8).
Restore works in a similar manner, restoring a class from file. We must first
examine how the data is saved to disk before restoring. The data for each instance of a
class is saved as one line of text. Patch calls the virtual Save function for each object
in its pObjectList. Each parameter of data is saved as a null terminated string. The
Identity part of the object is saved first followed by the BaseShell, and then the class
specific data. The object type is saved with the Identity16, while the pointer is saved
with the BaseShell part so the Connectors can find which objects they are connected
to.
16 GetType is a pure virtual function of Identity.
Algorithmic Composer, page19
: Patch : BaseShell : Delay
1: Save (ofstream&)
2: SaveBase (ofstream&)
3: SaveID (ofstream&)
4: SaveBase (ofstream&)
5: Save (ofstream&)
6: Save (ofstream&)
virtual function call through BaseShell
Save Type, Name, and Comment
Save pointer
Save class specific data
Figure 9 Save Sequence Diagram.
The resultant line of text in the file is
Delay Name Comment 19228988 500
Restoring the objects is done a line at a time, so a character buffer can hold all
data associated with the object. Data is restored by Identity first, then BaseShell,
followed by class specific data. The data is converted from a character buffer from a
line from a file into the appropriate data types string at a time.
static BaseShell* RestoreObject(std::string Type, const char** pszCursor, unsigned long* pOldPointer, Patch* pParent);
Assuming Type has been found within TypeList, TypeList calls the static
Restore function for the particular class Type. The argument pszCursor is a pointer to
the character buffer, pOldPointer is the address where the old pointer value will be
Algorithmic Composer, page20
stored in the calling function, and pPatch is the Parent Patch. Consider the Restore
function within the Delay class:
BaseShell* Delay::Restore(const char** pszCursor, unsigned long* pOldPointer, Patch* Parent){ const char* szName; const char* szComment; *pOldPointer = RestoreBase(pszCursor, &szName, &szComment);
unsigned riInterval = (unsigned)atoi(*pszCursor); *pszCursor = *pszCursor + strlen(*pszCursor)+1;
return new Delay(Parent, szName, szComment, riInterval);}
RestoreBase assigns szName, szComment to positions along the character buffer
*pszCursor, returns the value of the old pointer, which is assigned to *pOldPointer,
and moves pszCursor to the next point in the character buffer after the old pointer.
The local variable riInterval is declared and assigned to the converted value of the null
terminated string that pszCursor is pointing to, after which pszCursor is moved to the
next position. The variables pParent, szName, szComment and riInterval are passed
as parameters in the creation of a new Delay. Delay::Restore returns a pointer to the
new Delay (as a BaseShell*) to the Patch that is being restored. The Patch stores the
real pointer in pObjectList, while the old pointer is stored in a temporary map that
associates the old pointer with the new pointer. (See figure 10).
Alg
orit
hmic
Co
mpo
ser,
pag
e21
: P
atc
h :
De
lay
: T
yp
eL
ist
1:
Re
sto
reO
bje
ct
(co
ns
t c
ha
r*,
co
ns
t c
ha
r**,
un
sig
ne
d lo
ng
*, P
atc
h*)
2:
Re
sto
re (
co
ns
t c
ha
r**,
un
sig
ne
d lo
ng
*, P
atc
h*)
3:
Re
sto
reB
as
e (
co
ns
t c
ha
r**,
co
ns
t c
ha
r**,
co
ns
t c
ha
r**)
4:
Re
sto
reID
(c
on
st
ch
ar*
*, c
on
st
ch
ar*
*, c
on
st
ch
ar*
*)
5:
Re
sto
reB
as
e (
co
ns
t c
ha
r**,
co
ns
t c
ha
r**,
co
ns
t c
ha
r**)
6:
Re
sto
re (
co
ns
t c
ha
r**,
un
sig
ne
d lo
ng
*, P
atc
h*)
8:
Re
sto
reO
bje
ct
(co
ns
t c
ha
r*,
co
ns
t c
ha
r**,
un
sig
ne
d lo
ng
*, P
atc
h*)
: R
es
tore
(c
on
st
ch
ar*
*, u
ns
ign
ed
lon
g*,
Pa
tch
*)
De
fin
e T
yp
e
an
d c
all
sta
tic
fun
ctio
n
Re
ad
Na
me
an
d
Co
mm
en
t Re
ad
an
d a
ss
ign
O
ld P
oin
ter
Re
ad
cla
ss
s
pe
cif
ic d
ata
7:
De
lay
(P
atc
h*,
co
ns
t c
ha
r*,
co
ns
t c
ha
r*,
un
sig
ne
d)
Cre
ate
ne
w D
ela
y
with
pa
ram
ete
rs
pre
vio
us
ly a
qu
ire
dR
etu
rn p
oin
ter
to o
bje
ct
Fig
ure
10 R
esto
re S
eque
nce
Dia
gram
.
Algorithmic Composer, page 23
Connectors are saved in an identical manner, using the pointer to the inlet and
outlet objects, and the inlet and outlet numbers as the class specific data. Patch class
the function RestoreConnector, which uses the old BaseShell pointers as the key to
acquiring the new BaseShell pointers from the map created in Patch::Restore. The
Connector is created with the restored Name, Comment, object pointers, and inlet and
outlet numbers. The Patch uses the same temporary object map to associate Patch
inlets and outlets. (See figure 11).
An example of a patch saved to disk is
Patch New Patch File1 19226672 0 0 1Inlets Switch 19229016 5 0Outlets Switch 19232392 5 0Number Store 19234740 0 6 0Trigger 19236956Trigger 19239160Trigger 19241364Trigger 19243568Number Store 19245772 0 127 0Trigger 19247988Trigger 19250192Connector 19229016 0 19236956 0 19252424Connector 19232392 0 19243568 0 19255580Connector 19232392 4 19247988 0 19257708Connector 19234740 0 19229016 0 19259836Connector 19234740 0 19232392 0 19261964Connector 19239160 0 19229016 1 19221348PatchPortPointersEnd Patch 19226672
Algorithmic Composer, page 24
: Patch : Connector
2: Restore (const char**, const char**, const char**, unsigned long*, unsigned int*, unsigned long*)
3: RestoreID (const char**, const char**, const char**)
Get Name and Comment
1: Global Restore Connector
5: Global Restore Connector
6: Connector (Patch*, SocketDetails, SocketDetails, const char*, const char*)
Create new Connector with new pointers
4: Restore (const char**, const char**, const char**, unsigned long*, unsigned int*, unsigned long*)
Get Old Pointers and Socket numbers
Associate Old pointers with new pointers
Figure 11 Restore Connector Sequence Diagram.
Object Scheduling
Metro, Delay, and Sequencer use multiple inheritance to enable them to be
both BaseShells and TimerObjects (see figure 12). TimerObjects send callback
requests to the Scheduler, which implements the timing through the operating system
Algorithmic Composer, page 25
DelayLine
Sequencer
FreeRunning
Delay Metro
BaseShellTimerObjectScheduler
<<Global>>
Figure 12 Timing Objects Inheritance Diagram.
A TimerObject gets the current time by calling GetPosition from Scheduler
and adds a timing interval to calculate the callback time. The TimerObject sends a
TimerQueue item with the pointer to itself and the callback time as attributes (see
figure 13). The Scheduler pushes the event, which uses the callback time as the
priority, onto the ScheduledItems priority queue. If the new event is at the front of the
ScheduledItems priority queue, the Scheduler sends a single callback request to the
operating system (see figure 14). The TimerObject calls KillTimeEvent to delete an
event. The event is pushed onto the DeletedItems priority queue (see figure 15).
Algorithmic Composer, page 26
TimerObject
ReceiveClockTiming (Item : TimerQueueItem = default) : DWORDPurge ()
0..*
1
Scheduler
ScheduledItems : PriorityQueueDeletedItems : PriorityQueuewTimerId : unsigned int
SetTimeEvent (CallbackEvent : TimerQueueItem)KillTimeEvent (DeletedEvent : TimerQueueItem)Start ()Stop ()Pause ()Resume ()GetPosition () : DWORDOutputFunction ()
2
TimerPriorityQueue
empty () : boolfront () : TimerQueueItempush (Item : TimerQueueItem) 2
0..*TimerQueueItem
CallackTime : DWORDpTimer : TimerObject*
operator ==( )operator <( )
0..*
1
0..*
calls
Figure 13 Callback Scheduling.
: Scheduler : TimerObject : TimerPriorityQueue
Multimedia System
: TimerQueueItem
1: GetPosition ( )
3: SetTimeEvent (TimerQueueItem)
4: push (TimerQueueItem)
9: SetTimeEvent
2: timeGetTime
5: front ( )
7: Pause ( )
8: Start ( )If operator == returns true
6: operator == ( )
10: function return
Figure 14 Schedule Set Time Event.
Algorithmic Composer, page 27
: TimerObject : Scheduler : TimerPriorityQueue
1: KillTimeEvent (TimerQueueItem)
2: push (TimerQueueItem)
3: Function return
DeletedItems
Figure 15 Scheduler Kill Time Event.
The operating system calls the Scheduler at callback time. The Scheduler
reads the front of the ScheduledItems queue and, if it is not at the front of the
DeletedItems queue, it calls the ReceiveClockTiming function by de-referencing the
pTimer attribute of the TimerQueueItem. The function returns with the next
requested callback time for this TimerObject, which is in turn pushed onto the
ScheduledItems queue by the Scheduler. The Scheduler iterates with this procedure
until the callback time of the TimerQueueItem at the front of the ScheduledItems
queue is outside the tolerance of the current operating system callback, or the
ScheduledItems queue is empty. A callback request is then sent to the operating
system if the ScheduledItems queue is not empty (see figure 16).
Algorithmic Composer, page 28
DeletedItems
Multimedia System
: Scheduler : TimerPriorityQueue
: TimerPriorityQueue
: TimerObject : TimerQueueItem
ScheduledItems
1: OutputFunction ( )2: front ( )
3: pop ( )
4: front ( )
5: operator == ( )
6: pop ( )
7: ReceiveClockTiming (TimerQueueItem)
if operator== popelse ReceiveClockTiming
8: front ( )
while front time <= current time
9: pop ( )
10: front ( )
11: operator == ( )
12: pop ( )
13: ReceiveClockTiming (TimerQueueItem)
14: front ( )
15: empty ( )
16: SetTimeEvent
Figure 16 Multimedia System Callback.
FreeRunning holds one event and overloads the virtual function
ReceiveClockTiming. ReceiveClockTiming causes FreeRunning to execute the
virtual function OutputFunction, which its descendant Metro overloads, causing
Metro to produce an output. ReceiveCallBackTime returns the next callback time
(see figure 18).
Algorithmic Composer, page 29
Scheduler
ScheduledItems : PriorityQueueDeletedItems : PriorityQueuewTimerId : unsigned int
SetTimeEvent( )KillTimeEvent( )Start( )Stop( )Pause( )Resume( )GetPosition( )OutputFunction( )
0..*
1TimerObject
ReceiveClockTiming( )Purge( )
TimerQueueItem
CallackTime : DWORDpTimer : TimerObject*
operator ==( )operator <( )
0..*
1
FreeRunning
NextEvent : TimerQueueItemwInterval : unsignedfIsRunning : bool
Start( )Stop( )SetClockInterval( )OutputFunction( )ReceiveClockTiming( )IsRunning( )Purge( )
Metro
OutputFunction( )
Causes output from Outlet 0
Figure 17 Free Running Class.
: Scheduler : FreeRunning : Metro : OutletContainer
: TimerObject
1: ReceiveClockTiming (TimerQueueItem)
2: OutputFunction ( )3: ProduceOutput ( )
virtual functions
4: return next callback time
Figure 18 Metro Sequence Diagram.
DelayLine has a priority queue of DelayLineQueueItems that has the DWORD
attribute lparam, which is received from the member function call GoOneShot
through DelayLine ancestor (see figure 19). When a Scheduler calls
Algorithmic Composer, page 30
ReceiveClockTiming, the DelayLineQueueItem is taken from the front of the queue,
and the lparam value is used as the argument in the OutputFunction, which is
overloaded by the sub-class class (see figure 20 and 21). Delay uses the lparam as a
pointer to a message cell, whereas Sequencer does not use lparam. Purging
DelayLine causes it to call PurgeItem for each item in qParam.
DelayLine
qParam : DelayLinePriorityQueue
ReceiveClockTiming( )Purge( )OutputFunction( )GoOneShot( )PurgeItem( )
2
Scheduler
0..*1
TimerObject
0..*TimerQueueItem 0..*
1
TimerPriorityQueue
2
0..*calls
1
DelayLinePriorityQueue
empty( )front( )push( )pop( )
1DelayLineQueueItem
CallbackTime : DWORDlparam : DWORD
operator <( )operator ==( )
0..*0..*
Figure 19 Delay Line Diagram.
Algorithmic Composer, page 31
: Delay : OutletContainer
1: VoidInlet (unsigned int)
: MessageCell : DelayLinePriorityQueue
: DelayLineQueueItem
+ : Scheduler
2: MessageCell ( )
3: GoOneShot (unsigned)
4: DelayLineQueueItem (DWORD, DWORD)
5: push (DelayLineQueueItem)
6: SetTimeEvent (TimerQueueItem)
Figure 20 Set Delay Event.
: Scheduler : DelayLine : Delay : OutletContainer
: DelayLinePriorityQueue
1: ReceiveClockTiming (TimerQueueItem)
2: front ( )
3: pop ( )
4: OutputFunction (DWORD)
5: ProduceOutput ( )6: return NULL
Figure 21Delay Receive Callback.
Engine Bridge.
The user interface receives data from the engine through standard C function
calls. Implementing the engine in Windows 95 for later releases will require the
main engine to exist in a 16-bit DLL, which will require thunking with the 32-bit
Algorithmic Composer, page 32
process. Data alignment in 16-bit processes is different to data alignment in 32-bit
processes and so only certain types of data structures can be passed through the thunk
compiler.17 Class structures cannot pass through the thunk layer; therefore pointers to
the BaseShell and Connector objects cannot be de-referenced by the user interface. To
overcome this limitation, they are converted to DWORDs and passed as a parameter
to the function in the Bridge that accesses the BaseShell or Connector (see figure 22).
The Bridge casts the DWORD to the appropriate pointer for the function and de-
references it within the same DLL. For example:
#define DWORD unsigned long;#define P_BASESHELL DWORD;
unsigned BaseShellGetNumInlets (P_BASESHELL pObject){
return ((BaseShell*)pObject) ->GetNumInlets();}
: BridgeSome Object in User Interface
: BaseShell
1: BaseShellGetNumInlets (DWORD pObject)
2: GetNumInlets ( )
Cast pObject to BaseShell*
3: return value4: return value
Figure 22 Calling BaseShell through Bridge.
17 “Handling Data Types Not Supported by the Thunk Compiler,” Microsoft SoftwareDevelopment Network Online Library:http://premium.microsoft.com/isapi/devonly/prodinfo/msdnprod/msdnlib.idc?theURL=/msdn/library/sdkdoc/win95/tc_2ugj.htm.
Algorithmic Composer, page 33
Timing messages for the engine would occur during interrupt time, which
means the engine cannot call a function to the 32-bit process. The engine posts a
message instead, using the window handle of the window in the 32-bit process it
needs to communicate with. For example
void Trigger::Send(){tpOutlet[0]->ProduceOutput(); if(DisplayWindow)
PostMessage (DisplayWindow, TRIGGER_MESSAGE,(DWORD)this, NULL);
}
Header files required to interface to the engine are at Appendix A.
User Interface.
The user interface uses two classes to control memory management within the
interface. The TBaseShellHook and the TConnectorHook classes own all the memory
for visual component library (VCL) objects associated with BaseShells and
Connectors, which in turn are owned by the Patch Form (see figures 23 and 24).
Algorithmic Composer, page 34
Dashed Lines Point to Owner of Memory
PatchTreeView 1
Owner
1
*
TTreeView<<Window>>
TPatchForm<<Window>>
1
1
Owner
1
0..1
TBaseShellEditForm<<Window>>
pViewNode
1
TTreeNode<<Icon>>
*
Data0..1
0..*
Parent1
TPerformanceView<<Window>>
TBaseShellHook
pHook : P_BASESHELLpEditForm : TBaseShellEditForm*
1
0..1
1
0..1
TObjectBox<<Icon>>
0..*
1
Figure 23 TBaseShellHook Ownership
Algorithmic Composer, page 35
*
PatchTreeView 1
TTreeView<<Window>>
Owner
1
1
pEditForm0..1
TConnectorEditForm<<Window>>
pViewNode
TTreeNode
*Data
TPatchForm<<Window>>
1
1
TPerformanceView<<Window>>
TConnectorHook
1
0..1
TConnectorLine<<Icon>>
Figure 24 Connector Hook Ownership.
TBaseShellHooks are always deleted through the PatchForm. The
TBaseShellHook determines whether it needs to call a delete function upon the
BaseShell through the bridge. The TBaseShellHook automatically deletes any
windows or icons that are dependent upon it. TConnectorHook operates in the same
way.
Invoking an edit window or creating an icon for a particular type of object is
achieved in the same way as it is done in the engine. TBaseShellEditForm is a super-
class to all the different types of edit windows, whereas the TObjectBox is a super-
class to the different types of icons on the Performance View. Each type of edit
window and icon has a static Create function that is invoked to create it. The
TTypeElement class contains a map with function call associated with the type name
of the object (see figure 25).
Algorithmic Composer, page 36
TObjectBox
pObject : P_BASESHELLOwner : TBaseShellHook*Parent : TPerformanceView
<<Icon>>
TBaseShellEditForm
pObject : P_BASESHELLpViewNode : TTreeNode*
<<Window>>
TNumberBox
Create( )
<<Icon>>InletSwitchSwitchBox
Create( )
<<Icon>>
TNumberStoreEditForm
Create( )TNumberStoreEditForm( )
<<Window>>
More Sub-class Types
InletSwitchEditForm
Create( )
<<Window>>
Figure 25 Edit Window and Icon Inheritance Diagram.
DisplayEditForm function call is made to the TBaseShellHook that is associated with
the underlying BaseShell. If TBaseShellHook.pEditForm == NULL, a call to
TTypeElementList::GetCreateForm( string Type) returns the pointer to the static
create function for the edit window associated with the type. The create function is
called, which creates a new edit window, and returns a pointer to the new edit
window. The pointer is stored inside the TBaseShellHook.pEditForm (see figure 26).
TBaseShellHook calls Show upon its pEditForm attribute. The edit window releases
all it resources and notifies its owner, which sets pEditForm to NULL, upon closing.
The super-class, TBaseShellEditForm has a thread that updates the information on the
window when the window is not focused, which enables the user to read and set the
underlying values. The sub-classes overload the virtual functions LoadData and
StoreButtonClick to enable them to load and store class specific data (see figure 27).
Algorithmic Composer, page 37
Some Call to Display Edit Form
: TBaseShellHook
: TTypeElementList
: TNumberStoreEditForm
1: DisplayEditForm ( )
3: GetCreateForm (string)
2: GetType ( )
AssumeType = NumberStore
returns "NumberStore"
returns TNumberStoreEditForm::Create
4: Create (TBaseShellHook*)
5: TNumberStoreEditForm (TBaseShellHook*)
6: Show ( )
Figure 26 Display Edit Form Sequence.
Algorithmic Composer, page 38
TNumberBoxEditForm
NumberStoreSpecific : TComponent
Create( )LoadData( )StoreButtonClick( )
MessageStoreEditForm
MessageStoreSpecific : TComponent
Create( )LoadData( )StoreButtonClick( )
TThread
Terminated : bool
Execute( )Terminate( )
TBaseShellEditForm
pObject : P_BASESHELLBaseShellCommon : TComponent
StoreButtonClick( )EditNameClick( )EditCommentClick( )FormClose( )ResetButtonClick( )InletTabChange( )OutletTabChange( )CancelButtonClick( )UpdateButtonClick( )InletsListDblClick( )EditNameExit( )EditCommentExit( )FormShow( )OutletsListStartDrag( )OutletsListMouseDown( )OutletsListDblClick( )InletsListDragOver( )OutletsListDragOver( )InletsListStartDrag( )InletsListMouseDown( )InletsListDragDrop( )OutletsListDragDrop( )LocateButtonClick( )PageControl1Change( )BaseShellSendButtonClick( )EditNameChange( )EditCommentChange( )DragToView1Click( )DragToViewButtonStartDrag( )OutletsListClick( )OutletsListEnter( )OutletsListExit( )OutletConnectorUpDownClick( )REorderButtonClick( )StoreOutletConnectors( )StoreName( )StoreComment( )LoadType( )LoadName( )LoadComment( )LoadInletsList( )LoadOutletsList( )SetInletsTabs( )SetOutletsTabs( )TBaseShellEditForm( )UpdateForm( )~TBaseShellEditForm( )LoadData( )GetPatchForm( )HideConnectionImages( )
TFormRefresh
name : type = initval
PerformUpdata( )Execute( )
TEditPatch
PatchFormSpecific : TComponent
Create( )LoadData( )StoreButtonClick( )LoadInletPorts( )LoadOutletPorts( )StoreInletPorts( )StoreOutletPorts( )
FlipFlopEditForm
FlipFlopFormSpecific : TComponent
Create( )LoadData( )StoreData( )
Figure 27 TBaseShellEditForm Class Diagram.
Implementation of the performance view was in two separate packages, both
reliant upon the VCL. I created a package specifically for the graphical icons on the
Algorithmic Composer, page 39
performance view. This will enable me to change the implementation of the icons
and lines away from the main program (see figure 28).
mainprogramgraphics
vcl
Figure 28 Graphics Separation.
1
TGraphicControl(from vcl)
Parent
0..*
TWinControl(from vcl)
10..*
TGraphicShape
BottomFollowerLeader
0..1
TGraphicControlBox
TopFollower2
FollowerTLineFollow
Leader
TGraphicBoxFollow
0..12
Represent BaseShellsRepresent Inlets and outlets
Respresent Connectors
Parent
TGraphicLine
Figure 29 Graphics Inheritance.
Algorithmic Composer, page 40
TGraphicControl, TGraphicBoxFollow, and TGraphicLine are descended from
TGraphicControl in the VCL library, which enables these sub-classes to inherit the
ability to respond to the mouse events, and also to display images upon a canvas.
TGraphicControl must exist on a TWinControl type object from the VCL (see figure
29). TGraphicControl has two vectors of pointers to TGraphicBoxFollow type
objects, which have a vector of pointers to TLineFollow type objects (see figure 30).
The leaders notify the followers to follow, which cause the followers to update their
position through their leader. TGraphicControl calls the function NotifyFollowers
upon itself, which iterates through the TopFollowers and BottomFollowers vectors to
call NotifyFollowers in each TGraphicBoxFollow object. TGraphicBoxFollow gets
its position from TGraphicControl, and calls the function NotifyFollowers on itself,
which iterates through its vector of pointers to TLineFollowers, which update their
position (see figure 31)
.
Algorithmic Composer, page 41
TGraphicControlBoxwMinWidth : unsigned intwMinHeight : unsigned intTopFollowers : :vectorBottomFollowers : vector
AddFollower( )AddFollower( )TGraphicControlBox( )RemoveFollower( )ShowObject( )AdjustMinWidth( )GetFollower( )NotifyFollowers( )GetOffset( )ProcessDrag( )MouseDown( )MouseMove( )DoStartDrag( )DragOver( )DoEndDrag( )
TopFollowers, BottomFollowers
#Leader0..1 2
TLineFollow
TGraphicBoxFollow__fastcallwFollowerNum : const unsigned int
TGraphicBoxFollow( )Follow( )~TGraphicBoxFollow( )Position( )Position( )AddFollower( )RemoveFollower( )NotifyFollowers( )DragOver( )ProcessDragOver( )
0..1 2
Follower
Leader
Figure 30 Graphics Icons Relationship Diagram.
Algorithmic Composer, page 42
Drag Event from System
: TGraphicControlBox
: TGraphicBoxFollow
: TLineFollow
1: ProcessDrag (int, int)
3: NotifyFollowers (bool Finished)
4: Follow (bool Finished)
5: GetOffset (unsigned int, bool)
7: NotifyFollowers (bool)
8: Follow (bool)
9: Paint ( )
2: Paint ( )
6: Paint ( )
Figure 31 Graphic Package Follow Sequence.
The next level of abstraction associates sub-classes from the Graphic Package
to the BaseShell and Connector classes. TObjectBox descends from TGraphicControl
and represents the BaseShell. TObjectBox is owned by TBaseShellHook but has
TViewForm as its parent. TObjectSocket represents the inlets and outlets of the
BaseShell. Its position in the TopFollower or BottomFollower determines its inlet or
Algorithmic Composer, page 43
outlet number, while the attribute fIsTop determines whether it is an inlet or outlet
(see figure 32).
TObjectSocket
wSocketNumber : unsigned intpObject : P_BASESHELLfIsTop : bool
GetPatchForm( )TObjectSocket( )GetSocketDetails( )DragOver( )DoStartDrag( )DragDrop( )MouseDown( )MouseUp( )ShowConnectors( )
TObjectBox
DragType : unsigned intpObject : P_BASESHELL
TObjectBox( )Detach( )~TObjectBox( )GetObject( )GetHook( )GetPatchForm( )GetViewForm( )PlaceObject( )HasControls( )ControlDisplayed( )UpdateDisplay( )DisplayControl( )MouseUp( )MouseDown( )DoStartDrag( )
TGraphicBoxFollow
(from graphics)
TGraphicControlBox
(from graphics)
TopFollowers, BottomFollowers
#Leader 0..12 0..12
Figure 32 TObjectBox and TObjectSocket.
TObjectBox determines how many inlets or outlets it requires through calls to
BaseShellGetNumInlets and BaseShellGetNumOutlets in the bridge, creates and then
stores pointers to the subsequent TObjectSocket objects in its TopFollowers and
BottomFollowers vectors. The name of the inlet or outlet is acquired through the
bridge and stored in the Hint property of the TObjectSocket. The enables the name of
the inlet or outlet to display next to the mouse or in the status bar when the mouse
moves over the inlet or outlet of the object (see figure 33).
Creating a connection between objects on the performance view is done
through a drag and drop operation. The TObjectSocket creates a Connector that is not
connected to anything, and a TDragConnector Object.
Algorithmic Composer, page 44
: Bridge : TViewForm : TObjectBox : TGraphicBoxFollow
1: TObjectBox (TBaseShellHook*, TViewForm*)
2: BaseShellGetNumInlets (argtype)
3: TGraphicBoxFollow (TGraphicControlBox*, int, bool)
4: AddFollower (TGraphicBoxFollow*, bool)
6: BaseShellGetNumOutlets (P_BASESHELL)
7: TGraphicBoxFollow (TGraphicControlBox*, int, bool)
8: AddFollower (TGraphicBoxFollow*, bool)
5: BaseShellGetInletName (P_BASESHELL, int, LPSTR)
9: BaseShellGetOutletName (P_BASESHELL, int, LPSTR)
Figure 33 TObjectBox Creation.
Upon starting a drag, which is done by moving the mouse over the socket and holding
the left mouse button down, the cursor changes into a hand holding a plug. The inlet
or outlet details of the Connector are set or unset by moving mouse over another
socket. The TObjectSocket queries the BaseShell through the bridge as to whether it
can accept a connection. If a connection is acceptable, the cursor changes into a plug
with no hand, otherwise it remains held. Upon drag end, if the TDragConnector was
accepted by a TObjectSocket, the TObjectSocket calls Connect to the
TDragConnector, which calls BaseShellConnect function through the bridge and adds
a new TConnectorHook to the user interface through TPatchForm, otherwise the
Algorithmic Composer, page 45
Connector is deleted through the TDragConnector. TPatchForm queries all
performance views as to whether it can add this particular connector (see figure 34).
User presses mouse over outlet : (system)
Connect From : TObjectSocket
: TDragConnector
MouseOver : TObjectSocket
: TPatchForm : TViewForm : TConnectorHook
: Bridge
1: MouseDown (TMouseButton, TShiftState, int, int)
4: TDragConnector (P_CONNECTOR, bool)
3: ConnectorCreate ( )
8: DragOver (TObject*, int, int, TDragState, bool&)
5: SetOutlet ( )
2: DoStartDrag (TDragObject*&)
14: DragDrop (TObject*, int, int)
9: SetInlet ( )
12: CanConnectInlet ( )
13: BaseShellCanConnectInlet (P_BASESHELL, int, P_CONNECTOR)
15: MakeConnection ( )
19: AddConnector (TConnectorHook*)
16: ConnectorMakeConnection (P_CONNECTOR)
6: ConnectorSetOutletBase (P_CONNECTOR, P_BASESHELL)
7: ConnectorSetOutletNum (P_CONNECTOR, int)
10: ConnectorSetInletBase (P_CONNECTOR, P_BASESHELL)
11: ConnectorSetInletNum (P_CONNECTOR, int)
20: AddConnector (TConnectorHook*)
18: TConnectorHook (TComponent*, P_CONNECTOR)
17: GetPatchForm ( )
Figure 34 Performance View Make Connection Sequence Diagram.
TViewForm first checks whether it already has the Connector in its
TConnectorMap. It then gets the inlet and outlet BaseShell pointers and checks
whether they are both in the ObjectMap. If both are in the map, TViewForm gets the
TObjectBox associated with the BaseShell pointers and using the inlet and outlet
Algorithmic Composer, page 46
numbers, gets the TObjectSocket associated with the inlet and outlet number. A new
TConnectorLine is created and becomes associated with the TObjectSocket through
their super-class functions (see figures 35 and 36).
The patch is stored in two files, one each for the engine and interface. The
performance views are stored with details of the object position within the patch
instead of the old pointer value as used in the streaming of the engine. Future
implementations will use a single file for both parts.
Algorithmic Composer, page 47
TObjectBoxDragType : unsigned intpObject : P_BASESHELLNormalyVisible : bool
TObjectBox( )Detach( )~TObjectBox( )GetObject( )GetHook( )GetPatchForm( )GetViewForm( )PlaceObject( )HasControls( )ControlDisplayed( )UpdateDisplay( )DisplayControl( )MouseUp( )MouseDown( )DoStartDrag( )
1
pParentForm
0..1
1
1
TViewFormNumColumns : unsigned intRowHeight : unsigned intColumnWidth : unsigned intObjectMap : mapConnectorMapDisplayMode : boolpRefresher : TViewRefresh
FormDragOver( )FormCloseQuery( )FormDestroy( )FormClose( )SaveView1Click( )AutoArrangeClick( )ObjectNormallyVisibleClick( )ObjectNormallyHiddenClick( )ObjectPopupPopup( )ArrangeConnectorsClick( )ConnectorPopupMenuPopup( )ConnectorNormallyVisibleClick( )ConnectorNormallyHiddenClick( )ArrangeConnectorClick( )ShowHideButtonClick( )SocketHideConnectorsClick( )SocketShowConnectorsClick( )DisplayControlItemClick( )NumberBoxPopupPopup( )NoControl1Click( )NumberBox1Click( )VerticalSlider1Click( )HorizontalSlider1Click( )Guage1Click( )NewObject1Click( )FormCreate( )HideControl1Click( )DeleteFromPatch1Click( )RemoveFromView1Click( )DeleteConnector( )EditObject1Click( )FormDragDrop( )DragToView1Click( )FormMouseUp( )NoteName1Click( )ResetObject1Click( )EditDetails1Click( )ViewPopupMenuPopup( )TViewForm( )TViewForm( )UpdateView( )PlaceForm( )AddObject( )AddObject( )AddConnector( )UpdateForm( )AutoArrange( )StoreView( )GetPatchForm( )LoadView( )Detach( )Detach( )RemoveConnector( )RemoveObject( )
#pParentForm
0..1
1
ConnectorMapKey : P_CONNECTORAssociation : TConnectorLine*
operator[]( )Count( )Insert( )Erase( )
1
TConnectorLinepCon : P_CONNECTOR
TConnectorLine( )AutoArrange( )~TConnectorLine( )GetObject( )GetHook( )Detach( )GetPoints( )StorePoints( )MouseDown( )DoStartDrag( )DragOver( )DragDrop( )
0..1
1
ObjectMapKey : P_BASESHELLAssociation : TObjectBox*NormallyVisible : bool
operator[]( )Count( )Insert( )Erase( )
1
0..1
1
Figure 35 Performance View Class Diagram.
Alg
orit
hmic
Co
mpo
ser,
pag
e48
: C
onne
ctor
Map
Par
ent P
atch
: T
Pat
chF
orm
: T
Vie
wF
orm
: T
Con
nect
orH
ook
: B
ridge
: T
Con
nect
orLi
neF
rom
Obj
ect :
T
Obj
ectB
oxT
o O
bjec
t :
TO
bjec
tBox
To
Soc
ket :
T
Obj
ectS
ocke
tF
rom
Soc
ket :
T
Obj
ectS
ocke
t :
Obj
ectM
ap
1: A
ddC
onne
ctor
(T
Con
nect
orH
ook*
)
2: G
etH
ook
( )
4: C
onne
ctor
Get
Inle
tBas
e (P
_CO
NN
EC
TO
R)
6: C
ount
(P
_BA
SE
SH
ELL
)
3: C
ount
(P
_CO
NN
EC
TO
R)
5: C
onne
ctor
Get
Out
letB
ase
(P_C
ON
NE
CT
OR
)
7: C
ount
(P
_BA
SE
SH
ELL
)
9: o
pera
tor[
] (P
_BA
SE
SH
ELL
)
14: o
pera
tor[
] (P
_BA
SE
SH
ELL
)
10: C
onne
ctor
Get
Inle
tNum
(P
_CO
NN
EC
TO
R)
15: C
onne
ctor
Get
Out
letN
um (
P_C
ON
NE
CT
OR
)
8: T
Con
nect
orLi
ne (
TC
onne
ctor
Hoo
k*, T
Vie
wF
orm
*)
11: G
etF
ollo
wer
(un
sign
ed in
t, bo
ol Is
Top
)
12: A
ddF
ollo
wer
(T
Line
Fol
low
*)
13: S
tart
Lead
er (
TG
raph
icB
oxF
ollo
w*)
16: G
etF
ollo
wer
(un
sign
ed in
t, bo
ol Is
Bot
tom
)
17: A
ddF
ollo
wer
(T
Line
Fol
low
*)
18: E
ndLe
ader
(T
Gra
phic
Box
Fol
low
*)
Que
ry b
oth
Bas
eShe
lls
Join
to In
let O
bjec
t
Join
to O
utle
t O
bjec
t
Fig
ure
36 P
erfo
rman
ce V
iew
Add
Con
nect
or S
eque
nce.
Algorithmic Composer, page 49
Conclusion.
The current version of Algorithmic Composer has met the specifications I set
for myself at the beginning of the project, and has more features than I had originally
anticipated. I was able to find limitations to the program while using it to compose. In
some instances I made immediate changes to the program, while in other instances I
decided to improve later – including the timing algorithm. I have included a compact
disk containing three pieces that demonstrate some musical applications of
Algorithmic Composer. Each track demonstrates an aspect of the program that
fulfilled a musical purpose.
Track one, Be Still, is a new work of mine that is still in its compositional
stage. I have been able to experiment with different sound textures and timing
structures using Algorithmic Composer. The work is recorded live and demonstrates
the ability of Algorithmic Composer to enable the composer to experiment with
multiple MIDI channels simultaneously.
Track two, Table of Knowledge, is written by Jeff Dunn and performed by Jeff
Dunn and myself. This was Jeff’s first exposure to Algorithmic Composer and
demonstrates the ease at which a composer can use this program. I worked through
the program operation and patch construction with Jeff for approximately thirty
minutes, after which time Jeff was able to construct the patch and compose this piece
with virtually no input from me even though he has had no previous experience with
MAX.
Track three is an excerpt from Whirling Wheels, a work I wrote in 1997 using
MAX. I included this excerpt to demonstrate the ability of using Algorithmic
Composer for pieces created in MAX. Apart from manipulating sliders on the
Algorithmic Composer, page 50
computer display with the mouse, I perform Whirling Wheels through note, controller,
and pitch bend messages from a MIDI keyboard.
I am currently organizing demonstrations of Algorithmic Composer to
musicians from the Newcastle Conservatorium of Music through Terry Latham, who
is a lecturer in Music Technology there. I plan to continue development of this
package for my musical career as both a composer and performer, for the benefit of
the University of Western Sydney, and for all musicians who choose to compose and
perform with these types of tools.
Algorithmic Composer, page 51
Bibliography
Dale, Nell and Chip Weems. Introduction to Pascal and Structured design, fourthedition. Boston: Jones and Bartlett, 1997.
“Handling Data Types Not Supported by the Thunk Compiler,” Microsoft SoftwareDevelopment Network Online Library:http://premium.microsoft.com/isapi/devonly/prodinfo/msdnprod/msdnlib.idc?theURL=/msdn/library/sdkdoc/win95/tc_2ugj.htm.
Inprise newsgroups. Server: forums.inprise.com, newsgroup: borland.public.cpp, 20September 1998. www.inprise.com.
Lippman, Stanley B. and Josée Lajoie. C++ Primer, third edition. Reading,Massachusetts: Addison-Wesley, 1988.
McCulley, Mark. “Overcoming Timer-Latency Problems in MIDI Sequencers,”Microsoft Software Development Network Online Library (1996):http://premium.microsoft.com/isapi/devonly/prodinfo/msdnprod/msdnlib.idc?theURL=/msdn_mlatency.htm.
Messick, Paul. Maximum MIDI: Music Applications in C++. Greenwich CT:Manning, 1988.
Petzold, Charles. Programming Windows 95, fourth edition. Redmond: MicrosoftPress, 1996.
Pressing, Jeff. Synthesizer Performance and Real-Time Technique. Oxford: OxfordUniversity Press, 1992.
Reisdorph, Kent. Teach Yourself Borland C++ Builder in 14Days. Indiana: SAMS,1998.
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 52
Hea
der
File
s R
equi
red
for
Inte
rfac
ing
to E
ngin
e
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
*
Typ
eNam
es.h
*
this
co
nta
ins
defin
itio
ns o
f the
typ
e cl
asse
s a
nd t
he t
ype
nam
es a
sso
ciat
ed w
ith t
hem
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
#ifn
de
f TY
PE
NA
ME
S_
H#d
efin
e T
YP
EN
AM
ES
_H
#de
fine
INLE
TP
OR
T_T
YP
E
"Pat
chIn
letP
ort
"#d
efin
e O
UT
LET
PO
RT
_TY
PE
"P
atch
Out
letP
ort"
#de
fine
CO
NN
EC
TO
R_T
YP
E "
Co
nne
cto
r"#d
efin
e C
AL
CU
LA
TE
_TY
PE
"C
alc
ula
te"
#de
fine
CO
UN
TE
R_T
YP
E "
Co
unte
r"#d
efin
e D
EL
AY
_TY
PE
"D
ela
y"#d
efin
e D
ISP
LAY
_TY
PE
"D
isp
lay"
#d
efin
e F
LIP
FLO
P_
TY
PE
"F
lipF
lop"
#d
efin
e M
ES
SA
GE
ST
OR
E_
TY
PE
"M
essa
geS
tore
"#d
efin
e M
ET
RO
_TY
PE
"M
etro
"#d
efin
e P
AT
CH
_TY
PE
"P
atch
"#d
efin
e S
ELE
CT
OR
_TY
PE
"S
elec
tor"
#de
fine
ST
DM
IDIO
UT
_TY
PE
"M
idi O
ut"
#de
fine
ST
DM
IDII
N_T
YP
E "
Mid
i In"
#de
fine
SW
ITC
H_O
UT
LET
S_T
YP
E "
Out
lets
Sw
itch"
#de
fine
SW
ITC
H_I
NLE
TS
_TY
PE
"In
lets
Sw
itch"
#de
fine
TO
GG
LE_T
YP
E "
To
ggle
"#d
efin
e T
RIG
GE
R_T
YP
E "
Trig
ger"
#de
fine
PA
TC
H_
FIL
E_I
D "
Pat
ch fr
om
File
"#d
efin
e T
AB
LE_T
YP
E "
Tab
le"
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 53
#de
fine
NU
MB
ER
ST
OR
E_T
YP
E "
Num
ber
Sto
re"
#de
fine
RA
ND
OM
GE
N_T
YP
E "
Ran
dom
Gen
"#d
efin
e S
EQ
UE
NC
ER
_TY
PE
"S
eque
ncer
"#e
ndif
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
*
Win
dow
sMes
sage
s.h
*
Def
ines
the
win
dow
me
ssag
e fo
r ca
lls u
sing
Po
stM
essa
ge**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/
#ifn
def W
IND
OW
S_M
ES
SA
GE
S_H
#de
fine
WIN
DO
WS
_ME
SS
AG
ES
_H//
defin
e w
indo
ws
me
ssag
es h
ere
#de
fine
DIS
PLA
Y_D
ELE
TE
D (
WM
_US
ER
+1)
#de
fine
DIS
PLA
Y_M
ES
SA
GE
(W
M_U
SE
R +
2)
#de
fine
ER
RO
R_
ME
SS
AG
E
(W
M_U
SE
R +
3)
#de
fine
TR
IGG
ER
_ME
SS
AG
E (
WM
_US
ER
+ 4
)#d
efin
e T
RIG
GE
R_D
ELE
TE
D (
WM
_US
ER
+ 5
)
#end
if
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 54
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**
B
ridge
.h*
Hea
der
for
the
Alg
orit
hmic
Co
mpo
ser
Eng
ine
Bri
dge
* D
ecla
res
all
func
tions
req
uire
d to
inte
rfac
e to
the
eng
ine
* ****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/#
ifnde
f BR
IDG
E_H
#de
fine
BR
IDG
E_H
#in
clud
e "T
yped
efs
.h"
#ifd
ef _
PA
SS
_CL
AS
S_P
OIN
TE
RS
//o
nly
for
debu
ggin
g w
ith t
he e
ngin
e#
incl
ude
"Pat
ch.h
"#e
ndif
#ifd
ef _
_cp
lusp
lus
exte
rn "
C"
{
// A
ssu
me
C d
ecla
ratio
ns fo
r C
++
#end
if
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**C
om
mo
n In
terf
ace
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
// C
onv
ersi
on
of M
IDI
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T N
umbe
rTo
Mid
i(un
sig
ned
Nu
mV
al,
LPS
TR
Buf
);P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Mid
iTo
Nu
mbe
r(LP
ST
R s
zNot
eNa
me,
int*
Res
ult)
;
//E
rror
Inte
rfac
eP
RE
FIX
b
ool W
INA
PI
EX
PO
RT
Get
Err
orM
essa
ge(
LPS
TR
Bu
f);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Set
Err
orW
ind
ow
(HW
ND
hW
nd);
//a
ll re
ma
inin
g fu
nctio
ns a
ssu
me
the
first
arg
ume
nt is
a v
alid
//if
it is
a p
oin
ter
repr
esen
atat
ion
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 55
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
*Id
entit
y cl
ass
acc
ess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Iden
tityG
etN
ame(
P_
IDE
NT
ITY
dw
pId
entit
y, L
PS
TR
Bu
f);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Iden
tityG
etC
om
me
nt(P
_ID
EN
TIT
Y d
wpI
den
tity,
LP
ST
R B
uf)
;P
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T Id
entit
yGet
Typ
e(P
_ID
EN
TIT
Y d
wp
Iden
tity,
LP
ST
R B
uf);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Iden
tityS
etN
ame(
P_
IDE
NT
ITY
dw
pId
entit
y, L
PS
TR
Bu
f);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Iden
tityS
etC
om
me
nt(P
_ID
EN
TIT
Y d
wp
Iden
tity,
LP
ST
R B
uf);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Iden
tityS
etM
odi
fied
(P_
IDE
NT
ITY
dw
pId
entit
y, b
oo
l Mo
difi
ed);
PR
EF
IX
boo
l WIN
AP
I E
XP
OR
T Id
entit
yGet
Mo
difi
ed(P
_ID
EN
TIT
Y d
wpI
dent
ity);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
*B
aseS
hell
clas
s ac
cess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/
PR
EF
IX
P_
BA
SE
SH
ELL
WIN
AP
I E
XP
OR
T B
aseS
hellC
reat
e(LP
ST
R T
ype,
P_
PA
TC
H p
Par
ent)
;
PR
EF
IX
P_
PA
TC
H W
INA
PI
EX
PO
RT
Bas
eShe
llGet
Par
ent(
P_
BA
SE
SH
ELL
dw
pS
he
ll);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Bas
eShe
llSet
Par
ent(
P_
BA
SE
SH
ELL
dw
pS
hell,
P_
PA
TC
H d
wp
Par
ent)
;P
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T B
aseS
hellR
eset
(P_
BA
SE
SH
ELL
dw
pS
hell)
;P
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T B
aseS
hellS
end
(P_
BA
SE
SH
ELL
dw
pS
hell)
;P
RE
FIX
b
ool W
INA
PI
EX
PO
RT
Bas
eShe
llCa
nSa
ve(P
_B
AS
ES
HE
LL d
wp
Sh
ell)
;
//ge
t si
ze//c
all
befo
re u
sing
the
re
ma
inin
g fu
nctio
nsP
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T B
aseS
hellG
etN
um
Inle
ts(P
_B
AS
ES
HE
LL d
wp
Sh
ell)
;P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T B
aseS
hellG
etN
um
Out
lets
(P_B
AS
ES
HE
LL d
wpS
hell)
;
//ge
t na
me
for
hint
s o
ver
inle
t o
r o
utle
t
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 56
//all
follo
win
g as
sum
e w
So
cket
Num
ber
in r
ang
eP
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T B
aseS
hellG
etIn
letN
am
e(P
_B
AS
ES
HE
LL d
wp
She
ll, u
nsig
ned
wS
ock
etN
um
, LP
ST
R B
uf);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Bas
eShe
llGet
Out
letN
am
e(P
_BA
SE
SH
ELL
dw
pShe
ll, u
nsig
ned
wS
ock
etN
um,
LPS
TR
Bu
f);
//ho
w m
any
co
nnec
tors
for
a pa
rtic
ula
r in
let
or o
utle
tP
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T B
aseS
hellG
etN
um
Inle
tCo
nne
cto
rs(P
_B
AS
ES
HE
LL d
wp
She
ll,u
nsig
ned
wS
ock
etN
um
);P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T B
aseS
hellG
etN
um
Out
letC
onn
ecto
rs(P
_BA
SE
SH
ELL
dw
pShe
ll, u
nsig
ned
wS
ock
etN
um);
//te
st fo
r ab
ility
to
conn
ect
PR
EF
IX
boo
l WIN
AP
I E
XP
OR
T B
aseS
hellC
anC
onn
ectI
nlet
(P_B
AS
ES
HE
LL d
wpS
hell,
uns
igne
d w
So
cket
Num
, P
_CO
NN
EC
TO
R d
wpC
on)
;P
RE
FIX
b
ool W
INA
PI
EX
PO
RT
Bas
eShe
llCa
nCo
nnec
tOut
let(
P_B
AS
ES
HE
LL d
wpS
hell,
uns
igne
d w
So
cket
Num
, P
_CO
NN
EC
TO
Rdw
pCo
n);
//ge
t co
nnec
tor
at in
de
x//
assu
mes
Ind
ex
is v
alid
PR
EF
IX
P_C
ON
NE
CT
OR
WIN
AP
I E
XP
OR
T B
aseS
hellG
etIn
letC
onn
ecto
r(P
_BA
SE
SH
ELL
dw
pShe
ll,u
nsig
ned
wS
ock
etN
um,
unsi
gne
dIn
dex)
;P
RE
FIX
P
_CO
NN
EC
TO
R W
INA
PI
EX
PO
RT
Bas
eShe
llGet
Out
letC
onn
ecto
r(P
_BA
SE
SH
ELL
dw
pShe
ll, u
nsig
ned
wS
ock
etN
um,
unsi
gne
dIn
dex)
;
// fi
nd t
he C
onn
ect
or
// a
ssu
me
s dw
pCo
n is
in t
his
sock
etP
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T B
aseS
hellF
indO
utle
tCo
nnec
torI
ndex
(P_B
AS
ES
HE
LL d
wpS
hell,
uns
igne
d w
So
cket
Num
,P
_CO
NN
EC
TO
R d
wpC
on)
;P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T B
aseS
hellF
indI
nlet
Co
nnec
torI
ndex
(P_B
AS
ES
HE
LL d
wpS
hell,
uns
igne
d w
So
cket
Num
,P
_CO
NN
EC
TO
R d
wpC
on)
;
//as
sum
es b
oth
inde
xes
are
valid
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Bas
eShe
llSw
apO
utle
tCo
nnec
tor(
P_B
AS
ES
HE
LL d
wpS
hell,
uns
igne
d O
utle
tNu
mbe
r, u
nsig
ned
Co
nnec
tor1
,un
sig
ned
Co
nnec
tor2
);
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 57
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
*C
onn
ecto
r cl
ass
acce
ss fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
//te
st if
full
conn
ectio
n e
xist
sP
RE
FIX
b
ool W
INA
PI
EX
PO
RT
Co
nnec
torI
sVa
lid(P
_CO
NN
EC
TO
R d
wpC
on)
;
//fin
d o
ut a
bout
Co
nnec
tor
PR
EF
IX
P_B
AS
ES
HE
LL W
INA
PI
EX
PO
RT
Co
nnec
torG
etIn
letB
ase(
P_C
ON
NE
CT
OR
dw
pCo
n);
PR
EF
IX
uns
igne
d W
INA
PI
EX
PO
RT
Co
nnec
torG
etIn
letN
um
(P_C
ON
NE
CT
OR
dw
pCo
n);
PR
EF
IX
P_B
AS
ES
HE
LL W
INA
PI
EX
PO
RT
Co
nnec
torG
etO
utle
tBas
e(P
_CO
NN
EC
TO
R d
wpC
on)
;P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T C
onn
ecto
rGet
Out
letN
um(P
_CO
NN
EC
TO
R d
wpC
on)
;
//fin
d po
sitio
n in
Out
let
PR
EF
IX
uns
igne
d W
INA
PI
EX
PO
RT
Co
nnec
torG
etO
utle
tInd
ex(P
_CO
NN
EC
TO
R d
wpC
on)
;
PR
EF
IX
P_P
AT
CH
WIN
AP
I E
XP
OR
T C
onn
ecto
rGet
Par
ent(
P_C
ON
NE
CT
OR
dw
pCo
n);
//us
e fo
r te
stin
g ac
cept
abili
ty o
f co
nnec
tor
//do
es n
ot a
ctua
lly c
onn
ect
to t
he B
aseS
hell
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Co
nnec
torS
etIn
letB
ase(
P_
CO
NN
EC
TO
R d
wp
Co
n, P
_B
AS
ES
HE
LL d
wp
She
ll);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Co
nnec
torS
etIn
letN
um
(P_C
ON
NE
CT
OR
dw
pCo
n, u
nsig
ned
wS
ock
etN
um);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Co
nnec
torS
etO
utle
tBas
e(P
_CO
NN
EC
TO
R d
wpC
on,
P_B
AS
ES
HE
LL d
wpS
hell)
;P
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T C
onn
ecto
rSet
Out
letN
um
(P_C
ON
NE
CT
OR
dw
pCo
n, u
nsig
ned
wS
ock
etN
um);
//co
mp
lete
co
nnec
tion.
PR
EF
IX
boo
l WIN
AP
I E
XP
OR
T C
onn
ecto
rMak
eCo
nnec
tion(
P_C
ON
NE
CT
OR
dw
pCo
n);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Co
nnec
torS
etP
aren
t(P
_CO
NN
EC
TO
R d
wpC
on,
P_P
AT
CH
dw
pPar
ent)
;
PR
EF
IX
P_C
ON
NE
CT
OR
WIN
AP
I E
XP
OR
T C
onn
ect
orC
reat
e();
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 58
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Co
nnec
torD
elet
e(P
_CO
NN
EC
TO
R d
wpC
on)
;
PR
EF
IX
boo
l WIN
AP
I E
XP
OR
T C
onn
ecto
rCan
Sav
e(P
_C
ON
NE
CT
OR
dw
pC
on)
;
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* P
atch
Cla
ss a
cces
s fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
///
assu
mes
dw
pShe
ll e
xist
s in
thi
s pa
tch
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chD
etac
hBa
seS
hell(
P_
PA
TC
H d
wp
Pat
ch,
P_
BA
SE
SH
ELL
dw
pS
hell)
;P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T P
atch
Fin
dB
ase
She
llPo
sitio
n(P
_P
AT
CH
dw
pP
atch
, P
_B
AS
ES
HE
LL d
wp
She
ll);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chA
ddB
ase
She
ll(P
_PA
TC
H d
wpP
atch
, P
_BA
SE
SH
ELL
dw
pShe
ll);
PR
EF
IX
uns
igne
d W
INA
PI
EX
PO
RT
Pat
chN
um
ber
Bas
eShe
lls(P
_P
AT
CH
dw
pP
atch
);//
assu
mes
a v
alid
inde
xP
RE
FIX
P
_B
AS
ES
HE
LL W
INA
PI
EX
PO
RT
Pat
chF
ind
Bas
eSh
ell(
P_
PA
TC
H d
wp
Pat
ch,
uns
igne
d In
de
x);
//ca
uses
Co
nnec
tor
to b
eco
me
dele
ted
fro
m m
em
ory
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chD
etac
hCo
nnec
tor(
P_P
AT
CH
dw
pPat
ch,
P_C
ON
NE
CT
OR
dw
pCo
n);
//ca
ll a
fter
com
ple
tein
g a
conn
ectio
nP
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T P
atch
Add
Co
nnec
tor(
P_P
AT
CH
dw
pPat
ch,
P_C
ON
NE
CT
OR
dw
pCo
n);
PR
EF
IX
uns
igne
d W
INA
PI
EX
PO
RT
Pat
chN
umbe
rCo
nnec
tors
(P_P
AT
CH
dw
pPat
ch);
//as
sum
es a
va
lid in
dex
PR
EF
IX
P_C
ON
NE
CT
OR
WIN
AP
I E
XP
OR
T P
atch
Fin
dCo
nnec
tor(
P_P
AT
CH
dw
pPat
ch,
unsi
gne
d In
dex)
;
//ca
ll a
fter
dele
ting
any
Ba
seS
hells
to
see
if a
ny C
onn
ecto
rs w
ere
also
de
lete
dP
RE
FIX
P
_CO
NN
EC
TO
R W
INA
PI
EX
PO
RT
Pat
chG
etD
eadC
onn
ecto
r(P
_PA
TC
H d
wpP
atch
);
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 59
//sa
me
as
Bas
eShe
llCre
ate
for
Pat
ch I
nlet
s an
d O
utle
tsP
RE
FIX
P
_B
AS
ES
HE
LL W
INA
PI
EX
PO
RT
Pat
chA
dd
Inle
t(P
_P
AT
CH
dw
pP
atch
);P
RE
FIX
P
_B
AS
ES
HE
LL W
INA
PI
EX
PO
RT
Pat
chA
dd
Ou
tlet(
P_
PA
TC
H d
wp
Pat
ch);
PR
EF
IX
P_
PA
TC
H W
INA
PI
EX
PO
RT
Pat
chM
akeN
ew(L
PS
TR
Na
me)
;
//st
ream
ing
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chS
etF
ileN
am
e(P
_P
AT
CH
dw
pP
atch
, LP
ST
R F
ileN
am
e);
PR
EF
IX
P_
PA
TC
H W
INA
PI
EX
PO
RT
Pat
chLo
adP
atch
File
(LP
ST
R F
ileN
am
e, P
_P
AT
CH
dw
pP
aren
t);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chG
etF
ileN
am
e(P
_P
AT
CH
dw
pP
atch
, LP
ST
R F
ileN
am
e);
PR
EF
IX
boo
l WIN
AP
I E
XP
OR
T P
atch
Sa
ve(P
_P
AT
CH
dw
pP
atch
, LP
ST
R F
ileN
am
e);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chD
ele
te(P
_P
AT
CH
dw
pP
atch
);P
RE
FIX
v
oid
WIN
AP
I E
XP
OR
T P
atch
Set
Num
Vie
ws(
P_
PA
TC
H d
wp
Pat
ch,
uns
igne
d N
um
Vie
ws)
;P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T P
atch
Get
Num
Vie
ws(
P_
PA
TC
H d
wp
Pat
ch);
//alte
r th
e or
derin
g o
f inl
ets
and
out
lets
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chS
wap
Out
lets
(P_P
AT
CH
dw
pPat
ch,
unsi
gne
d O
utle
t1,
unsi
gne
d O
utle
t2);
PR
EF
IX
vo
id W
INA
PI
EX
PO
RT
Pat
chS
wap
Inle
ts(P
_P
AT
CH
dw
pP
atch
, u
nsig
ned
Inle
t1,
uns
igne
d In
let2
);
PR
EF
IX
P_
BA
SE
SH
ELL
WIN
AP
I E
XP
OR
T P
atch
Get
Inle
t(P
_P
AT
CH
dw
pP
atch
, u
nsig
ned
So
cket
Num
);P
RE
FIX
P
_B
AS
ES
HE
LL W
INA
PI
EX
PO
RT
Pat
chG
etO
utle
t(P
_P
AT
CH
dw
pP
atch
, u
nsig
ned
So
cket
Num
);
PR
EF
IX
uns
igne
d W
INA
PI
EX
PO
RT
Pat
chO
utle
tGet
Out
letN
um
ber(
P_B
AS
ES
HE
LL d
wpP
ort
);P
RE
FIX
u
nsig
ned
WIN
AP
I E
XP
OR
T P
atch
Inle
tGet
Inle
tNu
mbe
r(P
_BA
SE
SH
ELL
dw
pPo
rt);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* C
alc
ula
te C
lass
acc
ess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Cal
cula
teG
etO
pera
tor(
P_B
AS
ES
HE
LL d
wpC
alc
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
alcu
late
Get
Res
etO
per
ato
r(P
_B
AS
ES
HE
LL d
wp
Ca
lc);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Cal
cula
teG
etLV
alu
e(P
_BA
SE
SH
ELL
dw
pCa
lc);
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 60
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Cal
cula
teG
etR
eset
LVa
lue(
P_
BA
SE
SH
ELL
dw
pC
alc
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
alcu
late
Get
RV
alu
e(P
_BA
SE
SH
ELL
dw
pCa
lc);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Cal
cula
teG
etR
eset
RV
alu
e(P
_B
AS
ES
HE
LL d
wp
Ca
lc);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T C
alcu
late
Get
RT
rigg
erC
alc
(P_
BA
SE
SH
ELL
dw
pC
alc
);P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Cal
cula
teG
etN
um
Ope
rato
rs(v
oid
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Cal
cula
teG
etO
pera
torT
ype(
uns
ign
ed I
nde
x, L
PS
TR
Buf
);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
alcu
late
Set
Ope
rato
r(P
_BA
SE
SH
ELL
dw
pCa
lc,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Cal
cula
teS
etR
eset
Ope
rato
r(P
_BA
SE
SH
ELL
dw
pCa
lc,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Cal
cula
teS
etLV
alu
e(P
_BA
SE
SH
ELL
dw
pCa
lc,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Cal
cula
teS
etR
eset
LVal
ue(
P_
BA
SE
SH
ELL
dw
pC
alc
, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
alcu
late
Set
RV
alue
(P_B
AS
ES
HE
LL d
wpC
alc
, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
alcu
late
Set
Res
etR
Val
ue(P
_B
AS
ES
HE
LL d
wp
Ca
lc,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Cal
cula
teS
etR
Trig
ger
Ca
lc(P
_B
AS
ES
HE
LL d
wp
Ca
lc,
boo
l Va
lue)
;
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
alcu
late
Ca
lcu
late
Va
lues
(P_B
AS
ES
HE
LL d
wpC
alc
);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* C
oun
ter
Cla
ss a
cces
s fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
ou
nter
Get
Co
unt
(P_
BA
SE
SH
ELL
dw
pC
oun
t);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Co
unte
rGet
Res
etC
oun
t(P
_BA
SE
SH
ELL
dw
pCo
unt)
;P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
ou
nter
Get
Ste
pSiz
e(P
_B
AS
ES
HE
LL d
wp
Co
unt)
;P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
ou
nter
Get
Res
etS
tep
Siz
e(P
_B
AS
ES
HE
LL d
wp
Co
unt)
;P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
ou
nter
Get
Up
per
Lim
it(P
_B
AS
ES
HE
LL d
wp
Co
unt)
;P
RE
FIX
int
WIN
AP
I E
XP
OR
T C
ou
nter
Get
Res
etU
pp
erL
imit(
P_
BA
SE
SH
ELL
dw
pC
oun
t);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Co
unte
rGet
Low
erLi
mit(
P_B
AS
ES
HE
LL d
wpC
oun
t);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Co
unt
erG
etR
eset
Low
erLi
mit(
P_
BA
SE
SH
ELL
dw
pC
oun
t);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T C
ou
nter
Get
Dire
ctio
n(P
_B
AS
ES
HE
LL d
wp
Co
unt)
;
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 61
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T C
ou
nter
Get
Res
etD
irect
ion(
P_
BA
SE
SH
ELL
dw
pC
oun
t);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T C
ou
nter
Get
BiD
irect
iona
l(P_
BA
SE
SH
ELL
dw
pC
oun
t);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T C
oun
terG
etR
eset
BiD
irect
iona
l(P_B
AS
ES
HE
LL d
wpC
oun
t);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
ou
nter
Set
Co
unt
(P_
BA
SE
SH
ELL
dw
pC
oun
t, in
t V
alue
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unte
rSet
Res
etC
oun
t(P
_BA
SE
SH
ELL
dw
pCo
unt,
int
Val
ue);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
ou
nter
Set
Ste
pSiz
e(P
_B
AS
ES
HE
LL d
wp
Co
unt,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unt
erS
etR
eset
Ste
pS
ize(
P_
BA
SE
SH
ELL
dw
pC
oun
t, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
oun
terS
etU
pper
Lim
it(P
_BA
SE
SH
ELL
dw
pCo
unt,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unte
rSet
Res
etU
pper
Lim
it(P
_BA
SE
SH
ELL
dw
pCo
unt,
int
Val
ue);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
oun
terS
etLo
wer
Lim
it(P
_BA
SE
SH
ELL
dw
pCo
unt,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unt
erS
etR
eset
Low
erLi
mit(
P_
BA
SE
SH
ELL
dw
pC
oun
t, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T C
ou
nter
Set
Dire
ctio
n(P
_B
AS
ES
HE
LL d
wp
Co
unt,
boo
l Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unt
erS
etR
eset
Dire
ctio
n(P
_B
AS
ES
HE
LL d
wp
Co
unt,
boo
l Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unt
erS
etB
iDire
ctio
nal(P
_B
AS
ES
HE
LL d
wp
Co
unt,
boo
l Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Co
unt
erS
etR
eset
BiD
irect
iona
l(P_
BA
SE
SH
ELL
dw
pC
oun
t, b
ool V
alu
e);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* M
etro
Cla
ss a
cces
s fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Met
roG
etIn
terv
al(P
_BA
SE
SH
ELL
dw
pMet
ro);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T M
etro
Get
Res
etIn
terv
al(P
_B
AS
ES
HE
LL d
wp
Met
ro);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T M
etro
IsR
unni
ng(P
_BA
SE
SH
ELL
dw
pMet
ro);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T M
etro
Act
ivat
e(P
_B
AS
ES
HE
LL d
wp
Met
ro, b
ool G
o);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T M
etro
Set
Inte
rval
(P_B
AS
ES
HE
LL d
wpM
etro
, uns
igne
d V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T M
etro
Set
Res
etIn
terv
al(P
_B
AS
ES
HE
LL d
wp
Met
ro, u
nsig
ned
Va
lue)
;
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* D
ela
y C
lass
acc
ess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 62
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T D
ela
yGet
Inte
rva
l(P_B
AS
ES
HE
LL d
wpD
ela
y);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T D
ela
yGet
Res
etIn
terv
al(P
_B
AS
ES
HE
LL d
wp
De
lay)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Del
ayS
etIn
terv
al(P
_B
AS
ES
HE
LL d
wpD
ela
y, u
nsig
ned
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Del
ayS
etR
eset
Inte
rva
l(P_
BA
SE
SH
ELL
dw
pD
ela
y, u
nsi
gne
d V
alu
e);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* S
witc
h C
lass
acc
ess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
witc
hGet
Po
sitio
n(P
_B
AS
ES
HE
LL d
wp
Sw
itch)
;P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Sw
itchG
etR
eset
Po
sitio
n(P
_B
AS
ES
HE
LL d
wp
Sw
itch)
;P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Sw
itchG
etN
um
Co
ntac
ts(P
_B
AS
ES
HE
LL d
wp
Sw
itch)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Sw
itchS
etP
osi
tion(
P_
BA
SE
SH
ELL
dw
pS
witc
h, u
nsig
ned
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Sw
itchS
etR
eset
Po
sitio
n(P
_B
AS
ES
HE
LL d
wp
Sw
itch,
uns
igne
d V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
witc
hRe
size
(P_
BA
SE
SH
ELL
dw
pS
witc
h, u
nsi
gne
d V
alu
e);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* S
tdM
idiO
ut C
lass
acc
ess
fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Std
Mid
iOu
tGet
Sta
tus(
P_
BA
SE
SH
ELL
dw
pM
idi);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiO
utG
etR
eset
Sta
tus(
P_B
AS
ES
HE
LL d
wpM
idi);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiO
utG
etC
hann
el(P
_BA
SE
SH
ELL
dw
pMid
i);P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Std
Mid
iOut
Get
Res
etC
hann
el(P
_BA
SE
SH
ELL
dw
pMid
i);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiO
utG
etD
ata1
(P_B
AS
ES
HE
LL d
wpM
idi);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiO
utG
etR
eset
Dat
a1(P
_BA
SE
SH
ELL
dw
pMid
i);P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Std
Mid
iOut
Get
Dat
a2(P
_BA
SE
SH
ELL
dw
pMid
i);P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Std
Mid
iOut
Get
Res
etD
ata2
(P_B
AS
ES
HE
LL d
wpM
idi);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiO
utG
etM
ono
(P_
BA
SE
SH
ELL
dw
pM
idi)
;P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Std
Mid
iOut
Get
Res
etM
ono
(P_B
AS
ES
HE
LL d
wpM
idi)
;P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Std
Mid
iOut
Get
Dat
a1T
rigge
r(P
_BA
SE
SH
ELL
dw
pMid
i);P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Std
Mid
iOut
Get
Res
etD
ata1
Trig
ger(
P_B
AS
ES
HE
LL d
wpM
idi)
;
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 63
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiO
utG
etD
evic
e(P
_B
AS
ES
HE
LL d
wp
Mid
i);P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Std
Mid
iOu
tSet
Sta
tus(
P_
BA
SE
SH
ELL
dw
pM
idi,
uns
igne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etR
eset
Sta
tus(
P_B
AS
ES
HE
LL d
wpM
idi,
uns
igne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etC
han
ne
l(P_
BA
SE
SH
ELL
dw
pM
idi,
uns
igne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etR
eset
Cha
nn
el(P
_B
AS
ES
HE
LL d
wp
Mid
i, u
nsig
ned
Va
lue)
;P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Std
Mid
iOut
Set
Dat
a1(P
_BA
SE
SH
ELL
dw
pMid
i, u
nsig
ned
Va
lue)
;P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Std
Mid
iOu
tSet
Res
etD
ata1
(P_
BA
SE
SH
ELL
dw
pM
idi,
uns
igne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etD
ata2
(P_B
AS
ES
HE
LL d
wpM
idi,
uns
igne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etR
eset
Dat
a2(P
_B
AS
ES
HE
LL d
wp
Mid
i, u
nsig
ned
Val
ue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Std
Mid
iOut
Set
Dat
a1T
rigge
r(P
_BA
SE
SH
ELL
dw
pMid
i, bo
ol V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etR
eset
Dat
a1T
rigge
r(P
_BA
SE
SH
ELL
dw
pMid
i, bo
ol V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
etM
ono
(P_
BA
SE
SH
ELL
dw
pM
idi,
boo
l Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Std
Mid
iOut
Set
Res
etM
ono
(P_B
AS
ES
HE
LL d
wpM
idi,
boo
l Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Std
Mid
iOu
tSet
Dev
ice(
P_
BA
SE
SH
ELL
dw
pM
idi,
uns
igne
d V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiO
utS
end(
P_B
AS
ES
HE
LL d
wpM
idi);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiO
utF
lush
De
vice
(P_
BA
SE
SH
ELL
dw
pM
idi)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Std
Mid
iOu
tRes
etD
evic
e(P
_B
AS
ES
HE
LL d
wp
Mid
i);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiO
utA
ddD
evi
ce(D
WO
RD
Ha
ndle
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Std
Mid
iOut
Cle
arD
evic
es(v
oid
);/*
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
Mid
i In
Fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***/
//th
ese
are
the
filte
rsP
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Std
Mid
iInG
etS
tatu
s(P
_BA
SE
SH
ELL
dw
pMid
i);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiIn
Get
Cha
nne
l(P_
BA
SE
SH
ELL
dw
pM
idi);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Std
Mid
iInG
etD
ata1
(P_
BA
SE
SH
ELL
dw
pM
idi);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Std
Mid
iInG
etD
ata2
(P_
BA
SE
SH
ELL
dw
pM
idi);
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T S
tdM
idiIn
Get
De
vice
(P_
BA
SE
SH
ELL
dw
pM
idi)
;
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 64
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiIn
Get
Filt
ered
(P_B
AS
ES
HE
LL d
wpM
idi);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiIn
Get
Not
eOnZ
ero
Filt
er(P
_BA
SE
SH
ELL
dw
pMid
i);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiIn
Set
Sta
tus(
P_B
AS
ES
HE
LL d
wpM
idi,
unsi
gne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiIn
Set
Cha
nne
l(P_
BA
SE
SH
ELL
dw
pM
idi,
uns
igne
d V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiIn
Set
Dev
ice(
P_
BA
SE
SH
ELL
dw
pM
idi,
uns
igne
d V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiIn
Set
Dat
a1(P
_B
AS
ES
HE
LL d
wp
Mid
i, in
t V
alu
e);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
tdM
idiIn
Set
Dat
a2(P
_B
AS
ES
HE
LL d
wp
Mid
i, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiIn
Pro
cess
Mid
iIn(u
nsig
ned
wD
evi
ce,
LPM
IDIE
VE
NT
lpE
vent
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Std
Mid
iInS
etF
ilter
ed(P
_BA
SE
SH
ELL
dw
pMid
i, bo
ol V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
tdM
idiIn
Set
No
teO
nZer
oF
ilter
(P_B
AS
ES
HE
LL d
wpM
idi,
boo
l Va
lue)
;/*
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**
Flip
Flo
p C
lass
acc
ess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T F
lipF
lopG
etS
tate
(P_
BA
SE
SH
ELL
dw
pF
lipF
lop)
;P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Flip
Flo
pGet
Res
etS
tate
(P_
BA
SE
SH
ELL
dw
pF
lipF
lop)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Flip
Flo
pSet
Sta
te(P
_B
AS
ES
HE
LL d
wp
Flip
Flo
p, b
oo
l Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Flip
Flo
pSet
Res
etS
tate
(P_
BA
SE
SH
ELL
dw
pF
lipF
lop,
bo
ol V
alu
e);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* T
ogg
le C
lass
acc
ess
func
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T T
og
gle
Get
Sta
te(P
_B
AS
ES
HE
LL d
wp
To
gg
le);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T T
ogg
leG
etR
eset
Sta
te(P
_BA
SE
SH
ELL
dw
pTo
ggle
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
To
gg
leS
etS
tate
(P_
BA
SE
SH
ELL
dw
pT
og
gle
, bo
ol V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
ogg
leS
etR
eset
Sta
te(P
_BA
SE
SH
ELL
dw
pTo
ggle
, bo
ol V
alu
e);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* M
essa
geS
tore
Cla
ss a
cces
s fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Mes
sage
Sto
reG
etM
essa
ge(P
_BA
SE
SH
ELL
dw
pSto
re,
LPS
TR
Mes
sage
);
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 65
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T M
essa
geS
tore
Get
Res
etM
essa
ge(P
_BA
SE
SH
ELL
dw
pSto
re,
LPS
TR
Mes
sage
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Mes
sage
Sto
reS
etM
essa
ge(P
_BA
SE
SH
ELL
dw
pSto
re,
LPS
TR
Mes
sage
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Mes
sage
Sto
reS
etR
eset
Mes
sage
(P_B
AS
ES
HE
LL d
wpS
tore
, LP
ST
R M
essa
ge);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T M
essa
geS
tore
Sen
d(P
_B
AS
ES
HE
LL d
wp
Sto
re);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* D
isp
lay
Cla
ss a
cce
ss fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Dis
pla
yGet
Mes
sag
e(P
_B
AS
ES
HE
LL d
wp
Dis
pla
y, L
PS
TR
Mes
sage
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Dis
pla
ySet
Dis
pla
yWin
dow
(P_B
AS
ES
HE
LL d
wpD
isp
lay,
HW
ND
Dis
pla
yWin
dow
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Dis
pla
yCle
arD
isp
layW
indo
w(P
_BA
SE
SH
ELL
dw
pDis
pla
y, H
WN
D D
isp
layW
indo
w);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T D
isp
layG
etLa
stM
essa
ge(P
_B
AS
ES
HE
LL d
wp
Dis
pla
y, L
PS
TR
Mes
sage
);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
* S
elec
tor
Cla
ss a
cce
ss fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
int
WIN
AP
I E
XP
OR
T S
elec
torG
etU
pper
Val
ue(P
_BA
SE
SH
ELL
dw
pSe
lect
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T S
elec
torG
etR
eset
Upp
erV
alue
(P_B
AS
ES
HE
LL d
wpS
ele
ct);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Sel
ecto
rGet
Low
erV
alu
e(P
_B
AS
ES
HE
LL d
wp
Se
lect
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T S
elec
torG
etR
eset
Low
erV
alu
e(P
_BA
SE
SH
ELL
dw
pSe
lect
);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
elec
torS
etU
pper
Val
ue(P
_BA
SE
SH
ELL
dw
pSe
lect
, int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Sel
ecto
rSet
Res
etU
pper
Val
ue(P
_BA
SE
SH
ELL
dw
pSe
lect
, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
elec
torS
etLo
wer
Val
ue(
P_
BA
SE
SH
ELL
dw
pS
ele
ct,
int
Val
ue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Sel
ecto
rSet
Res
etLo
wer
Val
ue(
P_B
AS
ES
HE
LL d
wpS
ele
ct,
int
Va
lue)
;/*
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
Tab
le F
unc
tions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Tab
leG
etS
ize(
P_B
AS
ES
HE
LL d
wpT
able
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T T
able
Get
Va
lue(
P_B
AS
ES
HE
LL d
wpT
able
, un
sig
ned
Inde
x);
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 66
PR
EF
IX u
nsig
ned
WIN
AP
I E
XP
OR
T T
able
Get
Nu
mT
able
s();
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Get
Tab
leN
am
e(u
nsig
ned
Ind
ex,
LP
ST
R B
uf);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Cha
ngeT
able
(P_
BA
SE
SH
ELL
dw
pT
able
, LP
ST
R N
ewN
am
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Re
size
(P_
BA
SE
SH
ELL
dw
pT
able
, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Set
Po
int(
P_
BA
SE
SH
ELL
dw
pT
able
, u
nsi
gne
d I
nde
x, in
t V
alu
e, b
oo
l Ins
ert)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Tab
leR
em
ove
Po
int(
P_B
AS
ES
HE
LL d
wpT
able
, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Se
nd(P
_B
AS
ES
HE
LL d
wp
Tab
le,
int
Ind
ex);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Inse
rt(P
_B
AS
ES
HE
LL d
wp
Tab
le,
int
Val
ue);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
able
Set
Mo
de(P
_BA
SE
SH
ELL
dw
pTab
le,
boo
l Va
lue)
;P
RE
FIX
P_
BA
SE
SH
ELL
WIN
AP
I E
XP
OR
T T
able
Load
Tab
le(L
PS
TR
File
Na
me,
P_
PA
TC
H d
wp
Par
ent)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Tab
leS
ave
Ta
ble(
P_B
AS
ES
HE
LL d
wpT
able
);P
RE
FIX
bo
ol W
INA
PI
EX
PO
RT
Tab
leG
etM
odi
fied(
P_B
AS
ES
HE
LL d
wpT
able
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T T
able
Get
Hig
hest
Va
lue(
P_B
AS
ES
HE
LL d
wpT
able
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T T
able
Get
Low
estV
alue
(P_
BA
SE
SH
ELL
dw
pT
abl
e);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
*N
um
ber
Sto
re F
unct
ions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
*/P
RE
FIX
int
WIN
AP
I E
XP
OR
T N
umbe
rSto
reG
etN
umbe
r(P
_BA
SE
SH
ELL
dw
pSto
re);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Num
berS
tore
Get
Res
etN
umbe
r(P
_BA
SE
SH
ELL
dw
pSto
re);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Num
berS
tore
Get
Upp
erL
imit(
P_B
AS
ES
HE
LL d
wpS
tore
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T N
umbe
rSto
reG
etLo
wer
Lim
it(P
_BA
SE
SH
ELL
dw
pSto
re);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T N
umbe
rSto
reS
etN
umbe
r(P
_BA
SE
SH
ELL
dw
pSto
re,
int
Val
ue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Num
berS
tore
Set
Res
etN
umbe
r(P
_BA
SE
SH
ELL
dw
pSto
re, i
nt V
alue
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Num
berS
tore
Set
Up
per
Lim
it(P
_B
AS
ES
HE
LL d
wp
Sto
re, i
nt V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T N
umbe
rSto
reS
etLo
wer
Lim
it(P
_BA
SE
SH
ELL
dw
pSto
re,
int
Val
ue);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***
Trig
ger
Fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**/
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 67
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T T
rigge
rSet
Win
dow
(P_B
AS
ES
HE
LL d
wpT
rigg
er,
HW
ND
Dis
pla
yWin
dow
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Trig
gerC
lear
Win
dow
(P_B
AS
ES
HE
LL d
wpT
rigge
r, H
WN
D D
isp
layW
indo
w);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**R
and
om
Fu
nctio
ns**
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
/
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Ran
dom
Ge
nGet
Nu
mbe
r(P
_BA
SE
SH
ELL
dw
pRan
d);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Ran
dom
Ge
nGet
Res
etN
um
ber(
P_B
AS
ES
HE
LL d
wpR
and
);P
RE
FIX
int
WIN
AP
I E
XP
OR
T R
ando
mG
enG
etU
pper
Lim
it(P
_BA
SE
SH
ELL
dw
pRa
nd);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Ran
dom
Ge
nGet
Res
etU
pper
Lim
it(P
_BA
SE
SH
ELL
dw
pRa
nd);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T R
ando
mG
enS
etN
um
ber(
P_B
AS
ES
HE
LL d
wpR
and
, in
t V
alu
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T R
ando
mG
enS
etR
eset
Nu
mbe
r(P
_BA
SE
SH
ELL
dw
pRa
nd,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Ran
dom
Ge
nSet
Upp
erL
imit(
P_B
AS
ES
HE
LL d
wpR
and,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Ran
dom
Ge
nSet
Res
etU
pper
Lim
it(P
_BA
SE
SH
ELL
dw
pRa
nd,
int
Va
lue)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Ran
dom
Ge
nGe
nera
te(P
_B
AS
ES
HE
LL d
wp
Ra
nd);
/***
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
**
Seq
uenc
er F
unct
ions
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
***/
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rGet
File
Na
me(
P_
BA
SE
SH
ELL
dw
pS
eq,
LPS
TR
File
Nam
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rGet
Res
etF
ileN
am
e(P
_B
AS
ES
HE
LL d
wp
Seq
, LP
ST
R F
ileN
am
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rGet
Op
enF
ileN
am
e(P
_B
AS
ES
HE
LL d
wp
Seq
, LP
ST
R F
ileN
am
e);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rSet
File
Na
me(
P_
BA
SE
SH
ELL
dw
pS
eq,
LPS
TR
File
Na
me)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Seq
uen
cerS
etR
eset
File
Na
me(
P_
BA
SE
SH
ELL
dw
pS
eq,
LPS
TR
File
Na
me)
;P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Seq
uenc
erP
lay(
P_B
AS
ES
HE
LL d
wpS
eq);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rSto
p(P
_B
AS
ES
HE
LL d
wp
Seq
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Seq
uen
cerS
tart
(P_
BA
SE
SH
ELL
dw
pS
eq);
App
endi
x A
to
Alg
orith
mic
Com
pose
r, p
age 68
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rEnd
(P_
BA
SE
SH
ELL
dw
pS
eq);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Seq
uen
cerN
um
Tra
cks(
P_
BA
SE
SH
ELL
dw
pS
eq);
PR
EF
IX in
t W
INA
PI
EX
PO
RT
Seq
uenc
erR
eso
lutio
n(P
_BA
SE
SH
ELL
dw
pSeq
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Seq
uenc
erS
etT
empo
(P_B
AS
ES
HE
LL d
wpS
eq,
unsi
gne
d N
ewT
em
po);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rSet
Res
etT
empo
(P_
BA
SE
SH
ELL
dw
pS
eq,
uns
igne
d N
ewT
em
po
);P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Seq
uenc
erG
etT
em
po(P
_BA
SE
SH
ELL
dw
pSeq
);P
RE
FIX
uns
igne
d W
INA
PI
EX
PO
RT
Seq
uen
cerG
etR
eset
Te
mpo
(P_
BA
SE
SH
ELL
dw
pS
eq);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
equ
ence
rIsP
layi
ng
(P_
BA
SE
SH
ELL
dw
pS
eq);
PR
EF
IX D
WO
RD
WIN
AP
I E
XP
OR
T S
equ
ence
rNu
mE
vent
s(P
_B
AS
ES
HE
LL d
wp
Seq
);P
RE
FIX
DW
OR
D W
INA
PI
EX
PO
RT
Seq
uen
cerC
urre
ntP
os(
P_
BA
SE
SH
ELL
dw
pS
eq);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
equ
ence
rSet
Po
sitio
n(P
_B
AS
ES
HE
LL d
wp
Seq
, D
WO
RD
New
Po
s);
PR
EF
IX b
oo
l WIN
AP
I E
XP
OR
T S
eque
ncer
IsO
pen(
P_B
AS
ES
HE
LL d
wpS
eq);
PR
EF
IX v
oid
WIN
AP
I E
XP
OR
T S
eque
ncer
Ope
n(P
_BA
SE
SH
ELL
dw
pSeq
);P
RE
FIX
vo
id W
INA
PI
EX
PO
RT
Seq
uen
cerC
lose
(P_
BA
SE
SH
ELL
dw
pS
eq);
#ifd
ef _
_cp
lusp
lus
}
//
end
C d
ecla
ratio
ns fo
r C
++
#end
if
#end
if